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, raw_word,
neg_look_ahead(aw) neg_look_ahead(aw)
) )
local word = concat( local word = branch(
neg_look_behind(aw), concat(
right_word 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( local spaces = any_amount(branch(
s, s,
@ -204,7 +211,7 @@ while init ~= nil do
declaration = declaration:gsub('\n', ' ') declaration = declaration:gsub('\n', ' ')
declaration = declaration:gsub('%s+', ' ') declaration = declaration:gsub('%s+', ' ')
declaration = declaration:gsub(' ?%( ?', '(') declaration = declaration:gsub(' ?%( ?', '(')
declaration = declaration:gsub(' ?%) ?', ')') -- declaration = declaration:gsub(' ?%) ?', ')')
declaration = declaration:gsub(' ?, ?', ', ') declaration = declaration:gsub(' ?, ?', ', ')
declaration = declaration:gsub(' ?(%*+) ?', ' %1') declaration = declaration:gsub(' ?(%*+) ?', ' %1')
declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1') declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1')

View File

@ -16,7 +16,12 @@ ws = S(' \t') + nl
fill = ws ^ 0 fill = ws ^ 0
c_comment = P('//') * (not_nl ^ 0) c_comment = P('//') * (not_nl ^ 0)
c_preproc = 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_void = P('void')
c_param_type = ( c_param_type = (
((P('Error') * fill * P('*') * fill) * Cc('error')) + ((P('Error') * fill * P('*') * fill) * Cc('error')) +
@ -90,6 +95,7 @@ output:write([[
#include "nvim/os/msgpack_rpc.h" #include "nvim/os/msgpack_rpc.h"
#include "nvim/os/msgpack_rpc_helpers.h" #include "nvim/os/msgpack_rpc_helpers.h"
#include "nvim/api/private/helpers.h" #include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h"
]]) ]])
for i = 1, #headers do 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 -- start the handler functions. Visit each function metadata to build the
-- handler function with code generated for validating arguments and calling to -- handler function with code generated for validating arguments and calling to
-- the real API. -- the real API.
@ -146,7 +164,7 @@ for i = 1, #functions do
for j = 1, #fn.parameters do for j = 1, #fn.parameters do
local param = fn.parameters[j] local param = fn.parameters[j]
local converted = 'arg_'..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 end
output:write('\n') output:write('\n')
output:write('\n if (req->via.array.ptr[3].via.array.size != '..#fn.parameters..') {') 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] param = fn.parameters[j]
arg = '(req->via.array.ptr[3].via.array.ptr + '..(j - 1)..')' arg = '(req->via.array.ptr[3].via.array.ptr + '..(j - 1)..')'
converted = 'arg_'..j 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 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 snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");')
output:write('\n error->set = true;') output:write('\n error->set = true;')
@ -208,7 +226,7 @@ for i = 1, #functions do
end end
if fn.return_type ~= 'void' then 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 end
-- Now generate the cleanup label for freeing memory allocated for the -- Now generate the cleanup label for freeing memory allocated for the
-- arguments -- arguments
@ -216,7 +234,7 @@ for i = 1, #functions do
for j = 1, #fn.parameters do for j = 1, #fn.parameters do
local param = fn.parameters[j] 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 end
if fn.return_type ~= 'void' then if fn.return_type ~= 'void' then
output:write('\n return ret;\n}\n\n'); 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 include_end True if the slice includes the `end` parameter
/// @param[out] err Details of an error that may have occurred /// @param[out] err Details of an error that may have occurred
/// @return An array of lines /// @return An array of lines
Array buffer_get_slice(Buffer buffer, ArrayOf(String) buffer_get_slice(Buffer buffer,
Integer start, Integer start,
Integer end, Integer end,
Boolean include_start, Boolean include_start,
Boolean include_end, Boolean include_end,
Error *err) Error *err)
{ {
Array rv = ARRAY_DICT_INIT; Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);
@ -161,7 +161,7 @@ void buffer_set_slice(Buffer buffer,
Integer end, Integer end,
Boolean include_start, Boolean include_start,
Boolean include_end, Boolean include_end,
Array replacement, ArrayOf(String) replacement,
Error *err) Error *err)
{ {
buf_T *buf = find_buffer_by_handle(buffer, 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. /// to the end of the buffer.
/// @param lines An array of lines /// @param lines An array of lines
/// @param[out] err Details of an error that may have occurred /// @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); 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 name The mark's name
/// @param[out] err Details of an error that may have occurred /// @param[out] err Details of an error that may have occurred
/// @return The (row, col) tuple /// @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; Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err); buf_T *buf = find_buffer_by_handle(buffer, err);

View File

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

View File

@ -13,7 +13,7 @@
/// @param tabpage The tabpage /// @param tabpage The tabpage
/// @param[out] err Details of an error that may have occurred /// @param[out] err Details of an error that may have occurred
/// @return The number of windows in `tabpage` /// @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; Array rv = ARRAY_DICT_INIT;
tabpage_T *tab = find_tab_by_handle(tabpage, err); 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' /// Returns a list of paths contained in 'runtimepath'
/// ///
/// @return The list of paths /// @return The list of paths
Array vim_list_runtime_paths(void) ArrayOf(String) vim_list_runtime_paths(void)
{ {
Array rv = ARRAY_DICT_INIT; Array rv = ARRAY_DICT_INIT;
uint8_t *rtp = p_rtp; uint8_t *rtp = p_rtp;
@ -321,7 +321,7 @@ void vim_report_error(String str)
/// Gets the current list of buffer handles /// Gets the current list of buffer handles
/// ///
/// @return The number of buffers /// @return The number of buffers
Array vim_get_buffers(void) ArrayOf(Buffer) vim_get_buffers(void)
{ {
Array rv = ARRAY_DICT_INIT; Array rv = ARRAY_DICT_INIT;
buf_T *b = firstbuf; buf_T *b = firstbuf;
@ -381,7 +381,7 @@ void vim_set_current_buffer(Buffer buffer, Error *err)
/// Gets the current list of window handles /// Gets the current list of window handles
/// ///
/// @return The number of windows /// @return The number of windows
Array vim_get_windows(void) ArrayOf(Window) vim_get_windows(void)
{ {
Array rv = ARRAY_DICT_INIT; Array rv = ARRAY_DICT_INIT;
tabpage_T *tp; tabpage_T *tp;
@ -437,7 +437,7 @@ void vim_set_current_window(Window window, Error *err)
/// Gets the current list of tabpage handles /// Gets the current list of tabpage handles
/// ///
/// @return The number of tab pages /// @return The number of tab pages
Array vim_get_tabpages(void) ArrayOf(Tabpage) vim_get_tabpages(void)
{ {
Array rv = ARRAY_DICT_INIT; Array rv = ARRAY_DICT_INIT;
tabpage_T *tp = first_tabpage; 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 window The window handle
/// @param[out] err Details of an error that may have occurred /// @param[out] err Details of an error that may have occurred
/// @return the (row, col) tuple /// @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; Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err); 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 window The window handle
/// @param pos the (row, col) tuple representing the new position /// @param pos the (row, col) tuple representing the new position
/// @param[out] err Details of an error that may have occurred /// @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); 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 window The window handle
/// @param[out] err Details of an error that may have occurred /// @param[out] err Details of an error that may have occurred
/// @return The (row, col) tuple with the window position /// @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; Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err); win_T *win = find_window_by_handle(window, err);