api metadata: Allow typed container information in api functions

Adapt gendeclarations.lua/msgpack-gen.lua to allow the `ArrayOf(...)` and
`DictionaryOf(...)` types in function headers. These are simple macros that
expand to Array and Dictionary respectively, but the information is kept in the
metadata object, which is useful for building clients in statically typed
languages.
This commit is contained in:
Thiago de Arruda 2014-09-12 11:24:01 -03:00
parent cd2e46c078
commit 545acf2024
7 changed files with 59 additions and 26 deletions

View File

@ -59,9 +59,16 @@ local right_word = concat(
raw_word,
neg_look_ahead(aw)
)
local word = concat(
neg_look_behind(aw),
right_word
local word = branch(
concat(
branch(lit('ArrayOf('), lit('DictionaryOf(')), -- typed container macro
one_or_more(any_character - lit(')')),
lit(')')
),
concat(
neg_look_behind(aw),
right_word
)
)
local spaces = any_amount(branch(
s,
@ -204,7 +211,7 @@ while init ~= nil do
declaration = declaration:gsub('\n', ' ')
declaration = declaration:gsub('%s+', ' ')
declaration = declaration:gsub(' ?%( ?', '(')
declaration = declaration:gsub(' ?%) ?', ')')
-- declaration = declaration:gsub(' ?%) ?', ')')
declaration = declaration:gsub(' ?, ?', ', ')
declaration = declaration:gsub(' ?(%*+) ?', ' %1')
declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1')

View File

@ -16,7 +16,12 @@ ws = S(' \t') + nl
fill = ws ^ 0
c_comment = P('//') * (not_nl ^ 0)
c_preproc = P('#') * (not_nl ^ 0)
c_id = letter * (alpha ^ 0)
typed_container =
(P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')')
c_id = (
typed_container +
(letter * (alpha ^ 0))
)
c_void = P('void')
c_param_type = (
((P('Error') * fill * P('*') * fill) * Cc('error')) +
@ -90,6 +95,7 @@ output:write([[
#include "nvim/os/msgpack_rpc.h"
#include "nvim/os/msgpack_rpc_helpers.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h"
]])
for i = 1, #headers do
@ -132,6 +138,18 @@ void msgpack_rpc_init_function_metadata(Dictionary *metadata)
]])
local function real_type(type)
local rv = type
if typed_container:match(rv) then
if rv:match('Array') then
rv = 'Array'
else
rv = 'Dictionary'
end
end
return rv
end
-- start the handler functions. Visit each function metadata to build the
-- handler function with code generated for validating arguments and calling to
-- the real API.
@ -146,7 +164,7 @@ for i = 1, #functions do
for j = 1, #fn.parameters do
local param = fn.parameters[j]
local converted = 'arg_'..j
output:write('\n '..param[1]..' '..converted..' api_init_'..string.lower(param[1])..';')
output:write('\n '..param[1]..' '..converted..' api_init_'..string.lower(real_type(param[1]))..';')
end
output:write('\n')
output:write('\n if (req->via.array.ptr[3].via.array.size != '..#fn.parameters..') {')
@ -161,7 +179,7 @@ for i = 1, #functions do
param = fn.parameters[j]
arg = '(req->via.array.ptr[3].via.array.ptr + '..(j - 1)..')'
converted = 'arg_'..j
convert_arg = 'msgpack_rpc_to_'..string.lower(param[1])
convert_arg = 'msgpack_rpc_to_'..real_type(param[1]):lower()
output:write('\n if (!'..convert_arg..'('..arg..', &'..converted..')) {')
output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");')
output:write('\n error->set = true;')
@ -208,7 +226,7 @@ for i = 1, #functions do
end
if fn.return_type ~= 'void' then
output:write('\n Object ret = '..string.upper(fn.return_type)..'_OBJ(rv);')
output:write('\n Object ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);')
end
-- Now generate the cleanup label for freeing memory allocated for the
-- arguments
@ -216,7 +234,7 @@ for i = 1, #functions do
for j = 1, #fn.parameters do
local param = fn.parameters[j]
output:write('\n api_free_'..string.lower(param[1])..'(arg_'..j..');')
output:write('\n api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');')
end
if fn.return_type ~= 'void' then
output:write('\n return ret;\n}\n\n');

View File

@ -95,12 +95,12 @@ void buffer_del_line(Buffer buffer, Integer index, Error *err)
/// @param include_end True if the slice includes the `end` parameter
/// @param[out] err Details of an error that may have occurred
/// @return An array of lines
Array buffer_get_slice(Buffer buffer,
Integer start,
Integer end,
Boolean include_start,
Boolean include_end,
Error *err)
ArrayOf(String) buffer_get_slice(Buffer buffer,
Integer start,
Integer end,
Boolean include_start,
Boolean include_end,
Error *err)
{
Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);
@ -161,7 +161,7 @@ void buffer_set_slice(Buffer buffer,
Integer end,
Boolean include_start,
Boolean include_end,
Array replacement,
ArrayOf(String) replacement,
Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@ -436,7 +436,10 @@ Boolean buffer_is_valid(Buffer buffer)
/// to the end of the buffer.
/// @param lines An array of lines
/// @param[out] err Details of an error that may have occurred
void buffer_insert(Buffer buffer, Integer lnum, Array lines, Error *err)
void buffer_insert(Buffer buffer,
Integer lnum,
ArrayOf(String) lines,
Error *err)
{
buffer_set_slice(buffer, lnum, lnum, false, true, lines, err);
}
@ -447,7 +450,7 @@ void buffer_insert(Buffer buffer, Integer lnum, Array lines, Error *err)
/// @param name The mark's name
/// @param[out] err Details of an error that may have occurred
/// @return The (row, col) tuple
Array buffer_get_mark(Buffer buffer, String name, Error *err)
ArrayOf(Integer, 2) buffer_get_mark(Buffer buffer, String name, Error *err)
{
Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);

View File

@ -10,6 +10,11 @@
#define OBJECT_INIT { .type = kObjectTypeNil }
#define REMOTE_TYPE(type) typedef uint64_t type
#ifdef INCLUDE_GENERATED_DECLARATIONS
#define ArrayOf(...) Array
#define DictionaryOf(...) Dictionary
#endif
// Basic types
typedef struct {
char msg[256];

View File

@ -13,7 +13,7 @@
/// @param tabpage The tabpage
/// @param[out] err Details of an error that may have occurred
/// @return The number of windows in `tabpage`
Array tabpage_get_windows(Tabpage tabpage, Error *err)
ArrayOf(Window) tabpage_get_windows(Tabpage tabpage, Error *err)
{
Array rv = ARRAY_DICT_INIT;
tabpage_T *tab = find_tab_by_handle(tabpage, err);

View File

@ -149,7 +149,7 @@ Integer vim_strwidth(String str, Error *err)
/// Returns a list of paths contained in 'runtimepath'
///
/// @return The list of paths
Array vim_list_runtime_paths(void)
ArrayOf(String) vim_list_runtime_paths(void)
{
Array rv = ARRAY_DICT_INIT;
uint8_t *rtp = p_rtp;
@ -321,7 +321,7 @@ void vim_report_error(String str)
/// Gets the current list of buffer handles
///
/// @return The number of buffers
Array vim_get_buffers(void)
ArrayOf(Buffer) vim_get_buffers(void)
{
Array rv = ARRAY_DICT_INIT;
buf_T *b = firstbuf;
@ -381,7 +381,7 @@ void vim_set_current_buffer(Buffer buffer, Error *err)
/// Gets the current list of window handles
///
/// @return The number of windows
Array vim_get_windows(void)
ArrayOf(Window) vim_get_windows(void)
{
Array rv = ARRAY_DICT_INIT;
tabpage_T *tp;
@ -437,7 +437,7 @@ void vim_set_current_window(Window window, Error *err)
/// Gets the current list of tabpage handles
///
/// @return The number of tab pages
Array vim_get_tabpages(void)
ArrayOf(Tabpage) vim_get_tabpages(void)
{
Array rv = ARRAY_DICT_INIT;
tabpage_T *tp = first_tabpage;

View File

@ -33,7 +33,7 @@ Buffer window_get_buffer(Window window, Error *err)
/// @param window The window handle
/// @param[out] err Details of an error that may have occurred
/// @return the (row, col) tuple
Array window_get_cursor(Window window, Error *err)
ArrayOf(Integer, 2) window_get_cursor(Window window, Error *err)
{
Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err);
@ -51,7 +51,7 @@ Array window_get_cursor(Window window, Error *err)
/// @param window The window handle
/// @param pos the (row, col) tuple representing the new position
/// @param[out] err Details of an error that may have occurred
void window_set_cursor(Window window, Array pos, Error *err)
void window_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@ -247,7 +247,7 @@ void window_set_option(Window window, String name, Object value, Error *err)
/// @param window The window handle
/// @param[out] err Details of an error that may have occurred
/// @return The (row, col) tuple with the window position
Array window_get_position(Window window, Error *err)
ArrayOf(Integer, 2) window_get_position(Window window, Error *err)
{
Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err);