From cd100963866b2c33a286cbf6aac8e42cd16fd248 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Mon, 29 Oct 2018 19:11:41 +0100 Subject: tree-sitter: initial tree-sitter support --- src/nvim/lua/executor.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index f51aa3c6d4..8b0140f794 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -31,6 +31,7 @@ #include "nvim/lua/executor.h" #include "nvim/lua/converter.h" +#include "nvim/lua/tree_sitter.h" #include "luv/luv.h" @@ -310,7 +311,11 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setfield(lstate, -2, "luv"); lua_pop(lstate, 3); + // internal vim._treesitter... API + nlua_add_treesitter(lstate); + lua_setglobal(lstate, "vim"); + return 0; } @@ -816,3 +821,40 @@ void ex_luafile(exarg_T *const eap) return; } } + +static int unsafe_ptr_to_ts_tree(lua_State *L) +{ + if (!lua_gettop(L)) { + return 0; + } + TSTree *const *ptr = lua_topointer(L,1); + tslua_push_tree(L, *ptr); + return 1; +} + +static int create_tslua_parser(lua_State *L) +{ + TSLanguage *tree_sitter_c(void), *tree_sitter_javascript(void); + + if (!lua_gettop(L)) { + return 0; + } + char *str = lua_tostring(L,1); + + TSLanguage *lang = tree_sitter_c(); + if (str && striequal(str, "javascript")) { + lang = tree_sitter_javascript(); + } + tslua_push_parser(L, lang); + return 1; +} + +static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + tslua_init(lstate); + lua_pushcfunction(lstate, unsafe_ptr_to_ts_tree); + lua_setfield(lstate, -2, "unsafe_ts_tree"); + + lua_pushcfunction(lstate, create_tslua_parser); + lua_setfield(lstate, -2, "ts_parser"); +} -- cgit From 0e0beef85e4d3932e0d49528d8474794f7b69b01 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Thu, 6 Jun 2019 12:20:07 +0200 Subject: tree-sitter: load parsers as .so files --- src/nvim/lua/executor.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 8b0140f794..1794cee8d8 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -834,16 +834,31 @@ static int unsafe_ptr_to_ts_tree(lua_State *L) static int create_tslua_parser(lua_State *L) { - TSLanguage *tree_sitter_c(void), *tree_sitter_javascript(void); - - if (!lua_gettop(L)) { + if (lua_gettop(L) < 2) { return 0; } - char *str = lua_tostring(L,1); + const char *path = lua_tostring(L,1); + const char *lang_name = lua_tostring(L,2); + + // TODO: unsafe! + char symbol_buf[128] = "tree_sitter_"; + STRCAT(symbol_buf, lang_name); + + // TODO: we should maybe keep the uv_lib_t around, and close them + // at exit, to keep LeakSanitizer happy. + uv_lib_t lib; + if (uv_dlopen(path, &lib)) { + return luaL_error(L, "uv_dlopen: %s", uv_dlerror(&lib)); + } + + TSLanguage *(*lang_parser)(void); + if (uv_dlsym(&lib, symbol_buf, (void **)&lang_parser)) { + return luaL_error(L, "uv_dlsym: %s", uv_dlerror(&lib)); + } - TSLanguage *lang = tree_sitter_c(); - if (str && striequal(str, "javascript")) { - lang = tree_sitter_javascript(); + TSLanguage *lang = lang_parser(); + if (lang == NULL) { + return luaL_error(L, "failed to load parser"); } tslua_push_parser(L, lang); return 1; -- cgit From 1e9e2451bef21ff705e677802d1b0980356f1f86 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 7 Jun 2019 18:19:59 +0200 Subject: tree-sitter: objectify API --- src/nvim/lua/executor.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 1794cee8d8..a6447ebb2b 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -822,16 +822,6 @@ void ex_luafile(exarg_T *const eap) } } -static int unsafe_ptr_to_ts_tree(lua_State *L) -{ - if (!lua_gettop(L)) { - return 0; - } - TSTree *const *ptr = lua_topointer(L,1); - tslua_push_tree(L, *ptr); - return 1; -} - static int create_tslua_parser(lua_State *L) { if (lua_gettop(L) < 2) { @@ -867,9 +857,7 @@ static int create_tslua_parser(lua_State *L) static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { tslua_init(lstate); - lua_pushcfunction(lstate, unsafe_ptr_to_ts_tree); - lua_setfield(lstate, -2, "unsafe_ts_tree"); lua_pushcfunction(lstate, create_tslua_parser); - lua_setfield(lstate, -2, "ts_parser"); + lua_setfield(lstate, -2, "_create_ts_parser"); } -- cgit From afba23099fccc929fd0319a9a965a7b727407c7a Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 8 Jun 2019 15:51:38 +0200 Subject: tree-sitter: support pre-registration of languages --- src/nvim/lua/executor.c | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index a6447ebb2b..ae53bfce6a 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -824,34 +824,13 @@ void ex_luafile(exarg_T *const eap) static int create_tslua_parser(lua_State *L) { - if (lua_gettop(L) < 2) { - return 0; + if (lua_gettop(L) < 1 || !lua_isstring(L, 1)) { + return luaL_error(L, "string expected"); } - const char *path = lua_tostring(L,1); - const char *lang_name = lua_tostring(L,2); - // TODO: unsafe! - char symbol_buf[128] = "tree_sitter_"; - STRCAT(symbol_buf, lang_name); + const char *lang_name = lua_tostring(L,1); - // TODO: we should maybe keep the uv_lib_t around, and close them - // at exit, to keep LeakSanitizer happy. - uv_lib_t lib; - if (uv_dlopen(path, &lib)) { - return luaL_error(L, "uv_dlopen: %s", uv_dlerror(&lib)); - } - - TSLanguage *(*lang_parser)(void); - if (uv_dlsym(&lib, symbol_buf, (void **)&lang_parser)) { - return luaL_error(L, "uv_dlsym: %s", uv_dlerror(&lib)); - } - - TSLanguage *lang = lang_parser(); - if (lang == NULL) { - return luaL_error(L, "failed to load parser"); - } - tslua_push_parser(L, lang); - return 1; + return tslua_push_parser(L, lang_name); } static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL @@ -860,4 +839,7 @@ static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_pushcfunction(lstate, create_tslua_parser); lua_setfield(lstate, -2, "_create_ts_parser"); + + lua_pushcfunction(lstate, ts_lua_register_lang); + lua_setfield(lstate, -2, "ts_add_language"); } -- cgit From 4ea5e63aa8c866b4fcc9d10f1a26078d2517f96a Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 9 Jun 2019 13:26:48 +0200 Subject: tree-sitter: add basic testing on ci build tree-sitter c parser on ci for testing purposes --- src/nvim/lua/executor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index ae53bfce6a..23c4fcabbc 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -841,5 +841,5 @@ static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setfield(lstate, -2, "_create_ts_parser"); lua_pushcfunction(lstate, ts_lua_register_lang); - lua_setfield(lstate, -2, "ts_add_language"); + lua_setfield(lstate, -2, "_ts_add_language"); } -- cgit From c8f861b739b4703b1198dc1f88b09edbeb0d9f2e Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 15 Jun 2019 12:10:12 +0200 Subject: tree-sitter: rename tree_sitter => treesitter for consistency --- src/nvim/lua/executor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 23c4fcabbc..8a35f11c71 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -31,7 +31,7 @@ #include "nvim/lua/executor.h" #include "nvim/lua/converter.h" -#include "nvim/lua/tree_sitter.h" +#include "nvim/lua/treesitter.h" #include "luv/luv.h" -- cgit From c1dc1bedba4e0e3db2cd2e52d9241991567f8218 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 15 Jun 2019 13:12:59 +0200 Subject: tree-sitter: style --- src/nvim/lua/executor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 8a35f11c71..c208711985 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -828,8 +828,7 @@ static int create_tslua_parser(lua_State *L) return luaL_error(L, "string expected"); } - const char *lang_name = lua_tostring(L,1); - + const char *lang_name = lua_tostring(L, 1); return tslua_push_parser(L, lang_name); } -- cgit From d24dec596c25690aba0aca658546ffdfcc6a952c Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 15 Jun 2019 14:05:35 +0200 Subject: tree-sitter: inspect language --- src/nvim/lua/executor.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index c208711985..aa83e3c1ba 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -841,4 +841,7 @@ static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_pushcfunction(lstate, ts_lua_register_lang); lua_setfield(lstate, -2, "_ts_add_language"); + + lua_pushcfunction(lstate, ts_lua_inspect_lang); + lua_setfield(lstate, -2, "_ts_inspect_language"); } -- cgit From 06ee45b9b1c14c7ce6cb23403cdbe2852d495cad Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 21 Jun 2019 14:14:51 +0200 Subject: tree-sitter: fix lint, delete "demo" plugin (replaced by functional tests) --- src/nvim/lua/executor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index aa83e3c1ba..127458fe39 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -839,9 +839,9 @@ static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_pushcfunction(lstate, create_tslua_parser); lua_setfield(lstate, -2, "_create_ts_parser"); - lua_pushcfunction(lstate, ts_lua_register_lang); + lua_pushcfunction(lstate, tslua_register_lang); lua_setfield(lstate, -2, "_ts_add_language"); - lua_pushcfunction(lstate, ts_lua_inspect_lang); + lua_pushcfunction(lstate, tslua_inspect_lang); lua_setfield(lstate, -2, "_ts_inspect_language"); } -- cgit From 8ee7c94a92598d46b488b7fe3b1a5cff6b1bf94a Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 25 Aug 2019 22:01:35 +0200 Subject: lua: add vim.fn.{func} for direct access to vimL function compared to vim.api.|nvim_call_function|, this fixes some typing issues due to the indirect conversion via the API. float values are preserved as such (fixes #9389) as well as empty dicts/arrays. Ref https://github.com/norcalli/nvim.lua for the call syntax --- src/nvim/lua/executor.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 127458fe39..b7c1d57964 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -295,6 +295,9 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL // in_fast_event lua_pushcfunction(lstate, &nlua_in_fast_event); lua_setfield(lstate, -2, "in_fast_event"); + // call + lua_pushcfunction(lstate, &nlua_call); + lua_setfield(lstate, -2, "call"); // vim.loop luv_set_loop(lstate, &main_loop.uv); @@ -539,6 +542,64 @@ int nlua_in_fast_event(lua_State *lstate) return 1; } +int nlua_call(lua_State *lstate) +{ + Error err = ERROR_INIT; + size_t name_len; + const char_u *name = (const char_u *)luaL_checklstring(lstate, 1, &name_len); + int nargs = lua_gettop(lstate)-1; + if (nargs > MAX_FUNC_ARGS) { + return luaL_error(lstate, "Function called with too many arguments"); + } + + typval_T vim_args[MAX_FUNC_ARGS + 1]; + int i = 0; // also used for freeing the variables + for (; i < nargs; i++) { + lua_pushvalue(lstate, (int)i+2); + if (!nlua_pop_typval(lstate, &vim_args[i])) { + api_set_error(&err, kErrorTypeException, + "error converting argument %d", i+1); + goto free_vim_args; + } + } + + // TODO(bfredl): this should be simplified in error handling refactor + struct msglist **saved_msg_list = msg_list; + struct msglist *private_msg_list = NULL; + msg_list = &private_msg_list; + + force_abort = false; + suppress_errthrow = false; + current_exception = NULL; + did_emsg = false; + + try_start(); + typval_T rettv; + int dummy; + // call_func() retval is deceptive, ignore it. Instead we set `msg_list` + // (see above) to capture abort-causing non-exception errors. + (void)call_func(name, (int)name_len, &rettv, nargs, + vim_args, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, + &dummy, true, NULL, NULL); + if (!try_end(&err)) { + nlua_push_typval(lstate, &rettv, false); + } + tv_clear(&rettv); + + msg_list = saved_msg_list; + +free_vim_args: + while (i > 0) { + tv_clear(&vim_args[--i]); + } + if (ERROR_SET(&err)) { + lua_pushstring(lstate, err.msg); + api_clear_error(&err); + return lua_error(lstate); + } + return 1; +} + #ifdef WIN32 /// os.getenv: override os.getenv to maintain coherency. #9681 /// @@ -623,7 +684,7 @@ void executor_eval_lua(const String str, typval_T *const arg, if (arg->v_type == VAR_UNKNOWN) { lua_pushnil(lstate); } else { - nlua_push_typval(lstate, arg); + nlua_push_typval(lstate, arg, true); } if (lua_pcall(lstate, 1, 1, 0)) { nlua_error(lstate, -- cgit From efaf4732e26e2f0fbfab947296141376223b30d7 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 27 Oct 2019 15:26:32 -0700 Subject: lua/executor.c: use TRY_WRAP --- src/nvim/lua/executor.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index b7c1d57964..c7ff163f83 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -563,11 +563,8 @@ int nlua_call(lua_State *lstate) } } + TRY_WRAP({ // TODO(bfredl): this should be simplified in error handling refactor - struct msglist **saved_msg_list = msg_list; - struct msglist *private_msg_list = NULL; - msg_list = &private_msg_list; - force_abort = false; suppress_errthrow = false; current_exception = NULL; @@ -577,7 +574,7 @@ int nlua_call(lua_State *lstate) typval_T rettv; int dummy; // call_func() retval is deceptive, ignore it. Instead we set `msg_list` - // (see above) to capture abort-causing non-exception errors. + // (TRY_WRAP) to capture abort-causing non-exception errors. (void)call_func(name, (int)name_len, &rettv, nargs, vim_args, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, true, NULL, NULL); @@ -585,8 +582,7 @@ int nlua_call(lua_State *lstate) nlua_push_typval(lstate, &rettv, false); } tv_clear(&rettv); - - msg_list = saved_msg_list; + }); free_vim_args: while (i > 0) { -- cgit From 474d0bcbf724c7eed740f60391a0ed35d651e1d3 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 27 Oct 2019 20:49:03 +0100 Subject: lua: vim.rpcrequest, vim.rpcnotify, vim.NIL --- src/nvim/lua/executor.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index c7ff163f83..5e5cb0cea5 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -12,6 +12,7 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" +#include "nvim/msgpack_rpc/channel.h" #include "nvim/vim.h" #include "nvim/ex_getln.h" #include "nvim/ex_cmds2.h" @@ -299,6 +300,14 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_pushcfunction(lstate, &nlua_call); lua_setfield(lstate, -2, "call"); + // rpcrequest + lua_pushcfunction(lstate, &nlua_rpcrequest); + lua_setfield(lstate, -2, "rpcrequest"); + + // rpcnotify + lua_pushcfunction(lstate, &nlua_rpcnotify); + lua_setfield(lstate, -2, "rpcnotify"); + // vim.loop luv_set_loop(lstate, &main_loop.uv); luv_set_callback(lstate, nlua_luv_cfpcall); @@ -314,6 +323,15 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setfield(lstate, -2, "luv"); lua_pop(lstate, 3); + // vim.NIL + lua_newuserdata(lstate, 0); + lua_createtable(lstate, 0, 0); + lua_pushcfunction(lstate, &nlua_nil_tostring); + lua_setfield(lstate, -2, "__tostring"); + lua_setmetatable(lstate, -2); + nlua_nil_ref = nlua_ref(lstate, -1); + lua_setfield(lstate, -2, "NIL"); + // internal vim._treesitter... API nlua_add_treesitter(lstate); @@ -547,6 +565,10 @@ int nlua_call(lua_State *lstate) Error err = ERROR_INIT; size_t name_len; const char_u *name = (const char_u *)luaL_checklstring(lstate, 1, &name_len); + if (!nlua_is_deferred_safe(lstate)) { + return luaL_error(lstate, e_luv_api_disabled, "vimL function"); + } + int nargs = lua_gettop(lstate)-1; if (nargs > MAX_FUNC_ARGS) { return luaL_error(lstate, "Function called with too many arguments"); @@ -596,6 +618,67 @@ free_vim_args: return 1; } +static int nlua_rpcrequest(lua_State *lstate) +{ + if (!nlua_is_deferred_safe(lstate)) { + return luaL_error(lstate, e_luv_api_disabled, "rpcrequest"); + } + return nlua_rpc(lstate, true); +} + +static int nlua_rpcnotify(lua_State *lstate) +{ + return nlua_rpc(lstate, false); +} + +static int nlua_rpc(lua_State *lstate, bool request) +{ + size_t name_len; + uint64_t chan_id = (uint64_t)luaL_checkinteger(lstate, 1); + const char *name = luaL_checklstring(lstate, 2, &name_len); + int nargs = lua_gettop(lstate)-2; + Error err = ERROR_INIT; + Array args = ARRAY_DICT_INIT; + + for (int i = 0; i < nargs; i++) { + lua_pushvalue(lstate, (int)i+3); + ADD(args, nlua_pop_Object(lstate, false, &err)); + if (ERROR_SET(&err)) { + api_free_array(args); + goto check_err; + } + } + + if (request) { + Object result = rpc_send_call(chan_id, name, args, &err); + if (!ERROR_SET(&err)) { + nlua_push_Object(lstate, result, false); + api_free_object(result); + } + } else { + if (!rpc_send_event(chan_id, name, args)) { + api_set_error(&err, kErrorTypeValidation, + "Invalid channel: %"PRIu64, chan_id); + } + } + +check_err: + if (ERROR_SET(&err)) { + lua_pushstring(lstate, err.msg); + api_clear_error(&err); + return lua_error(lstate); + } + + return request ? 1 : 0; +} + +static int nlua_nil_tostring(lua_State *lstate) +{ + lua_pushstring(lstate, "vim.NIL"); + return 1; +} + + #ifdef WIN32 /// os.getenv: override os.getenv to maintain coherency. #9681 /// -- cgit From dab40f43b18d35b283804ecb033310198cbf7548 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 30 Oct 2019 20:53:09 +0100 Subject: Add v:lua.func() vimL syntax for calling lua Also simplify error messages when calling lua from vimL. --- src/nvim/lua/executor.c | 114 ++++++++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 52 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 5e5cb0cea5..093c130c5f 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -48,9 +48,6 @@ typedef struct { # include "lua/executor.c.generated.h" #endif -/// Name of the run code for use in messages -#define NLUA_EVAL_NAME "" - /// Convert lua error into a Vim error message /// /// @param lstate Lua interpreter state. @@ -397,29 +394,6 @@ static lua_State *nlua_enter(void) return lstate; } -/// Execute lua string -/// -/// @param[in] str String to execute. -/// @param[out] ret_tv Location where result will be saved. -/// -/// @return Result of the execution. -void executor_exec_lua(const String str, typval_T *const ret_tv) - FUNC_ATTR_NONNULL_ALL -{ - lua_State *const lstate = nlua_enter(); - - if (luaL_loadbuffer(lstate, str.data, str.size, NLUA_EVAL_NAME)) { - nlua_error(lstate, _("E5104: Error while creating lua chunk: %.*s")); - return; - } - if (lua_pcall(lstate, 0, 1, 0)) { - nlua_error(lstate, _("E5105: Error while calling lua chunk: %.*s")); - return; - } - - nlua_pop_typval(lstate, ret_tv); -} - static void nlua_print_event(void **argv) { char *str = argv[0]; @@ -732,10 +706,6 @@ void executor_eval_lua(const String str, typval_T *const arg, typval_T *const ret_tv) FUNC_ATTR_NONNULL_ALL { - lua_State *const lstate = nlua_enter(); - - garray_T str_ga; - ga_init(&str_ga, 1, 80); #define EVALHEADER "local _A=select(1,...) return (" const size_t lcmd_len = sizeof(EVALHEADER) - 1 + str.size + 1; char *lcmd; @@ -748,30 +718,71 @@ void executor_eval_lua(const String str, typval_T *const arg, memcpy(lcmd + sizeof(EVALHEADER) - 1, str.data, str.size); lcmd[lcmd_len - 1] = ')'; #undef EVALHEADER - if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { - nlua_error(lstate, - _("E5107: Error while creating lua chunk for luaeval(): %.*s")); - if (lcmd != (char *)IObuff) { - xfree(lcmd); - } - return; - } + typval_exec_lua(lcmd, lcmd_len, "luaeval()", arg, 1, true, ret_tv); + if (lcmd != (char *)IObuff) { xfree(lcmd); } +} - if (arg->v_type == VAR_UNKNOWN) { - lua_pushnil(lstate); +void executor_call_lua(const char *str, size_t len, typval_T *const args, + int argcount, typval_T *ret_tv) + FUNC_ATTR_NONNULL_ALL +{ +#define CALLHEADER "return " +#define CALLSUFFIX "(...)" + const size_t lcmd_len = sizeof(CALLHEADER) - 1 + len + sizeof(CALLSUFFIX) - 1; + char *lcmd; + if (lcmd_len < IOSIZE) { + lcmd = (char *)IObuff; } else { - nlua_push_typval(lstate, arg, true); + lcmd = xmalloc(lcmd_len); + } + memcpy(lcmd, CALLHEADER, sizeof(CALLHEADER) - 1); + memcpy(lcmd + sizeof(CALLHEADER) - 1, str, len); + memcpy(lcmd + sizeof(CALLHEADER) - 1 + len, CALLSUFFIX, + sizeof(CALLSUFFIX) - 1); +#undef CALLHEADER +#undef CALLSUFFIX + + typval_exec_lua(lcmd, lcmd_len, "v:lua", args, argcount, false, ret_tv); + + if (lcmd != (char *)IObuff) { + xfree(lcmd); + } +} + +static void typval_exec_lua(const char *lcmd, size_t lcmd_len, const char *name, + typval_T *const args, int argcount, bool special, + typval_T *ret_tv) +{ + if (check_restricted() || check_secure()) { + ret_tv->v_type = VAR_NUMBER; + ret_tv->vval.v_number = 0; + return; } - if (lua_pcall(lstate, 1, 1, 0)) { - nlua_error(lstate, - _("E5108: Error while calling lua chunk for luaeval(): %.*s")); + + lua_State *const lstate = nlua_enter(); + if (luaL_loadbuffer(lstate, lcmd, lcmd_len, name)) { + nlua_error(lstate, _("E5107: Error loading lua %.*s")); return; } - nlua_pop_typval(lstate, ret_tv); + for (int i = 0; i < argcount; i++) { + if (args[i].v_type == VAR_UNKNOWN) { + lua_pushnil(lstate); + } else { + nlua_push_typval(lstate, &args[i], special); + } + } + if (lua_pcall(lstate, argcount, ret_tv ? 1 : 0, 0)) { + nlua_error(lstate, _("E5108: Error executing lua %.*s")); + return; + } + + if (ret_tv) { + nlua_pop_typval(lstate, ret_tv); + } } /// Execute lua string @@ -857,9 +868,8 @@ void ex_lua(exarg_T *const eap) xfree(code); return; } - typval_T tv = { .v_type = VAR_UNKNOWN }; - executor_exec_lua((String) { .data = code, .size = len }, &tv); - tv_clear(&tv); + typval_exec_lua(code, len, ":lua", NULL, 0, false, NULL); + xfree(code); } @@ -897,8 +907,8 @@ void ex_luado(exarg_T *const eap) #undef DOSTART #undef DOEND - if (luaL_loadbuffer(lstate, lcmd, lcmd_len, NLUA_EVAL_NAME)) { - nlua_error(lstate, _("E5109: Error while creating lua chunk: %.*s")); + if (luaL_loadbuffer(lstate, lcmd, lcmd_len, ":luado")) { + nlua_error(lstate, _("E5109: Error loading lua: %.*s")); if (lcmd_len >= IOSIZE) { xfree(lcmd); } @@ -908,7 +918,7 @@ void ex_luado(exarg_T *const eap) xfree(lcmd); } if (lua_pcall(lstate, 0, 1, 0)) { - nlua_error(lstate, _("E5110: Error while creating lua function: %.*s")); + nlua_error(lstate, _("E5110: Error executing lua: %.*s")); return; } for (linenr_T l = eap->line1; l <= eap->line2; l++) { @@ -919,7 +929,7 @@ void ex_luado(exarg_T *const eap) lua_pushstring(lstate, (const char *)ml_get_buf(curbuf, l, false)); lua_pushnumber(lstate, (lua_Number)l); if (lua_pcall(lstate, 2, 1, 0)) { - nlua_error(lstate, _("E5111: Error while calling lua function: %.*s")); + nlua_error(lstate, _("E5111: Error calling lua: %.*s")); break; } if (lua_isstring(lstate, -1)) { -- cgit From d0d38fc36e0c1602186aa540417070fa6c1e2746 Mon Sep 17 00:00:00 2001 From: Ashkan Kiani Date: Sun, 24 Nov 2019 02:28:48 -0800 Subject: Lua: vim.env, vim.{g,v,w,bo,wo} #11442 - Add vim variable meta accessors: vim.env, vim.{g,v,w,bo,wo} - Redo gen_char_blob to generate multiple blobs instead of just one so that multiple Lua modules can be inlined. - Reorder vim.lua inclusion so that it can use previously defined C functions and utility functions like vim.shared and vim.inspect things. - Inline shared.lua into nvim, but also keep it available in runtime. --- src/nvim/lua/executor.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 093c130c5f..5450f62f54 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -268,12 +268,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL #endif // vim - const char *code = (char *)&vim_module[0]; - if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua") - || lua_pcall(lstate, 0, LUA_MULTRET, 0)) { - nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); - return 1; - } + lua_newtable(lstate); // vim.api nlua_add_api_functions(lstate); // vim.types, vim.type_idx, vim.val_idx @@ -334,6 +329,24 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setglobal(lstate, "vim"); + { + const char *code = (char *)&shared_module[0]; + if (luaL_loadbuffer(lstate, code, strlen(code), "@shared.lua") + || lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5106: Error while creating shared module: %.*s")); + return 1; + } + } + + { + const char *code = (char *)&vim_module[0]; + if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua") + || lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); + return 1; + } + } + return 0; } -- cgit From a3b6c2a3dc5576db45fe4e893cfb8482af591c92 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 2 Dec 2019 00:46:46 -0800 Subject: API: rename nvim_execute_lua => nvim_exec_lua - We already find ourselves renaming nvim_execute_lua in tests and scripts, which suggests "exec" is the verb we actually want. - Add "exec" verb to `:help dev-api`. --- src/nvim/lua/executor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 5450f62f54..25f4be1c4d 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -798,9 +798,9 @@ static void typval_exec_lua(const char *lcmd, size_t lcmd_len, const char *name, } } -/// Execute lua string +/// Execute Lua string /// -/// Used for nvim_execute_lua(). +/// Used for nvim_exec_lua(). /// /// @param[in] str String to execute. /// @param[in] args array of ... args -- cgit