api/lua: make nvim_execute_lua use native lua floats, not special tables

Rationale: the purpose of nvim_execute_lua is to simply call lua code with lua
values. If a lua function expects a floating point value, it should be enough
to specify a float as argument to nvim_execute_lua.

However, make sure to preserve the existing roundtripping behavior of
API values when using `vim.api` functions. This is covered by existing
lua/api_spec.lua tests.
This commit is contained in:
Björn Linse 2019-07-01 15:50:57 +02:00
parent 740fb337dd
commit 6ee05536ca
4 changed files with 35 additions and 21 deletions

View File

@ -441,7 +441,7 @@ local function process_function(fn)
end end
write_shifted_output(output, string.format([[ write_shifted_output(output, string.format([[
const %s ret = %s(%s); const %s ret = %s(%s);
nlua_push_%s(lstate, ret); nlua_push_%s(lstate, ret, true);
api_free_%s(ret); api_free_%s(ret);
%s %s
%s %s

View File

@ -615,7 +615,7 @@ static inline void nlua_create_typed_table(lua_State *lstate,
/// Convert given String to lua string /// Convert given String to lua string
/// ///
/// Leaves converted string on top of the stack. /// Leaves converted string on top of the stack.
void nlua_push_String(lua_State *lstate, const String s) void nlua_push_String(lua_State *lstate, const String s, bool special)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
lua_pushlstring(lstate, s.data, s.size); lua_pushlstring(lstate, s.data, s.size);
@ -624,7 +624,7 @@ void nlua_push_String(lua_State *lstate, const String s)
/// Convert given Integer to lua number /// Convert given Integer to lua number
/// ///
/// Leaves converted number on top of the stack. /// Leaves converted number on top of the stack.
void nlua_push_Integer(lua_State *lstate, const Integer n) void nlua_push_Integer(lua_State *lstate, const Integer n, bool special)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
lua_pushnumber(lstate, (lua_Number)n); lua_pushnumber(lstate, (lua_Number)n);
@ -633,19 +633,23 @@ void nlua_push_Integer(lua_State *lstate, const Integer n)
/// Convert given Float to lua table /// Convert given Float to lua table
/// ///
/// Leaves converted table on top of the stack. /// Leaves converted table on top of the stack.
void nlua_push_Float(lua_State *lstate, const Float f) void nlua_push_Float(lua_State *lstate, const Float f, bool special)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
nlua_create_typed_table(lstate, 0, 1, kObjectTypeFloat); if (special) {
nlua_push_val_idx(lstate); nlua_create_typed_table(lstate, 0, 1, kObjectTypeFloat);
lua_pushnumber(lstate, (lua_Number)f); nlua_push_val_idx(lstate);
lua_rawset(lstate, -3); lua_pushnumber(lstate, (lua_Number)f);
lua_rawset(lstate, -3);
} else {
lua_pushnumber(lstate, (lua_Number)f);
}
} }
/// Convert given Float to lua boolean /// Convert given Float to lua boolean
/// ///
/// Leaves converted value on top of the stack. /// Leaves converted value on top of the stack.
void nlua_push_Boolean(lua_State *lstate, const Boolean b) void nlua_push_Boolean(lua_State *lstate, const Boolean b, bool special)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
lua_pushboolean(lstate, b); lua_pushboolean(lstate, b);
@ -654,17 +658,18 @@ void nlua_push_Boolean(lua_State *lstate, const Boolean b)
/// Convert given Dictionary to lua table /// Convert given Dictionary to lua table
/// ///
/// Leaves converted table on top of the stack. /// Leaves converted table on top of the stack.
void nlua_push_Dictionary(lua_State *lstate, const Dictionary dict) void nlua_push_Dictionary(lua_State *lstate, const Dictionary dict,
bool special)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
if (dict.size == 0) { if (dict.size == 0 && special) {
nlua_create_typed_table(lstate, 0, 0, kObjectTypeDictionary); nlua_create_typed_table(lstate, 0, 0, kObjectTypeDictionary);
} else { } else {
lua_createtable(lstate, 0, (int)dict.size); lua_createtable(lstate, 0, (int)dict.size);
} }
for (size_t i = 0; i < dict.size; i++) { for (size_t i = 0; i < dict.size; i++) {
nlua_push_String(lstate, dict.items[i].key); nlua_push_String(lstate, dict.items[i].key, special);
nlua_push_Object(lstate, dict.items[i].value); nlua_push_Object(lstate, dict.items[i].value, special);
lua_rawset(lstate, -3); lua_rawset(lstate, -3);
} }
} }
@ -672,18 +677,18 @@ void nlua_push_Dictionary(lua_State *lstate, const Dictionary dict)
/// Convert given Array to lua table /// Convert given Array to lua table
/// ///
/// Leaves converted table on top of the stack. /// Leaves converted table on top of the stack.
void nlua_push_Array(lua_State *lstate, const Array array) void nlua_push_Array(lua_State *lstate, const Array array, bool special)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
lua_createtable(lstate, (int)array.size, 0); lua_createtable(lstate, (int)array.size, 0);
for (size_t i = 0; i < array.size; i++) { for (size_t i = 0; i < array.size; i++) {
nlua_push_Object(lstate, array.items[i]); nlua_push_Object(lstate, array.items[i], special);
lua_rawseti(lstate, -2, (int)i + 1); lua_rawseti(lstate, -2, (int)i + 1);
} }
} }
#define GENERATE_INDEX_FUNCTION(type) \ #define GENERATE_INDEX_FUNCTION(type) \
void nlua_push_##type(lua_State *lstate, const type item) \ void nlua_push_##type(lua_State *lstate, const type item, bool special) \
FUNC_ATTR_NONNULL_ALL \ FUNC_ATTR_NONNULL_ALL \
{ \ { \
lua_pushnumber(lstate, (lua_Number)(item)); \ lua_pushnumber(lstate, (lua_Number)(item)); \
@ -698,7 +703,7 @@ GENERATE_INDEX_FUNCTION(Tabpage)
/// Convert given Object to lua value /// Convert given Object to lua value
/// ///
/// Leaves converted value on top of the stack. /// Leaves converted value on top of the stack.
void nlua_push_Object(lua_State *lstate, const Object obj) void nlua_push_Object(lua_State *lstate, const Object obj, bool special)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
switch (obj.type) { switch (obj.type) {
@ -712,7 +717,7 @@ void nlua_push_Object(lua_State *lstate, const Object obj)
} }
#define ADD_TYPE(type, data_key) \ #define ADD_TYPE(type, data_key) \
case kObjectType##type: { \ case kObjectType##type: { \
nlua_push_##type(lstate, obj.data.data_key); \ nlua_push_##type(lstate, obj.data.data_key, special); \
break; \ break; \
} }
ADD_TYPE(Boolean, boolean) ADD_TYPE(Boolean, boolean)
@ -724,7 +729,7 @@ void nlua_push_Object(lua_State *lstate, const Object obj)
#undef ADD_TYPE #undef ADD_TYPE
#define ADD_REMOTE_TYPE(type) \ #define ADD_REMOTE_TYPE(type) \
case kObjectType##type: { \ case kObjectType##type: { \
nlua_push_##type(lstate, (type)obj.data.integer); \ nlua_push_##type(lstate, (type)obj.data.integer, special); \
break; \ break; \
} }
ADD_REMOTE_TYPE(Buffer) ADD_REMOTE_TYPE(Buffer)

View File

@ -562,7 +562,7 @@ Object executor_exec_lua_api(const String str, const Array args, Error *err)
} }
for (size_t i = 0; i < args.size; i++) { for (size_t i = 0; i < args.size; i++) {
nlua_push_Object(lstate, args.items[i]); nlua_push_Object(lstate, args.items[i], false);
} }
if (lua_pcall(lstate, (int)args.size, 1, 0)) { if (lua_pcall(lstate, (int)args.size, 1, 0)) {
@ -583,7 +583,7 @@ Object executor_exec_lua_cb(LuaRef ref, const char *name, Array args,
nlua_pushref(lstate, ref); nlua_pushref(lstate, ref);
lua_pushstring(lstate, name); lua_pushstring(lstate, name);
for (size_t i = 0; i < args.size; i++) { for (size_t i = 0; i < args.size; i++) {
nlua_push_Object(lstate, args.items[i]); nlua_push_Object(lstate, args.items[i], false);
} }
if (lua_pcall(lstate, (int)args.size+1, retval ? 1 : 0, 0)) { if (lua_pcall(lstate, (int)args.size+1, retval ? 1 : 0, 0)) {

View File

@ -339,6 +339,15 @@ describe('API', function()
"did\nthe\nfail"}, "did\nthe\nfail"},
meth_pcall(meths.execute_lua, 'error("did\\nthe\\nfail")', {})) meth_pcall(meths.execute_lua, 'error("did\\nthe\\nfail")', {}))
end) end)
it('uses native float values', function()
eq(2.5, meths.execute_lua("return select(1, ...)", {2.5}))
eq("2.5", meths.execute_lua("return vim.inspect(...)", {2.5}))
-- "special" float values are still accepted as return values.
eq(2.5, meths.execute_lua("return vim.api.nvim_eval('2.5')", {}))
eq("{\n [false] = 2.5,\n [true] = 3\n}", meths.execute_lua("return vim.inspect(vim.api.nvim_eval('2.5'))", {}))
end)
end) end)
describe('nvim_input', function() describe('nvim_input', function()