mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor(lua): use Arena when converting from lua stack to API args
and for return value of nlua_exec/nlua_call_ref, as this uses the same family of functions. NB: the handling of luaref:s is a bit of a mess. add api_luarefs_free_XX functions as a stop-gap as refactoring luarefs is a can of worms for another PR:s. as a minor feature/bug-fix, nvim_buf_call and nvim_win_call now preserves arbitrary return values.
This commit is contained in:
parent
89135cff03
commit
0353dd3029
@ -2183,8 +2183,7 @@ nvim_buf_call({buffer}, {fun}) *nvim_buf_call()*
|
||||
only)
|
||||
|
||||
Return: ~
|
||||
Return value of function. NB: will deepcopy Lua values currently, use
|
||||
upvalues to send Lua references in and out.
|
||||
Return value of function.
|
||||
|
||||
nvim_buf_del_keymap({buffer}, {mode}, {lhs}) *nvim_buf_del_keymap()*
|
||||
Unmaps a buffer-local |mapping| for the given mode.
|
||||
@ -2879,8 +2878,7 @@ nvim_win_call({window}, {fun}) *nvim_win_call()*
|
||||
only)
|
||||
|
||||
Return: ~
|
||||
Return value of function. NB: will deepcopy Lua values currently, use
|
||||
upvalues to send Lua references in and out.
|
||||
Return value of function.
|
||||
|
||||
See also: ~
|
||||
• |win_execute()|
|
||||
|
@ -422,6 +422,8 @@ The following changes to existing APIs or features add new behavior.
|
||||
|
||||
• |--startuptime| reports the startup times for both processes (TUI + server) as separate sections.
|
||||
|
||||
• |nvim_buf_call()| and |nvim_win_call()| now preserves any return value (NB: not multiple return values)
|
||||
|
||||
==============================================================================
|
||||
REMOVED FEATURES *news-removed*
|
||||
|
||||
|
@ -431,7 +431,8 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
||||
});
|
||||
|
||||
cb.type = kCallbackLua;
|
||||
cb.data.luaref = api_new_luaref(callback->data.luaref);
|
||||
cb.data.luaref = callback->data.luaref;
|
||||
callback->data.luaref = LUA_NOREF;
|
||||
break;
|
||||
case kObjectTypeString:
|
||||
cb.type = kCallbackFuncref;
|
||||
|
@ -1227,8 +1227,7 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
|
||||
/// @param fun Function to call inside the buffer (currently Lua callable
|
||||
/// only)
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return Return value of function. NB: will deepcopy Lua values
|
||||
/// currently, use upvalues to send Lua references in and out.
|
||||
/// @return Return value of function.
|
||||
Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
FUNC_API_LUA_ONLY
|
||||
@ -1242,7 +1241,7 @@ Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err)
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
Object res = nlua_call_ref(fun, NULL, args, true, err);
|
||||
Object res = nlua_call_ref(fun, NULL, args, kRetLuaref, NULL, err);
|
||||
|
||||
aucmd_restbuf(&aco);
|
||||
try_end(err);
|
||||
@ -1419,7 +1418,7 @@ static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len,
|
||||
} else {
|
||||
String str = STRING_INIT;
|
||||
if (len > 0) {
|
||||
str = arena_string(arena, cbuf_as_string((char *)s, len));
|
||||
str = CBUF_TO_ARENA_STR(arena, s, len);
|
||||
if (replace_nl) {
|
||||
// Vim represents NULs as NLs, but this may confuse clients.
|
||||
strchrsub(str.data, '\n', '\0');
|
||||
|
@ -99,7 +99,7 @@
|
||||
Dict(cmd) nvim_parse_cmd(String str, Dict(empty) *opts, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(10) FUNC_API_FAST
|
||||
{
|
||||
Dict(cmd) result = { 0 };
|
||||
Dict(cmd) result = KEYDICT_INIT;
|
||||
|
||||
// Parse command line
|
||||
exarg_T ea;
|
||||
@ -514,7 +514,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
VALIDATE_MOD((!ea.forceit || (ea.argt & EX_BANG)), "bang", cmd->cmd.data);
|
||||
|
||||
if (HAS_KEY(cmd, cmd, magic)) {
|
||||
Dict(cmd_magic) magic[1] = { 0 };
|
||||
Dict(cmd_magic) magic[1] = KEYDICT_INIT;
|
||||
if (!api_dict_to_keydict(magic, KeyDict_cmd_magic_get_field, cmd->magic, err)) {
|
||||
goto end;
|
||||
}
|
||||
@ -532,13 +532,13 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
}
|
||||
|
||||
if (HAS_KEY(cmd, cmd, mods)) {
|
||||
Dict(cmd_mods) mods[1] = { 0 };
|
||||
Dict(cmd_mods) mods[1] = KEYDICT_INIT;
|
||||
if (!api_dict_to_keydict(mods, KeyDict_cmd_mods_get_field, cmd->mods, err)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (HAS_KEY(mods, cmd_mods, filter)) {
|
||||
Dict(cmd_mods_filter) filter[1] = { 0 };
|
||||
Dict(cmd_mods_filter) filter[1] = KEYDICT_INIT;
|
||||
|
||||
if (!api_dict_to_keydict(&filter, KeyDict_cmd_mods_filter_get_field,
|
||||
mods->filter, err)) {
|
||||
@ -1103,7 +1103,8 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
|
||||
|
||||
if (opts->complete.type == kObjectTypeLuaRef) {
|
||||
context = EXPAND_USER_LUA;
|
||||
compl_luaref = api_new_luaref(opts->complete.data.luaref);
|
||||
compl_luaref = opts->complete.data.luaref;
|
||||
opts->complete.data.luaref = LUA_NOREF;
|
||||
} else if (opts->complete.type == kObjectTypeString) {
|
||||
VALIDATE_S(OK == parse_compl_arg(opts->complete.data.string.data,
|
||||
(int)opts->complete.data.string.size, &context, &argt,
|
||||
@ -1123,7 +1124,8 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
|
||||
});
|
||||
|
||||
argt |= EX_PREVIEW;
|
||||
preview_luaref = api_new_luaref(opts->preview.data.luaref);
|
||||
preview_luaref = opts->preview.data.luaref;
|
||||
opts->preview.data.luaref = LUA_NOREF;
|
||||
}
|
||||
|
||||
switch (command.type) {
|
||||
|
@ -51,12 +51,12 @@ String nvim_command_output(uint64_t channel_id, String command, Error *err)
|
||||
|
||||
/// @deprecated Use nvim_exec_lua() instead.
|
||||
/// @see nvim_exec_lua
|
||||
Object nvim_execute_lua(String code, Array args, Error *err)
|
||||
Object nvim_execute_lua(String code, Array args, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(3)
|
||||
FUNC_API_DEPRECATED_SINCE(7)
|
||||
FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
return nlua_exec(code, args, err);
|
||||
return nlua_exec(code, args, kRetObject, arena, err);
|
||||
}
|
||||
|
||||
/// Gets the buffer number
|
||||
|
@ -576,7 +576,7 @@ String arena_string(Arena *arena, String str)
|
||||
if (str.size) {
|
||||
return cbuf_as_string(arena_memdupz(arena, str.data, str.size), str.size);
|
||||
} else {
|
||||
return (String)STRING_INIT;
|
||||
return (String){ .data = arena ? "" : xstrdup(""), .size = 0 };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1062,24 +1062,56 @@ Dictionary api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void api_free_keydict(void *dict, KeySetLink *table)
|
||||
void api_luarefs_free_object(Object value)
|
||||
{
|
||||
// TODO(bfredl): this is more complicated than it needs to be.
|
||||
// we should be able to lock down more specifically where luarefs can be
|
||||
switch (value.type) {
|
||||
case kObjectTypeLuaRef:
|
||||
api_free_luaref(value.data.luaref);
|
||||
break;
|
||||
|
||||
case kObjectTypeArray:
|
||||
api_luarefs_free_array(value.data.array);
|
||||
break;
|
||||
|
||||
case kObjectTypeDictionary:
|
||||
api_luarefs_free_dict(value.data.dictionary);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void api_luarefs_free_keydict(void *dict, KeySetLink *table)
|
||||
{
|
||||
for (size_t i = 0; table[i].str; i++) {
|
||||
char *mem = ((char *)dict + table[i].ptr_off);
|
||||
if (table[i].type == kObjectTypeNil) {
|
||||
api_free_object(*(Object *)mem);
|
||||
} else if (table[i].type == kObjectTypeString) {
|
||||
api_free_string(*(String *)mem);
|
||||
} else if (table[i].type == kObjectTypeArray) {
|
||||
api_free_array(*(Array *)mem);
|
||||
} else if (table[i].type == kObjectTypeDictionary) {
|
||||
api_free_dictionary(*(Dictionary *)mem);
|
||||
api_luarefs_free_object(*(Object *)mem);
|
||||
} else if (table[i].type == kObjectTypeLuaRef) {
|
||||
api_free_luaref(*(LuaRef *)mem);
|
||||
} else if (table[i].type == kObjectTypeDictionary) {
|
||||
api_luarefs_free_dict(*(Dictionary *)mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void api_luarefs_free_array(Array value)
|
||||
{
|
||||
for (size_t i = 0; i < value.size; i++) {
|
||||
api_luarefs_free_object(value.items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void api_luarefs_free_dict(Dictionary value)
|
||||
{
|
||||
for (size_t i = 0; i < value.size; i++) {
|
||||
api_luarefs_free_object(value.items[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a named mark
|
||||
/// buffer and mark name must be validated already
|
||||
/// @param buffer Buffer to set the mark on
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define CSTR_TO_OBJ(s) STRING_OBJ(cstr_to_string(s))
|
||||
#define CSTR_TO_ARENA_STR(arena, s) arena_string(arena, cstr_as_string(s))
|
||||
#define CSTR_TO_ARENA_OBJ(arena, s) STRING_OBJ(CSTR_TO_ARENA_STR(arena, s))
|
||||
#define CBUF_TO_ARENA_STR(arena, s, len) arena_string(arena, cbuf_as_string((char *)(s), len))
|
||||
|
||||
#define BUFFER_OBJ(s) ((Object) { \
|
||||
.type = kObjectTypeBuffer, \
|
||||
@ -119,6 +120,8 @@
|
||||
#define api_init_array = ARRAY_DICT_INIT
|
||||
#define api_init_dictionary = ARRAY_DICT_INIT
|
||||
|
||||
#define KEYDICT_INIT { 0 }
|
||||
|
||||
#define api_free_boolean(value)
|
||||
#define api_free_integer(value)
|
||||
#define api_free_float(value)
|
||||
|
@ -496,11 +496,12 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool
|
||||
/// or executing the Lua code.
|
||||
///
|
||||
/// @return Return value of Lua code if present or NIL.
|
||||
Object nvim_exec_lua(String code, Array args, Error *err)
|
||||
Object nvim_exec_lua(String code, Array args, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
return nlua_exec(code, args, err);
|
||||
// TODO(bfredl): convert directly from msgpack to lua and then back again
|
||||
return nlua_exec(code, args, kRetObject, arena, err);
|
||||
}
|
||||
|
||||
/// Notify the user with a message
|
||||
@ -512,7 +513,7 @@ Object nvim_exec_lua(String code, Array args, Error *err)
|
||||
/// @param log_level The log level
|
||||
/// @param opts Reserved for future use.
|
||||
/// @param[out] err Error details, if any
|
||||
Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err)
|
||||
Object nvim_notify(String msg, Integer log_level, Dictionary opts, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
{
|
||||
MAXSIZE_TEMP_ARRAY(args, 3);
|
||||
@ -520,7 +521,7 @@ Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err)
|
||||
ADD_C(args, INTEGER_OBJ(log_level));
|
||||
ADD_C(args, DICTIONARY_OBJ(opts));
|
||||
|
||||
return NLUA_EXEC_STATIC("return vim.notify(...)", args, err);
|
||||
return NLUA_EXEC_STATIC("return vim.notify(...)", args, kRetObject, arena, err);
|
||||
}
|
||||
|
||||
/// Calculates the number of display cells occupied by `text`.
|
||||
@ -603,7 +604,8 @@ String nvim__get_lib_dir(void)
|
||||
/// @param all whether to return all matches or only the first
|
||||
/// @param opts is_lua: only search Lua subdirs
|
||||
/// @return list of absolute paths to the found files
|
||||
ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, Error *err)
|
||||
ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, Arena *arena,
|
||||
Error *err)
|
||||
FUNC_API_SINCE(8)
|
||||
FUNC_API_FAST
|
||||
{
|
||||
@ -613,7 +615,7 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E
|
||||
return (Array)ARRAY_DICT_INIT;
|
||||
}
|
||||
|
||||
ArrayOf(String) res = runtime_get_named(opts->is_lua, pat, all);
|
||||
ArrayOf(String) res = runtime_get_named(opts->is_lua, pat, all, arena);
|
||||
|
||||
if (opts->do_source) {
|
||||
for (size_t i = 0; i < res.size; i++) {
|
||||
@ -1068,7 +1070,7 @@ static void term_write(const char *buf, size_t size, void *data)
|
||||
ADD_C(args, BUFFER_OBJ(terminal_buf(chan->term)));
|
||||
ADD_C(args, STRING_OBJ(((String){ .data = (char *)buf, .size = size })));
|
||||
textlock++;
|
||||
nlua_call_ref(cb, "input", args, false, NULL);
|
||||
nlua_call_ref(cb, "input", args, kRetNilBool, NULL, NULL);
|
||||
textlock--;
|
||||
}
|
||||
|
||||
@ -1189,7 +1191,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
|
||||
/// @return
|
||||
/// - true: Client may continue pasting.
|
||||
/// - false: Client must cancel the paste.
|
||||
Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
|
||||
Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(6)
|
||||
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
|
||||
{
|
||||
@ -1199,19 +1201,18 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
|
||||
VALIDATE_INT((phase >= -1 && phase <= 3), "phase", phase, {
|
||||
return false;
|
||||
});
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
Object rv = OBJECT_INIT;
|
||||
Array lines = ARRAY_DICT_INIT;
|
||||
if (phase == -1 || phase == 1) { // Start of paste-stream.
|
||||
draining = false;
|
||||
} else if (draining) {
|
||||
// Skip remaining chunks. Report error only once per "stream".
|
||||
goto theend;
|
||||
}
|
||||
Array lines = string_to_array(data, crlf);
|
||||
ADD(args, ARRAY_OBJ(lines));
|
||||
ADD(args, INTEGER_OBJ(phase));
|
||||
rv = nvim_exec_lua(STATIC_CSTR_AS_STRING("return vim.paste(...)"), args,
|
||||
err);
|
||||
lines = string_to_array(data, crlf);
|
||||
MAXSIZE_TEMP_ARRAY(args, 2);
|
||||
ADD_C(args, ARRAY_OBJ(lines));
|
||||
ADD_C(args, INTEGER_OBJ(phase));
|
||||
Object rv = NLUA_EXEC_STATIC("return vim.paste(...)", args, kRetNilBool, arena, err);
|
||||
if (ERROR_SET(err)) {
|
||||
draining = true;
|
||||
goto theend;
|
||||
@ -1238,8 +1239,7 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
|
||||
AppendCharToRedobuff(ESC); // Dot-repeat.
|
||||
}
|
||||
theend:
|
||||
api_free_object(rv);
|
||||
api_free_array(args);
|
||||
api_free_array(lines);
|
||||
if (cancel || phase == -1 || phase == 3) { // End of paste-stream.
|
||||
draining = false;
|
||||
}
|
||||
@ -1875,7 +1875,7 @@ Array nvim_list_uis(Arena *arena)
|
||||
/// Gets the immediate children of process `pid`.
|
||||
///
|
||||
/// @return Array of child process ids, empty if process not found.
|
||||
Array nvim_get_proc_children(Integer pid, Error *err)
|
||||
Array nvim_get_proc_children(Integer pid, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(4)
|
||||
{
|
||||
Array rvobj = ARRAY_DICT_INIT;
|
||||
@ -1892,7 +1892,7 @@ Array nvim_get_proc_children(Integer pid, Error *err)
|
||||
DLOG("fallback to vim._os_proc_children()");
|
||||
MAXSIZE_TEMP_ARRAY(a, 1);
|
||||
ADD(a, INTEGER_OBJ(pid));
|
||||
Object o = NLUA_EXEC_STATIC("return vim._os_proc_children(...)", a, err);
|
||||
Object o = NLUA_EXEC_STATIC("return vim._os_proc_children(...)", a, kRetObject, arena, err);
|
||||
if (o.type == kObjectTypeArray) {
|
||||
rvobj = o.data.array;
|
||||
} else if (!ERROR_SET(err)) {
|
||||
@ -1900,11 +1900,11 @@ Array nvim_get_proc_children(Integer pid, Error *err)
|
||||
"Failed to get process children. pid=%" PRId64 " error=%d",
|
||||
pid, rv);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < proc_count; i++) {
|
||||
ADD(rvobj, INTEGER_OBJ(proc_list[i]));
|
||||
} else {
|
||||
rvobj = arena_array(arena, proc_count);
|
||||
for (size_t i = 0; i < proc_count; i++) {
|
||||
ADD(rvobj, INTEGER_OBJ(proc_list[i]));
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
@ -1915,19 +1915,17 @@ end:
|
||||
/// Gets info describing process `pid`.
|
||||
///
|
||||
/// @return Map of process properties, or NIL if process not found.
|
||||
Object nvim_get_proc(Integer pid, Error *err)
|
||||
Object nvim_get_proc(Integer pid, Arena *arena, Error *err)
|
||||
FUNC_API_SINCE(4)
|
||||
{
|
||||
Object rvobj = OBJECT_INIT;
|
||||
rvobj.data.dictionary = (Dictionary)ARRAY_DICT_INIT;
|
||||
rvobj.type = kObjectTypeDictionary;
|
||||
Object rvobj = NIL;
|
||||
|
||||
VALIDATE_INT((pid > 0 && pid <= INT_MAX), "pid", pid, {
|
||||
return NIL;
|
||||
});
|
||||
|
||||
#ifdef MSWIN
|
||||
rvobj.data.dictionary = os_proc_info((int)pid);
|
||||
rvobj = DICTIONARY_OBJ(os_proc_info((int)pid));
|
||||
if (rvobj.data.dictionary.size == 0) { // Process not found.
|
||||
return NIL;
|
||||
}
|
||||
@ -1935,11 +1933,11 @@ Object nvim_get_proc(Integer pid, Error *err)
|
||||
// Cross-platform process info APIs are miserable, so use `ps` instead.
|
||||
MAXSIZE_TEMP_ARRAY(a, 1);
|
||||
ADD(a, INTEGER_OBJ(pid));
|
||||
Object o = NLUA_EXEC_STATIC("return vim._os_proc_info(...)", a, err);
|
||||
Object o = NLUA_EXEC_STATIC("return vim._os_proc_info(...)", a, kRetObject, arena, err);
|
||||
if (o.type == kObjectTypeArray && o.data.array.size == 0) {
|
||||
return NIL; // Process not found.
|
||||
} else if (o.type == kObjectTypeDictionary) {
|
||||
rvobj.data.dictionary = o.data.dictionary;
|
||||
rvobj = o;
|
||||
} else if (!ERROR_SET(err)) {
|
||||
api_set_error(err, kErrorTypeException,
|
||||
"Failed to get process info. pid=%" PRId64, pid);
|
||||
|
@ -600,7 +600,7 @@ Dict(win_config) nvim_win_get_config(Window window, Arena *arena, Error *err)
|
||||
/// Keep in sync with WinSplit in buffer_defs.h
|
||||
static const char *const win_split_str[] = { "left", "right", "above", "below" };
|
||||
|
||||
Dict(win_config) rv = { 0 };
|
||||
Dict(win_config) rv = KEYDICT_INIT;
|
||||
|
||||
win_T *wp = find_window_by_handle(window, err);
|
||||
if (!wp) {
|
||||
|
@ -421,8 +421,7 @@ void nvim_win_close(Window window, Boolean force, Error *err)
|
||||
/// @param fun Function to call inside the window (currently Lua callable
|
||||
/// only)
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return Return value of function. NB: will deepcopy Lua values
|
||||
/// currently, use upvalues to send Lua references in and out.
|
||||
/// @return Return value of function.
|
||||
Object nvim_win_call(Window window, LuaRef fun, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
FUNC_API_LUA_ONLY
|
||||
@ -438,7 +437,7 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
|
||||
win_execute_T win_execute_args;
|
||||
if (win_execute_before(&win_execute_args, win, tabpage)) {
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
res = nlua_call_ref(fun, NULL, args, true, err);
|
||||
res = nlua_call_ref(fun, NULL, args, kRetLuaref, NULL, err);
|
||||
}
|
||||
win_execute_after(&win_execute_args);
|
||||
try_end(err);
|
||||
|
@ -2002,15 +2002,15 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc)
|
||||
{
|
||||
Callback callback = ac->exec.callable.cb;
|
||||
if (callback.type == kCallbackLua) {
|
||||
Dictionary data = ARRAY_DICT_INIT;
|
||||
PUT(data, "id", INTEGER_OBJ(ac->id));
|
||||
PUT(data, "event", CSTR_TO_OBJ(event_nr2name(apc->event)));
|
||||
PUT(data, "match", CSTR_TO_OBJ(autocmd_match));
|
||||
PUT(data, "file", CSTR_TO_OBJ(autocmd_fname));
|
||||
PUT(data, "buf", INTEGER_OBJ(autocmd_bufnr));
|
||||
MAXSIZE_TEMP_DICT(data, 7);
|
||||
PUT_C(data, "id", INTEGER_OBJ(ac->id));
|
||||
PUT_C(data, "event", CSTR_AS_OBJ(event_nr2name(apc->event)));
|
||||
PUT_C(data, "match", CSTR_AS_OBJ(autocmd_match));
|
||||
PUT_C(data, "file", CSTR_AS_OBJ(autocmd_fname));
|
||||
PUT_C(data, "buf", INTEGER_OBJ(autocmd_bufnr));
|
||||
|
||||
if (apc->data) {
|
||||
PUT(data, "data", copy_object(*apc->data, NULL));
|
||||
PUT_C(data, "data", *apc->data);
|
||||
}
|
||||
|
||||
int group = ac->pat->group;
|
||||
@ -2023,21 +2023,15 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc)
|
||||
// omit group in these cases
|
||||
break;
|
||||
default:
|
||||
PUT(data, "group", INTEGER_OBJ(group));
|
||||
PUT_C(data, "group", INTEGER_OBJ(group));
|
||||
break;
|
||||
}
|
||||
|
||||
MAXSIZE_TEMP_ARRAY(args, 1);
|
||||
ADD_C(args, DICTIONARY_OBJ(data));
|
||||
|
||||
Object result = nlua_call_ref(callback.data.luaref, NULL, args, true, NULL);
|
||||
bool ret = false;
|
||||
if (result.type == kObjectTypeBoolean) {
|
||||
ret = result.data.boolean;
|
||||
}
|
||||
api_free_dictionary(data);
|
||||
api_free_object(result);
|
||||
return ret;
|
||||
Object result = nlua_call_ref(callback.data.luaref, NULL, args, kRetNilBool, NULL, NULL);
|
||||
return LUARET_TRUTHY(result);
|
||||
} else {
|
||||
typval_T argsin = TV_INITIAL_VALUE;
|
||||
typval_T rettv = TV_INITIAL_VALUE;
|
||||
|
@ -179,7 +179,7 @@ void buf_updates_unload(buf_T *buf, bool can_reload)
|
||||
ADD_C(args, BUFFER_OBJ(buf->handle));
|
||||
|
||||
TEXTLOCK_WRAP({
|
||||
nlua_call_ref(thecb, keep ? "reload" : "detach", args, false, NULL);
|
||||
nlua_call_ref(thecb, keep ? "reload" : "detach", args, false, NULL, NULL);
|
||||
});
|
||||
}
|
||||
|
||||
@ -295,10 +295,10 @@ void buf_updates_send_changes(buf_T *buf, linenr_T firstline, int64_t num_added,
|
||||
|
||||
Object res;
|
||||
TEXTLOCK_WRAP({
|
||||
res = nlua_call_ref(cb.on_lines, "lines", args, false, NULL);
|
||||
res = nlua_call_ref(cb.on_lines, "lines", args, kRetNilBool, NULL, NULL);
|
||||
});
|
||||
|
||||
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
|
||||
if (LUARET_TRUTHY(res)) {
|
||||
buffer_update_callbacks_free(cb);
|
||||
keep = false;
|
||||
}
|
||||
@ -345,10 +345,10 @@ void buf_updates_send_splice(buf_T *buf, int start_row, colnr_T start_col, bcoun
|
||||
|
||||
Object res;
|
||||
TEXTLOCK_WRAP({
|
||||
res = nlua_call_ref(cb.on_bytes, "bytes", args, false, NULL);
|
||||
res = nlua_call_ref(cb.on_bytes, "bytes", args, kRetNilBool, NULL, NULL);
|
||||
});
|
||||
|
||||
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
|
||||
if (LUARET_TRUTHY(res)) {
|
||||
buffer_update_callbacks_free(cb);
|
||||
keep = false;
|
||||
}
|
||||
@ -381,10 +381,10 @@ void buf_updates_changedtick(buf_T *buf)
|
||||
|
||||
Object res;
|
||||
TEXTLOCK_WRAP({
|
||||
res = nlua_call_ref(cb.on_changedtick, "changedtick", args, false, NULL);
|
||||
res = nlua_call_ref(cb.on_changedtick, "changedtick", args, kRetNilBool, NULL, NULL);
|
||||
});
|
||||
|
||||
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
|
||||
if (LUARET_TRUTHY(res)) {
|
||||
buffer_update_callbacks_free(cb);
|
||||
keep = false;
|
||||
}
|
||||
|
@ -2591,7 +2591,7 @@ static char *get_healthcheck_names(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
||||
if (last_gen != get_cmdline_last_prompt_id() || last_gen == 0) {
|
||||
Array a = ARRAY_DICT_INIT;
|
||||
Error err = ERROR_INIT;
|
||||
Object res = nlua_exec(STATIC_CSTR_AS_STRING("return vim.health._complete()"), a, &err);
|
||||
Object res = NLUA_EXEC_STATIC("return vim.health._complete()", a, kRetObject, NULL, &err);
|
||||
api_clear_error(&err);
|
||||
api_free_object(names);
|
||||
names = res;
|
||||
|
@ -48,7 +48,7 @@ static bool decor_provider_invoke(int provider_idx, const char *name, LuaRef ref
|
||||
|
||||
textlock++;
|
||||
provider_active = true;
|
||||
Object ret = nlua_call_ref(ref, name, args, true, &err);
|
||||
Object ret = nlua_call_ref(ref, name, args, kRetNilBool, NULL, &err);
|
||||
provider_active = false;
|
||||
textlock--;
|
||||
|
||||
|
@ -6143,8 +6143,8 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
|
||||
break;
|
||||
|
||||
case kCallbackLua:
|
||||
rv = nlua_call_ref(callback->data.luaref, NULL, args, false, NULL);
|
||||
return (rv.type == kObjectTypeBoolean && rv.data.boolean == true);
|
||||
rv = nlua_call_ref(callback->data.luaref, NULL, args, kRetNilBool, NULL, NULL);
|
||||
return LUARET_TRUTHY(rv);
|
||||
|
||||
case kCallbackNone:
|
||||
return false;
|
||||
|
@ -3278,13 +3278,11 @@ static bool has_wsl(void)
|
||||
static TriState has_wsl = kNone;
|
||||
if (has_wsl == kNone) {
|
||||
Error err = ERROR_INIT;
|
||||
Object o = nlua_exec(STATIC_CSTR_AS_STRING("return vim.uv.os_uname()['release']:lower()"
|
||||
":match('microsoft') and true or false"),
|
||||
(Array)ARRAY_DICT_INIT, &err);
|
||||
Object o = NLUA_EXEC_STATIC("return vim.uv.os_uname()['release']:lower()"
|
||||
":match('microsoft')",
|
||||
(Array)ARRAY_DICT_INIT, kRetNilBool, NULL, &err);
|
||||
assert(!ERROR_SET(&err));
|
||||
assert(o.type == kObjectTypeBoolean);
|
||||
has_wsl = o.data.boolean ? kTrue : kFalse;
|
||||
api_free_object(o);
|
||||
has_wsl = LUARET_TRUTHY(o) ? kTrue : kFalse;
|
||||
}
|
||||
return has_wsl == kTrue;
|
||||
}
|
||||
@ -6963,6 +6961,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
|
||||
ArenaMem res_mem = NULL;
|
||||
Object result = rpc_send_call(chan_id, method, args, &res_mem, &err);
|
||||
api_free_array(args);
|
||||
|
||||
if (l_provider_call_nesting) {
|
||||
current_sctx = save_current_sctx;
|
||||
|
@ -7445,7 +7445,7 @@ static void ex_checkhealth(exarg_T *eap)
|
||||
ADD_C(args, STRING_OBJ(((String){ .data = mods, .size = mods_len })));
|
||||
ADD_C(args, CSTR_AS_OBJ(eap->arg));
|
||||
|
||||
NLUA_EXEC_STATIC("return vim.health._check(...)", args, &err);
|
||||
NLUA_EXEC_STATIC("vim.health._check(...)", args, kRetNilBool, NULL, &err);
|
||||
if (!ERROR_SET(&err)) {
|
||||
return;
|
||||
}
|
||||
|
@ -333,9 +333,6 @@ KeySetLink *KeyDict_]] .. k.name .. [[_get_field(const char *str, size_t len)
|
||||
}
|
||||
|
||||
]])
|
||||
keysets_defs:write(
|
||||
'#define api_free_keydict_' .. k.name .. '(x) api_free_keydict(x, ' .. k.name .. '_table)\n'
|
||||
)
|
||||
end
|
||||
|
||||
local function real_type(type)
|
||||
@ -687,6 +684,7 @@ local function process_function(fn)
|
||||
static int %s(lua_State *lstate)
|
||||
{
|
||||
Error err = ERROR_INIT;
|
||||
Arena arena = ARENA_EMPTY;
|
||||
char *err_param = 0;
|
||||
if (lua_gettop(lstate) != %i) {
|
||||
api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s");
|
||||
@ -736,18 +734,24 @@ local function process_function(fn)
|
||||
local param = fn.parameters[j]
|
||||
local cparam = string.format('arg%u', j)
|
||||
local param_type = real_type(param[1])
|
||||
local lc_param_type = real_type(param[1]):lower()
|
||||
local extra = param_type == 'Dictionary' and 'false, ' or ''
|
||||
if param[1] == 'Object' or param[1] == 'DictionaryOf(LuaRef)' then
|
||||
local arg_free_code = ''
|
||||
if param[1] == 'Object' then
|
||||
extra = 'true, '
|
||||
arg_free_code = 'api_luarefs_free_object(' .. cparam .. ');'
|
||||
elseif param[1] == 'DictionaryOf(LuaRef)' then
|
||||
extra = 'true, '
|
||||
arg_free_code = 'api_luarefs_free_dict(' .. cparam .. ');'
|
||||
elseif param[1] == 'LuaRef' then
|
||||
arg_free_code = 'api_free_luaref(' .. cparam .. ');'
|
||||
end
|
||||
local errshift = 0
|
||||
local seterr = ''
|
||||
if string.match(param_type, '^KeyDict_') then
|
||||
write_shifted_output(
|
||||
[[
|
||||
%s %s = { 0 };
|
||||
nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err);
|
||||
%s %s = KEYDICT_INIT;
|
||||
nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &arena, &err);
|
||||
]],
|
||||
param_type,
|
||||
cparam,
|
||||
@ -756,10 +760,15 @@ local function process_function(fn)
|
||||
)
|
||||
cparam = '&' .. cparam
|
||||
errshift = 1 -- free incomplete dict on error
|
||||
arg_free_code = 'api_luarefs_free_keydict('
|
||||
.. cparam
|
||||
.. ', '
|
||||
.. string.sub(param_type, 9)
|
||||
.. '_table);'
|
||||
else
|
||||
write_shifted_output(
|
||||
[[
|
||||
const %s %s = nlua_pop_%s(lstate, %s&err);]],
|
||||
const %s %s = nlua_pop_%s(lstate, %s&arena, &err);]],
|
||||
param[1],
|
||||
cparam,
|
||||
param_type,
|
||||
@ -776,7 +785,7 @@ local function process_function(fn)
|
||||
}
|
||||
|
||||
]], #fn.parameters - j + errshift)
|
||||
free_code[#free_code + 1] = ('api_free_%s(%s);'):format(lc_param_type, cparam)
|
||||
free_code[#free_code + 1] = arg_free_code
|
||||
cparams = cparam .. ', ' .. cparams
|
||||
end
|
||||
if fn.receives_channel_id then
|
||||
@ -784,7 +793,6 @@ local function process_function(fn)
|
||||
end
|
||||
if fn.arena_return then
|
||||
cparams = cparams .. '&arena, '
|
||||
write_shifted_output(' Arena arena = ARENA_EMPTY;\n')
|
||||
end
|
||||
|
||||
if fn.has_lua_imp then
|
||||
@ -809,6 +817,7 @@ local function process_function(fn)
|
||||
local err_throw_code = [[
|
||||
|
||||
exit_0:
|
||||
arena_mem_free(arena_finish(&arena));
|
||||
if (ERROR_SET(&err)) {
|
||||
luaL_where(lstate, 1);
|
||||
if (err_param) {
|
||||
@ -829,10 +838,8 @@ exit_0:
|
||||
else
|
||||
return_type = fn.return_type
|
||||
end
|
||||
local free_retval
|
||||
if fn.arena_return then
|
||||
free_retval = ' arena_mem_free(arena_finish(&arena));'
|
||||
else
|
||||
local free_retval = ''
|
||||
if not fn.arena_return then
|
||||
free_retval = ' api_free_' .. return_type:lower() .. '(ret);'
|
||||
end
|
||||
write_shifted_output(' %s ret = %s(%s);\n', fn.return_type, fn.name, cparams)
|
||||
@ -858,6 +865,7 @@ exit_0:
|
||||
write_shifted_output(' nlua_push_%s(lstate, ret, %s);\n', return_type, tostring(special))
|
||||
end
|
||||
|
||||
-- NOTE: we currently assume err_throw needs nothing from arena
|
||||
write_shifted_output(
|
||||
|
||||
[[
|
||||
|
@ -3027,7 +3027,7 @@ bool map_execute_lua(bool may_repeat)
|
||||
|
||||
Error err = ERROR_INIT;
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
nlua_call_ref(ref, NULL, args, false, &err);
|
||||
nlua_call_ref(ref, NULL, args, kRetNilBool, NULL, &err);
|
||||
if (err.type != kErrorTypeNone) {
|
||||
semsg_multiline("E5108: %s", err.msg);
|
||||
api_clear_error(&err);
|
||||
|
@ -212,7 +212,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault)
|
||||
|
||||
Error err = ERROR_INIT;
|
||||
recursive++;
|
||||
Object ret = nlua_call_ref(p->hl_def, "hl_def", args, true, &err);
|
||||
Object ret = nlua_call_ref(p->hl_def, "hl_def", args, kRetObject, NULL, &err);
|
||||
recursive--;
|
||||
|
||||
// TODO(bfredl): or "inherit", combine with global value?
|
||||
@ -221,7 +221,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault)
|
||||
HlAttrs attrs = HLATTRS_INIT;
|
||||
if (ret.type == kObjectTypeDictionary) {
|
||||
fallback = false;
|
||||
Dict(highlight) dict = { 0 };
|
||||
Dict(highlight) dict = KEYDICT_INIT;
|
||||
if (api_dict_to_keydict(&dict, KeyDict_highlight_get_field,
|
||||
ret.data.dictionary, &err)) {
|
||||
attrs = dict2hlattrs(&dict, true, &it.link_id, &err);
|
||||
@ -1086,7 +1086,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
|
||||
|
||||
// Handle cterm attrs
|
||||
if (dict->cterm.type == kObjectTypeDictionary) {
|
||||
Dict(highlight_cterm) cterm[1] = { 0 };
|
||||
Dict(highlight_cterm) cterm[1] = KEYDICT_INIT;
|
||||
if (!api_dict_to_keydict(cterm, KeyDict_highlight_cterm_get_field,
|
||||
dict->cterm.data.dictionary, err)) {
|
||||
return hlattrs;
|
||||
|
@ -795,8 +795,8 @@ void nlua_push_Object(lua_State *lstate, const Object obj, bool special)
|
||||
/// Convert lua value to string
|
||||
///
|
||||
/// Always pops one value from the stack.
|
||||
String nlua_pop_String(lua_State *lstate, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
String nlua_pop_String(lua_State *lstate, Arena *arena, Error *err)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (lua_type(lstate, -1) != LUA_TSTRING) {
|
||||
lua_pop(lstate, 1);
|
||||
@ -807,7 +807,10 @@ String nlua_pop_String(lua_State *lstate, Error *err)
|
||||
|
||||
ret.data = (char *)lua_tolstring(lstate, -1, &(ret.size));
|
||||
assert(ret.data != NULL);
|
||||
ret.data = xmemdupz(ret.data, ret.size);
|
||||
// TODO(bfredl): it would be "nice" to just use the memory of the lua string
|
||||
// directly, although ensuring the lifetime of such strings is a bit tricky
|
||||
// (an API call could invoke nested lua, which triggers GC, and kaboom?)
|
||||
ret.data = arena_memdupz(arena, ret.data, ret.size);
|
||||
lua_pop(lstate, 1);
|
||||
|
||||
return ret;
|
||||
@ -816,8 +819,8 @@ String nlua_pop_String(lua_State *lstate, Error *err)
|
||||
/// Convert lua value to integer
|
||||
///
|
||||
/// Always pops one value from the stack.
|
||||
Integer nlua_pop_Integer(lua_State *lstate, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
Integer nlua_pop_Integer(lua_State *lstate, Arena *arena, Error *err)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (lua_type(lstate, -1) != LUA_TNUMBER) {
|
||||
lua_pop(lstate, 1);
|
||||
@ -840,8 +843,8 @@ Integer nlua_pop_Integer(lua_State *lstate, Error *err)
|
||||
/// thus `err` is never set as any lua value can be co-erced into a lua bool
|
||||
///
|
||||
/// Always pops one value from the stack.
|
||||
Boolean nlua_pop_Boolean(lua_State *lstate, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
Boolean nlua_pop_Boolean(lua_State *lstate, Arena *arena, Error *err)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
const Boolean ret = lua_toboolean(lstate, -1);
|
||||
lua_pop(lstate, 1);
|
||||
@ -915,7 +918,7 @@ static inline LuaTableProps nlua_check_type(lua_State *const lstate, Error *cons
|
||||
/// Convert lua table to float
|
||||
///
|
||||
/// Always pops one value from the stack.
|
||||
Float nlua_pop_Float(lua_State *lstate, Error *err)
|
||||
Float nlua_pop_Float(lua_State *lstate, Arena *arena, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (lua_type(lstate, -1) == LUA_TNUMBER) {
|
||||
@ -939,29 +942,29 @@ Float nlua_pop_Float(lua_State *lstate, Error *err)
|
||||
/// @param[in] table_props nlua_traverse_table() output.
|
||||
/// @param[out] err Location where error will be saved.
|
||||
static Array nlua_pop_Array_unchecked(lua_State *const lstate, const LuaTableProps table_props,
|
||||
Error *const err)
|
||||
Arena *arena, Error *const err)
|
||||
{
|
||||
Array ret = { .size = table_props.maxidx, .items = NULL };
|
||||
Array ret = arena_array(arena, table_props.maxidx);
|
||||
|
||||
if (ret.size == 0) {
|
||||
if (table_props.maxidx == 0) {
|
||||
lua_pop(lstate, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.items = xcalloc(ret.size, sizeof(*ret.items));
|
||||
for (size_t i = 1; i <= ret.size; i++) {
|
||||
for (size_t i = 1; i <= table_props.maxidx; i++) {
|
||||
Object val;
|
||||
|
||||
lua_rawgeti(lstate, -1, (int)i);
|
||||
|
||||
val = nlua_pop_Object(lstate, false, err);
|
||||
val = nlua_pop_Object(lstate, false, arena, err);
|
||||
if (ERROR_SET(err)) {
|
||||
ret.size = i - 1;
|
||||
lua_pop(lstate, 1);
|
||||
api_free_array(ret);
|
||||
if (!arena) {
|
||||
api_free_array(ret);
|
||||
}
|
||||
return (Array) { .size = 0, .items = NULL };
|
||||
}
|
||||
ret.items[i - 1] = val;
|
||||
ADD_C(ret, val);
|
||||
}
|
||||
lua_pop(lstate, 1);
|
||||
|
||||
@ -971,15 +974,14 @@ static Array nlua_pop_Array_unchecked(lua_State *const lstate, const LuaTablePro
|
||||
/// Convert lua table to array
|
||||
///
|
||||
/// Always pops one value from the stack.
|
||||
Array nlua_pop_Array(lua_State *lstate, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
Array nlua_pop_Array(lua_State *lstate, Arena *arena, Error *err)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
const LuaTableProps table_props = nlua_check_type(lstate, err,
|
||||
kObjectTypeArray);
|
||||
const LuaTableProps table_props = nlua_check_type(lstate, err, kObjectTypeArray);
|
||||
if (table_props.type != kObjectTypeArray) {
|
||||
return (Array) { .size = 0, .items = NULL };
|
||||
}
|
||||
return nlua_pop_Array_unchecked(lstate, table_props, err);
|
||||
return nlua_pop_Array_unchecked(lstate, table_props, arena, err);
|
||||
}
|
||||
|
||||
/// Convert lua table to dictionary
|
||||
@ -991,30 +993,30 @@ Array nlua_pop_Array(lua_State *lstate, Error *err)
|
||||
/// @param[in] table_props nlua_traverse_table() output.
|
||||
/// @param[out] err Location where error will be saved.
|
||||
static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate, const LuaTableProps table_props,
|
||||
bool ref, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
bool ref, Arena *arena, Error *err)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 5) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
Dictionary ret = { .size = table_props.string_keys_num, .items = NULL };
|
||||
Dictionary ret = arena_dict(arena, table_props.string_keys_num);
|
||||
|
||||
if (ret.size == 0) {
|
||||
if (table_props.string_keys_num == 0) {
|
||||
lua_pop(lstate, 1);
|
||||
return ret;
|
||||
}
|
||||
ret.items = xcalloc(ret.size, sizeof(*ret.items));
|
||||
|
||||
lua_pushnil(lstate);
|
||||
for (size_t i = 0; lua_next(lstate, -2) && i < ret.size;) {
|
||||
for (size_t i = 0; lua_next(lstate, -2) && i < table_props.string_keys_num;) {
|
||||
// stack: dict, key, value
|
||||
|
||||
if (lua_type(lstate, -2) == LUA_TSTRING) {
|
||||
lua_pushvalue(lstate, -2);
|
||||
// stack: dict, key, value, key
|
||||
|
||||
ret.items[i].key = nlua_pop_String(lstate, err);
|
||||
String key = nlua_pop_String(lstate, arena, err);
|
||||
// stack: dict, key, value
|
||||
|
||||
if (!ERROR_SET(err)) {
|
||||
ret.items[i].value = nlua_pop_Object(lstate, ref, err);
|
||||
Object value = nlua_pop_Object(lstate, ref, arena, err);
|
||||
kv_push_c(ret, ((KeyValuePair) { .key = key, .value = value }));
|
||||
// stack: dict, key
|
||||
} else {
|
||||
lua_pop(lstate, 1);
|
||||
@ -1022,8 +1024,9 @@ static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate, const LuaTabl
|
||||
}
|
||||
|
||||
if (ERROR_SET(err)) {
|
||||
ret.size = i;
|
||||
api_free_dictionary(ret);
|
||||
if (!arena) {
|
||||
api_free_dictionary(ret);
|
||||
}
|
||||
lua_pop(lstate, 2);
|
||||
// stack:
|
||||
return (Dictionary) { .size = 0, .items = NULL };
|
||||
@ -1042,8 +1045,8 @@ static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate, const LuaTabl
|
||||
/// Convert lua table to dictionary
|
||||
///
|
||||
/// Always pops one value from the stack.
|
||||
Dictionary nlua_pop_Dictionary(lua_State *lstate, bool ref, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
Dictionary nlua_pop_Dictionary(lua_State *lstate, bool ref, Arena *arena, Error *err)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 4) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
const LuaTableProps table_props = nlua_check_type(lstate, err,
|
||||
kObjectTypeDictionary);
|
||||
@ -1052,7 +1055,7 @@ Dictionary nlua_pop_Dictionary(lua_State *lstate, bool ref, Error *err)
|
||||
return (Dictionary) { .size = 0, .items = NULL };
|
||||
}
|
||||
|
||||
return nlua_pop_Dictionary_unchecked(lstate, table_props, ref, err);
|
||||
return nlua_pop_Dictionary_unchecked(lstate, table_props, ref, arena, err);
|
||||
}
|
||||
|
||||
/// Helper structure for nlua_pop_Object
|
||||
@ -1064,7 +1067,8 @@ typedef struct {
|
||||
/// Convert lua table to object
|
||||
///
|
||||
/// Always pops one value from the stack.
|
||||
Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
|
||||
Object nlua_pop_Object(lua_State *const lstate, bool ref, Arena *arena, Error *const err)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 4) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
Object ret = NIL;
|
||||
const int initial_size = lua_gettop(lstate);
|
||||
@ -1099,10 +1103,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
|
||||
size_t len;
|
||||
const char *s = lua_tolstring(lstate, -2, &len);
|
||||
const size_t idx = cur.obj->data.dictionary.size++;
|
||||
cur.obj->data.dictionary.items[idx].key = (String) {
|
||||
.data = xmemdupz(s, len),
|
||||
.size = len,
|
||||
};
|
||||
cur.obj->data.dictionary.items[idx].key = CBUF_TO_ARENA_STR(arena, s, len);
|
||||
kvi_push(stack, cur);
|
||||
cur = (ObjPopStackItem){ .obj = &cur.obj->data.dictionary.items[idx].value };
|
||||
} else {
|
||||
@ -1133,7 +1134,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
|
||||
case LUA_TSTRING: {
|
||||
size_t len;
|
||||
const char *s = lua_tolstring(lstate, -1, &len);
|
||||
*cur.obj = STRING_OBJ(((String) { .data = xmemdupz(s, len), .size = len }));
|
||||
*cur.obj = STRING_OBJ(CBUF_TO_ARENA_STR(arena, s, len));
|
||||
break;
|
||||
}
|
||||
case LUA_TNUMBER: {
|
||||
@ -1151,23 +1152,17 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
|
||||
|
||||
switch (table_props.type) {
|
||||
case kObjectTypeArray:
|
||||
*cur.obj = ARRAY_OBJ(((Array) { .items = NULL, .size = 0, .capacity = 0 }));
|
||||
*cur.obj = ARRAY_OBJ(((Array)ARRAY_DICT_INIT));
|
||||
if (table_props.maxidx != 0) {
|
||||
cur.obj->data.array.items =
|
||||
xcalloc(table_props.maxidx,
|
||||
sizeof(cur.obj->data.array.items[0]));
|
||||
cur.obj->data.array.capacity = table_props.maxidx;
|
||||
cur.obj->data.array = arena_array(arena, table_props.maxidx);
|
||||
cur.container = true;
|
||||
kvi_push(stack, cur);
|
||||
}
|
||||
break;
|
||||
case kObjectTypeDictionary:
|
||||
*cur.obj = DICTIONARY_OBJ(((Dictionary) { .items = NULL, .size = 0, .capacity = 0 }));
|
||||
*cur.obj = DICTIONARY_OBJ(((Dictionary)ARRAY_DICT_INIT));
|
||||
if (table_props.string_keys_num != 0) {
|
||||
cur.obj->data.dictionary.items =
|
||||
xcalloc(table_props.string_keys_num,
|
||||
sizeof(cur.obj->data.dictionary.items[0]));
|
||||
cur.obj->data.dictionary.capacity = table_props.string_keys_num;
|
||||
cur.obj->data.dictionary = arena_dict(arena, table_props.string_keys_num);
|
||||
cur.container = true;
|
||||
kvi_push(stack, cur);
|
||||
lua_pushnil(lstate);
|
||||
@ -1219,7 +1214,9 @@ type_error:
|
||||
}
|
||||
kvi_destroy(stack);
|
||||
if (ERROR_SET(err)) {
|
||||
api_free_object(ret);
|
||||
if (!arena) {
|
||||
api_free_object(ret);
|
||||
}
|
||||
ret = NIL;
|
||||
lua_pop(lstate, lua_gettop(lstate) - initial_size + 1);
|
||||
}
|
||||
@ -1227,14 +1224,14 @@ type_error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
LuaRef nlua_pop_LuaRef(lua_State *const lstate, Error *err)
|
||||
LuaRef nlua_pop_LuaRef(lua_State *const lstate, Arena *arena, Error *err)
|
||||
{
|
||||
LuaRef rv = nlua_ref_global(lstate, -1);
|
||||
lua_pop(lstate, 1);
|
||||
return rv;
|
||||
}
|
||||
|
||||
handle_T nlua_pop_handle(lua_State *lstate, Error *err)
|
||||
handle_T nlua_pop_handle(lua_State *lstate, Arena *arena, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
handle_T ret;
|
||||
@ -1296,7 +1293,8 @@ void nlua_init_types(lua_State *const lstate)
|
||||
}
|
||||
|
||||
// lua specific variant of api_dict_to_keydict
|
||||
void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_opt, Error *err)
|
||||
void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_opt, Arena *arena,
|
||||
Error *err)
|
||||
{
|
||||
if (!lua_istable(L, -1)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Expected Lua table");
|
||||
@ -1323,7 +1321,7 @@ void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_
|
||||
char *mem = ((char *)retval + field->ptr_off);
|
||||
|
||||
if (field->type == kObjectTypeNil) {
|
||||
*(Object *)mem = nlua_pop_Object(L, true, err);
|
||||
*(Object *)mem = nlua_pop_Object(L, true, arena, err);
|
||||
} else if (field->type == kObjectTypeInteger) {
|
||||
if (field->is_hlgroup && lua_type(L, -1) == LUA_TSTRING) {
|
||||
size_t name_len;
|
||||
@ -1331,23 +1329,23 @@ void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_
|
||||
lua_pop(L, 1);
|
||||
*(Integer *)mem = name_len > 0 ? syn_check_group(name, name_len) : 0;
|
||||
} else {
|
||||
*(Integer *)mem = nlua_pop_Integer(L, err);
|
||||
*(Integer *)mem = nlua_pop_Integer(L, arena, err);
|
||||
}
|
||||
} else if (field->type == kObjectTypeBoolean) {
|
||||
*(Boolean *)mem = nlua_pop_Boolean_strict(L, err);
|
||||
} else if (field->type == kObjectTypeString) {
|
||||
*(String *)mem = nlua_pop_String(L, err);
|
||||
*(String *)mem = nlua_pop_String(L, arena, err);
|
||||
} else if (field->type == kObjectTypeFloat) {
|
||||
*(Float *)mem = nlua_pop_Float(L, err);
|
||||
*(Float *)mem = nlua_pop_Float(L, arena, err);
|
||||
} else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow
|
||||
|| field->type == kObjectTypeTabpage) {
|
||||
*(handle_T *)mem = nlua_pop_handle(L, err);
|
||||
*(handle_T *)mem = nlua_pop_handle(L, arena, err);
|
||||
} else if (field->type == kObjectTypeArray) {
|
||||
*(Array *)mem = nlua_pop_Array(L, err);
|
||||
*(Array *)mem = nlua_pop_Array(L, arena, err);
|
||||
} else if (field->type == kObjectTypeDictionary) {
|
||||
*(Dictionary *)mem = nlua_pop_Dictionary(L, false, err);
|
||||
*(Dictionary *)mem = nlua_pop_Dictionary(L, false, arena, err);
|
||||
} else if (field->type == kObjectTypeLuaRef) {
|
||||
*(LuaRef *)mem = nlua_pop_LuaRef(L, err);
|
||||
*(LuaRef *)mem = nlua_pop_LuaRef(L, arena, err);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
@ -311,7 +311,10 @@ static int nlua_thr_api_nvim__get_runtime(lua_State *lstate)
|
||||
lua_pop(lstate, 1);
|
||||
|
||||
Error err = ERROR_INIT;
|
||||
const Array pat = nlua_pop_Array(lstate, &err);
|
||||
// TODO(bfredl): we could use an arena here for both "pat" and "ret", but then
|
||||
// we need a path to not use the freelist but a private block local to the thread.
|
||||
// We do not want mutex contentionery for the main arena freelist.
|
||||
const Array pat = nlua_pop_Array(lstate, NULL, &err);
|
||||
if (ERROR_SET(&err)) {
|
||||
luaL_where(lstate, 1);
|
||||
lua_pushstring(lstate, err.msg);
|
||||
@ -1242,13 +1245,13 @@ static int nlua_rpc(lua_State *lstate, bool request)
|
||||
const char *name = luaL_checklstring(lstate, 2, &name_len);
|
||||
int nargs = lua_gettop(lstate) - 2;
|
||||
Error err = ERROR_INIT;
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
Arena arena = ARENA_EMPTY;
|
||||
|
||||
Array args = arena_array(&arena, (size_t)nargs);
|
||||
for (int i = 0; i < nargs; i++) {
|
||||
lua_pushvalue(lstate, i + 3);
|
||||
ADD(args, nlua_pop_Object(lstate, false, &err));
|
||||
ADD(args, nlua_pop_Object(lstate, false, &arena, &err));
|
||||
if (ERROR_SET(&err)) {
|
||||
api_free_array(args);
|
||||
goto check_err;
|
||||
}
|
||||
}
|
||||
@ -1265,10 +1268,11 @@ static int nlua_rpc(lua_State *lstate, bool request)
|
||||
api_set_error(&err, kErrorTypeValidation,
|
||||
"Invalid channel: %" PRIu64, chan_id);
|
||||
}
|
||||
api_free_array(args); // TODO(bfredl): no
|
||||
}
|
||||
|
||||
check_err:
|
||||
arena_mem_free(arena_finish(&arena));
|
||||
|
||||
if (ERROR_SET(&err)) {
|
||||
lua_pushstring(lstate, err.msg);
|
||||
api_clear_error(&err);
|
||||
@ -1541,10 +1545,12 @@ int typval_exec_lua_callable(LuaRef lua_cb, int argcount, typval_T *argvars, typ
|
||||
///
|
||||
/// @param[in] str String to execute.
|
||||
/// @param[in] args array of ... args
|
||||
/// @param[in] mode Whether and how the the return value should be converted to Object
|
||||
/// @param[in] arena can be NULL, then nested allocations are used
|
||||
/// @param[out] err Location where error will be saved.
|
||||
///
|
||||
/// @return Return value of the execution.
|
||||
Object nlua_exec(const String str, const Array args, Error *err)
|
||||
Object nlua_exec(const String str, const Array args, LuaRetMode mode, Arena *arena, Error *err)
|
||||
{
|
||||
lua_State *const lstate = global_lstate;
|
||||
|
||||
@ -1568,7 +1574,7 @@ Object nlua_exec(const String str, const Array args, Error *err)
|
||||
return NIL;
|
||||
}
|
||||
|
||||
return nlua_pop_Object(lstate, false, err);
|
||||
return nlua_call_pop_retval(lstate, mode, arena, err);
|
||||
}
|
||||
|
||||
bool nlua_ref_is_function(LuaRef ref)
|
||||
@ -1589,12 +1595,12 @@ bool nlua_ref_is_function(LuaRef ref)
|
||||
/// @param ref the reference to call (not consumed)
|
||||
/// @param name if non-NULL, sent to callback as first arg
|
||||
/// if NULL, only args are used
|
||||
/// @param retval if true, convert return value to Object
|
||||
/// if false, only check if return value is truthy
|
||||
/// @param mode Whether and how the the return value should be converted to Object
|
||||
/// @param arena can be NULL, then nested allocations are used
|
||||
/// @param err Error details, if any (if NULL, errors are echoed)
|
||||
/// @return Return value of function, if retval was set. Otherwise
|
||||
/// BOOLEAN_OBJ(true) or NIL.
|
||||
Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Error *err)
|
||||
/// @return Return value of function, as per mode
|
||||
Object nlua_call_ref(LuaRef ref, const char *name, Array args, LuaRetMode mode, Arena *arena,
|
||||
Error *err)
|
||||
{
|
||||
lua_State *const lstate = global_lstate;
|
||||
nlua_pushref(lstate, ref);
|
||||
@ -1620,18 +1626,34 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro
|
||||
return NIL;
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
Error dummy = ERROR_INIT;
|
||||
if (err == NULL) {
|
||||
err = &dummy;
|
||||
}
|
||||
return nlua_pop_Object(lstate, false, err);
|
||||
} else {
|
||||
bool value = lua_toboolean(lstate, -1);
|
||||
return nlua_call_pop_retval(lstate, mode, arena, err);
|
||||
}
|
||||
|
||||
static Object nlua_call_pop_retval(lua_State *lstate, LuaRetMode mode, Arena *arena, Error *err)
|
||||
{
|
||||
if (lua_isnil(lstate, -1)) {
|
||||
lua_pop(lstate, 1);
|
||||
return NIL;
|
||||
}
|
||||
Error dummy = ERROR_INIT;
|
||||
|
||||
switch (mode) {
|
||||
case kRetNilBool: {
|
||||
bool bool_value = lua_toboolean(lstate, -1);
|
||||
lua_pop(lstate, 1);
|
||||
|
||||
return value ? BOOLEAN_OBJ(true) : NIL;
|
||||
return BOOLEAN_OBJ(bool_value);
|
||||
}
|
||||
case kRetLuaref: {
|
||||
LuaRef ref = nlua_ref_global(lstate, -1);
|
||||
lua_pop(lstate, 1);
|
||||
|
||||
return LUAREF_OBJ(ref);
|
||||
}
|
||||
case kRetObject:
|
||||
return nlua_pop_Object(lstate, false, arena, err ? err : &dummy);
|
||||
}
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
/// check if the current execution context is safe for calling deferred API
|
||||
@ -1930,13 +1952,14 @@ int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results)
|
||||
*num_results = 0;
|
||||
*results = NULL;
|
||||
|
||||
int prefix_len = (int)nlua_pop_Integer(lstate, &err);
|
||||
Arena arena = ARENA_EMPTY;
|
||||
int prefix_len = (int)nlua_pop_Integer(lstate, &arena, &err);
|
||||
if (ERROR_SET(&err)) {
|
||||
ret = FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
Array completions = nlua_pop_Array(lstate, &err);
|
||||
Array completions = nlua_pop_Array(lstate, &arena, &err);
|
||||
if (ERROR_SET(&err)) {
|
||||
ret = FAIL;
|
||||
goto cleanup_array;
|
||||
@ -1960,7 +1983,7 @@ int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results)
|
||||
*num_results = result_array.ga_len;
|
||||
|
||||
cleanup_array:
|
||||
api_free_array(completions);
|
||||
arena_mem_free(arena_finish(&arena));
|
||||
|
||||
cleanup:
|
||||
|
||||
@ -2354,13 +2377,10 @@ bool nlua_func_exists(const char *lua_funcname)
|
||||
vim_snprintf(str, length, "return %s", lua_funcname);
|
||||
ADD_C(args, CSTR_AS_OBJ(str));
|
||||
Error err = ERROR_INIT;
|
||||
Object result = NLUA_EXEC_STATIC("return type(loadstring(...)()) == 'function'", args, &err);
|
||||
Object result = NLUA_EXEC_STATIC("return type(loadstring(...)()) == 'function'", args,
|
||||
kRetNilBool, NULL, &err);
|
||||
xfree(str);
|
||||
|
||||
api_clear_error(&err);
|
||||
if (result.type != kObjectTypeBoolean) {
|
||||
api_free_object(result);
|
||||
return false;
|
||||
}
|
||||
return result.data.boolean;
|
||||
return LUARET_TRUTHY(result);
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ typedef struct {
|
||||
#endif
|
||||
} nlua_ref_state_t;
|
||||
|
||||
#define NLUA_EXEC_STATIC(cstr, arg, err) nlua_exec(STATIC_CSTR_AS_STRING(cstr), arg, err)
|
||||
#define NLUA_EXEC_STATIC(cstr, arg, mode, arena, err) \
|
||||
nlua_exec(STATIC_CSTR_AS_STRING(cstr), arg, mode, arena, err)
|
||||
|
||||
#define NLUA_CLEAR_REF(x) \
|
||||
do { \
|
||||
@ -35,6 +36,16 @@ typedef struct {
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef enum {
|
||||
kRetObject, ///< any object, but doesn't preserve nested luarefs
|
||||
kRetNilBool, ///< NIL preserved as such, other values return their booleanness
|
||||
///< Should also be used when return value is ignored, as it is allocation-free
|
||||
kRetLuaref, ///< return value becomes a single Luaref, regardless of type (except NIL)
|
||||
} LuaRetMode;
|
||||
|
||||
/// To use with kRetNilBool for quick thuthyness check
|
||||
#define LUARET_TRUTHY(res) ((res).type == kObjectTypeBoolean && (res).data.boolean == true)
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "lua/executor.h.generated.h"
|
||||
#endif
|
||||
|
@ -209,7 +209,8 @@ static bool check_xdiff_opt(ObjectType actType, ObjectType expType, const char *
|
||||
static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg, xpparam_t *params,
|
||||
int64_t *linematch, Error *err)
|
||||
{
|
||||
const DictionaryOf(LuaRef) opts = nlua_pop_Dictionary(lstate, true, err);
|
||||
// TODO: this is very much a keydict..
|
||||
const DictionaryOf(LuaRef) opts = nlua_pop_Dictionary(lstate, true, NULL, err);
|
||||
|
||||
NluaXdiffMode mode = kNluaXdiffModeUnified;
|
||||
|
||||
|
@ -940,20 +940,20 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
|
||||
}
|
||||
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
kv_resize(args, (size_t)(argc - remote_args));
|
||||
for (int t_argc = remote_args; t_argc < argc; t_argc++) {
|
||||
String arg_s = cstr_to_string(argv[t_argc]);
|
||||
ADD(args, STRING_OBJ(arg_s));
|
||||
ADD_C(args, CSTR_AS_OBJ(argv[t_argc]));
|
||||
}
|
||||
|
||||
Error err = ERROR_INIT;
|
||||
Array a = ARRAY_DICT_INIT;
|
||||
MAXSIZE_TEMP_ARRAY(a, 4);
|
||||
ADD(a, INTEGER_OBJ((int)chan));
|
||||
ADD(a, CSTR_TO_OBJ(server_addr));
|
||||
ADD(a, CSTR_TO_OBJ(connect_error));
|
||||
ADD(a, CSTR_AS_OBJ(server_addr));
|
||||
ADD(a, CSTR_AS_OBJ(connect_error));
|
||||
ADD(a, ARRAY_OBJ(args));
|
||||
String s = STATIC_CSTR_AS_STRING("return vim._cs_remote(...)");
|
||||
Object o = nlua_exec(s, a, &err);
|
||||
api_free_array(a);
|
||||
Object o = nlua_exec(s, a, kRetObject, NULL, &err);
|
||||
kv_destroy(args);
|
||||
if (ERROR_SET(&err)) {
|
||||
fprintf(stderr, "%s\n", err.msg);
|
||||
os_exit(2);
|
||||
@ -2085,7 +2085,7 @@ static void do_exrc_initialization(void)
|
||||
str = nlua_read_secure(VIMRC_LUA_FILE);
|
||||
if (str != NULL) {
|
||||
Error err = ERROR_INIT;
|
||||
nlua_exec(cstr_as_string(str), (Array)ARRAY_DICT_INIT, &err);
|
||||
nlua_exec(cstr_as_string(str), (Array)ARRAY_DICT_INIT, kRetNilBool, NULL, &err);
|
||||
xfree(str);
|
||||
if (ERROR_SET(&err)) {
|
||||
semsg("Error detected while processing %s:", VIMRC_LUA_FILE);
|
||||
|
@ -1644,7 +1644,7 @@ char *eval_map_expr(mapblock_T *mp, int c)
|
||||
if (mp->m_luaref != LUA_NOREF) {
|
||||
Error err = ERROR_INIT;
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
Object ret = nlua_call_ref(mp->m_luaref, NULL, args, true, &err);
|
||||
Object ret = nlua_call_ref(mp->m_luaref, NULL, args, kRetObject, NULL, &err);
|
||||
if (ret.type == kObjectTypeString) {
|
||||
p = string_to_cstr(ret.data.string);
|
||||
}
|
||||
|
@ -192,7 +192,6 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem
|
||||
|
||||
if (!(channel = find_rpc_channel(id))) {
|
||||
api_set_error(err, kErrorTypeException, "Invalid channel: %" PRIu64, id);
|
||||
api_free_array(args);
|
||||
return NIL;
|
||||
}
|
||||
|
||||
@ -201,7 +200,6 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem
|
||||
uint32_t request_id = rpc->next_request_id++;
|
||||
// Send the msgpack-rpc request
|
||||
send_request(channel, request_id, method_name, args);
|
||||
api_free_array(args);
|
||||
|
||||
// Push the frame
|
||||
ChannelCallFrame frame = { request_id, false, false, NIL, NULL };
|
||||
|
@ -592,13 +592,13 @@ Array runtime_inspect(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
ArrayOf(String) runtime_get_named(bool lua, Array pat, bool all)
|
||||
ArrayOf(String) runtime_get_named(bool lua, Array pat, bool all, Arena *arena)
|
||||
{
|
||||
int ref;
|
||||
RuntimeSearchPath path = runtime_search_path_get_cached(&ref);
|
||||
static char buf[MAXPATHL];
|
||||
|
||||
ArrayOf(String) rv = runtime_get_named_common(lua, pat, all, path, buf, sizeof buf);
|
||||
ArrayOf(String) rv = runtime_get_named_common(lua, pat, all, path, buf, sizeof buf, arena);
|
||||
|
||||
runtime_search_path_unref(path, &ref);
|
||||
return rv;
|
||||
@ -610,15 +610,16 @@ ArrayOf(String) runtime_get_named_thread(bool lua, Array pat, bool all)
|
||||
uv_mutex_lock(&runtime_search_path_mutex);
|
||||
static char buf[MAXPATHL];
|
||||
ArrayOf(String) rv = runtime_get_named_common(lua, pat, all, runtime_search_path_thread,
|
||||
buf, sizeof buf);
|
||||
buf, sizeof buf, NULL);
|
||||
uv_mutex_unlock(&runtime_search_path_mutex);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static ArrayOf(String) runtime_get_named_common(bool lua, Array pat, bool all,
|
||||
RuntimeSearchPath path, char *buf, size_t buf_len)
|
||||
RuntimeSearchPath path, char *buf, size_t buf_len,
|
||||
Arena *arena)
|
||||
{
|
||||
ArrayOf(String) rv = ARRAY_DICT_INIT;
|
||||
ArrayOf(String) rv = arena_array(arena, kv_size(path) * pat.size);
|
||||
for (size_t i = 0; i < kv_size(path); i++) {
|
||||
SearchPathItem *item = &kv_A(path, i);
|
||||
if (lua) {
|
||||
@ -638,7 +639,7 @@ static ArrayOf(String) runtime_get_named_common(bool lua, Array pat, bool all,
|
||||
item->path, pat_item.data.string.data);
|
||||
if (size < buf_len) {
|
||||
if (os_file_is_readable(buf)) {
|
||||
ADD(rv, CSTR_TO_OBJ(buf));
|
||||
ADD_C(rv, CSTR_TO_ARENA_OBJ(arena, buf));
|
||||
if (!all) {
|
||||
goto done;
|
||||
}
|
||||
|
@ -710,8 +710,8 @@ void ui_call_event(char *name, Array args)
|
||||
bool handled = false;
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
Error err = ERROR_INIT;
|
||||
Object res = nlua_call_ref(event_cb->cb, name, args, false, &err);
|
||||
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
|
||||
Object res = nlua_call_ref(event_cb->cb, name, args, kRetNilBool, NULL, &err);
|
||||
if (LUARET_TRUTHY(res)) {
|
||||
handled = true;
|
||||
}
|
||||
if (ERROR_SET(&err)) {
|
||||
|
@ -170,7 +170,7 @@ Object handle_ui_client_redraw(uint64_t channel_id, Array args, Arena *arena, Er
|
||||
static HlAttrs ui_client_dict2hlattrs(Dictionary d, bool rgb)
|
||||
{
|
||||
Error err = ERROR_INIT;
|
||||
Dict(highlight) dict = { 0 };
|
||||
Dict(highlight) dict = KEYDICT_INIT;
|
||||
if (!api_dict_to_keydict(&dict, KeyDict_highlight_get_field, d, &err)) {
|
||||
// TODO(bfredl): log "err"
|
||||
return HLATTRS_INIT;
|
||||
|
@ -2681,9 +2681,9 @@ void list_in_columns(char **items, int size, int current)
|
||||
|
||||
void list_lua_version(void)
|
||||
{
|
||||
char *code = "return ((jit and jit.version) and jit.version or _VERSION)";
|
||||
Error err = ERROR_INIT;
|
||||
Object ret = nlua_exec(cstr_as_string(code), (Array)ARRAY_DICT_INIT, &err);
|
||||
Object ret = NLUA_EXEC_STATIC("return ((jit and jit.version) and jit.version or _VERSION)",
|
||||
(Array)ARRAY_DICT_INIT, kRetObject, NULL, &err);
|
||||
assert(!ERROR_SET(&err));
|
||||
assert(ret.type == kObjectTypeString);
|
||||
msg(ret.data.string.data, 0);
|
||||
|
@ -3543,6 +3543,18 @@ describe('lua stdlib', function()
|
||||
]])
|
||||
)
|
||||
end)
|
||||
|
||||
it('can return values by reference', function()
|
||||
eq(
|
||||
{ 4, 7 },
|
||||
exec_lua [[
|
||||
local val = {4, 10}
|
||||
local ref = vim.api.nvim_buf_call(0, function() return val end)
|
||||
ref[2] = 7
|
||||
return val
|
||||
]]
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('vim.api.nvim_win_call', function()
|
||||
@ -3640,6 +3652,18 @@ describe('lua stdlib', function()
|
||||
|
|
||||
]]
|
||||
end)
|
||||
|
||||
it('can return values by reference', function()
|
||||
eq(
|
||||
{ 7, 10 },
|
||||
exec_lua [[
|
||||
local val = {4, 10}
|
||||
local ref = vim.api.nvim_win_call(0, function() return val end)
|
||||
ref[1] = 7
|
||||
return val
|
||||
]]
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('vim.iconv', function()
|
||||
|
Loading…
Reference in New Issue
Block a user