aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua/converter.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-30 20:35:25 +0000
commit1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (patch)
treecd08258054db80bb9a11b1061bb091c70b76926a /src/nvim/lua/converter.c
parenteaa89c11d0f8aefbb512de769c6c82f61a8baca3 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.tar.gz
rneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.tar.bz2
rneovim-1b7b916b7631ddf73c38e3a0070d64e4636cb2f3.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpostaucmd_textputpost
Diffstat (limited to 'src/nvim/lua/converter.c')
-rw-r--r--src/nvim/lua/converter.c149
1 files changed, 100 insertions, 49 deletions
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 6160b84485..4598d48c4a 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
#include <assert.h>
#include <lauxlib.h>
#include <lua.h>
@@ -10,26 +7,24 @@
#include <stdlib.h>
#include <string.h>
+#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/memory.h"
-// FIXME: vim.h is not actually needed, but otherwise it states MAXPATHL is
-// redefined
-#include "klib/kvec.h"
-#include "nvim/ascii.h"
+#include "nvim/ascii_defs.h"
#include "nvim/eval/decode.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/typval_encode.h"
#include "nvim/eval/userfunc.h"
-#include "nvim/garray.h"
+#include "nvim/func_attr.h"
#include "nvim/gettext.h"
#include "nvim/lua/converter.h"
#include "nvim/lua/executor.h"
-#include "nvim/macros.h"
+#include "nvim/macros_defs.h"
+#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/types.h"
-#include "nvim/vim.h"
+#include "nvim/types_defs.h"
+#include "nvim/vim_defs.h"
/// Determine, which keys lua table contains
typedef struct {
@@ -183,7 +178,7 @@ typedef struct {
int idx; ///< Container index (used to detect self-referencing structures).
} TVPopStackItem;
-/// Convert lua object to VimL typval_T
+/// Convert lua object to Vimscript typval_T
///
/// Should pop exactly one value from lua stack.
///
@@ -459,7 +454,7 @@ static bool typval_conv_special = false;
TYPVAL_ENCODE_CONV_NUMBER(tv, flt)
#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \
- lua_pushlstring(lstate, (const char *)(str), (len))
+ lua_pushlstring(lstate, (str), (len))
#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING
@@ -469,9 +464,7 @@ static bool typval_conv_special = false;
#define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \
do { \
const blob_T *const blob_ = (blob); \
- lua_pushlstring(lstate, \
- blob_ != NULL ? (const char *)blob_->bv_ga.ga_data : "", \
- (size_t)(len)); \
+ lua_pushlstring(lstate, blob_ != NULL ? blob_->bv_ga.ga_data : "", (size_t)(len)); \
} while (0)
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
@@ -603,7 +596,7 @@ static bool typval_conv_special = false;
#undef TYPVAL_ENCODE_CONV_RECURSE
#undef TYPVAL_ENCODE_ALLOW_SPECIALS
-/// Convert VimL typval_T to lua value
+/// Convert Vimscript typval_T to lua value
///
/// Should leave single value in lua stack. May only fail if lua failed to grow
/// stack.
@@ -630,8 +623,7 @@ bool nlua_push_typval(lua_State *lstate, typval_T *const tv, bool special)
/// Push value which is a type index
///
-/// Used for all “typed” tables: i.e. for all tables which represent VimL
-/// values.
+/// Used for all “typed” tables: i.e. for all tables which represent Vimscript values.
static inline void nlua_push_type_idx(lua_State *lstate)
FUNC_ATTR_NONNULL_ALL
{
@@ -659,7 +651,7 @@ static inline void nlua_push_type(lua_State *lstate, ObjectType type)
lua_pushnumber(lstate, (lua_Number)type);
}
-/// Create lua table which has an entry that determines its VimL type
+/// Create Lua table which has an entry that determines its Vimscript type
///
/// @param[out] lstate Lua state.
/// @param[in] narr Number of “array” entries to be populated later.
@@ -816,7 +808,7 @@ String nlua_pop_String(lua_State *lstate, Error *err)
{
if (lua_type(lstate, -1) != LUA_TSTRING) {
lua_pop(lstate, 1);
- api_set_error(err, kErrorTypeValidation, "Expected lua string");
+ api_set_error(err, kErrorTypeValidation, "Expected Lua string");
return (String) { .size = 0, .data = NULL };
}
String ret;
@@ -837,7 +829,7 @@ Integer nlua_pop_Integer(lua_State *lstate, Error *err)
{
if (lua_type(lstate, -1) != LUA_TNUMBER) {
lua_pop(lstate, 1);
- api_set_error(err, kErrorTypeValidation, "Expected lua number");
+ api_set_error(err, kErrorTypeValidation, "Expected Lua number");
return 0;
}
const lua_Number n = lua_tonumber(lstate, -1);
@@ -852,6 +844,9 @@ Integer nlua_pop_Integer(lua_State *lstate, Error *err)
/// Convert lua value to boolean
///
+/// Despite the name of the function, this uses lua semantics for booleans.
+/// 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
@@ -861,6 +856,36 @@ Boolean nlua_pop_Boolean(lua_State *lstate, Error *err)
return ret;
}
+/// Convert lua value to boolean
+///
+/// This follows API conventions for a Boolean value, compare api_object_to_bool
+///
+/// Always pops one value from the stack.
+Boolean nlua_pop_Boolean_strict(lua_State *lstate, Error *err)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ Boolean ret = false;
+ switch (lua_type(lstate, -1)) {
+ case LUA_TBOOLEAN:
+ ret = lua_toboolean(lstate, -1);
+ break;
+
+ case LUA_TNUMBER:
+ ret = (lua_tonumber(lstate, -1) != 0);
+ break;
+
+ case LUA_TNIL:
+ ret = false;
+ break;
+
+ default:
+ api_set_error(err, kErrorTypeValidation, "not a boolean");
+ }
+
+ lua_pop(lstate, 1);
+ return ret;
+}
+
/// Check whether typed table on top of the stack has given type
///
/// @param[in] lstate Lua state.
@@ -874,7 +899,8 @@ static inline LuaTableProps nlua_check_type(lua_State *const lstate, Error *cons
{
if (lua_type(lstate, -1) != LUA_TTABLE) {
if (err) {
- api_set_error(err, kErrorTypeValidation, "Expected lua table");
+ api_set_error(err, kErrorTypeValidation, "Expected Lua %s",
+ (type == kObjectTypeFloat) ? "number" : "table");
}
return (LuaTableProps) { .type = kObjectTypeNil };
}
@@ -887,7 +913,7 @@ static inline LuaTableProps nlua_check_type(lua_State *const lstate, Error *cons
if (table_props.type != type) {
if (err) {
- api_set_error(err, kErrorTypeValidation, "Unexpected type");
+ api_set_error(err, kErrorTypeValidation, "Expected %s-like Lua table", api_typename(type));
}
}
@@ -1171,7 +1197,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
break;
case kObjectTypeNil:
api_set_error(err, kErrorTypeValidation,
- "Cannot convert given lua table");
+ "Cannot convert given Lua table");
break;
default:
abort();
@@ -1227,26 +1253,19 @@ LuaRef nlua_pop_LuaRef(lua_State *const lstate, Error *err)
return rv;
}
-#define GENERATE_INDEX_FUNCTION(type) \
- type nlua_pop_##type(lua_State *lstate, Error *err) \
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \
- { \
- type ret; \
- if (lua_type(lstate, -1) != LUA_TNUMBER) { \
- api_set_error(err, kErrorTypeValidation, "Expected Lua number"); \
- ret = (type) - 1; \
- } else { \
- ret = (type)lua_tonumber(lstate, -1); \
- } \
- lua_pop(lstate, 1); \
- return ret; \
+handle_T nlua_pop_handle(lua_State *lstate, Error *err)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ handle_T ret;
+ if (lua_type(lstate, -1) != LUA_TNUMBER) {
+ api_set_error(err, kErrorTypeValidation, "Expected Lua number");
+ ret = (handle_T) - 1;
+ } else {
+ ret = (handle_T)lua_tonumber(lstate, -1);
}
-
-GENERATE_INDEX_FUNCTION(Buffer)
-GENERATE_INDEX_FUNCTION(Window)
-GENERATE_INDEX_FUNCTION(Tabpage)
-
-#undef GENERATE_INDEX_FUNCTION
+ lua_pop(lstate, 1);
+ return ret;
+}
/// Record some auxiliary values in vim module
///
@@ -1295,10 +1314,11 @@ void nlua_init_types(lua_State *const lstate)
lua_rawset(lstate, -3);
}
-void nlua_pop_keydict(lua_State *L, void *retval, field_hash hashy, Error *err)
+// lua specific variant of api_dict_to_keydict
+void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_opt, Error *err)
{
if (!lua_istable(L, -1)) {
- api_set_error(err, kErrorTypeValidation, "Expected lua table");
+ api_set_error(err, kErrorTypeValidation, "Expected Lua table");
lua_pop(L, -1);
return;
}
@@ -1308,14 +1328,45 @@ void nlua_pop_keydict(lua_State *L, void *retval, field_hash hashy, Error *err)
// [dict, key, value]
size_t len;
const char *s = lua_tolstring(L, -2, &len);
- Object *field = hashy(retval, s, len);
+ KeySetLink *field = hashy(s, len);
if (!field) {
api_set_error(err, kErrorTypeValidation, "invalid key: %.*s", (int)len, s);
lua_pop(L, 3); // []
return;
}
- *field = nlua_pop_Object(L, true, err);
+ if (field->opt_index >= 0) {
+ OptKeySet *ks = (OptKeySet *)retval;
+ ks->is_set_ |= (1ULL << field->opt_index);
+ }
+ char *mem = ((char *)retval + field->ptr_off);
+
+ if (field->type == kObjectTypeNil) {
+ *(Object *)mem = nlua_pop_Object(L, true, err);
+ } else if (field->type == kObjectTypeInteger) {
+ *(Integer *)mem = nlua_pop_Integer(L, 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);
+ } else if (field->type == kObjectTypeFloat) {
+ *(Float *)mem = nlua_pop_Float(L, err);
+ } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow
+ || field->type == kObjectTypeTabpage) {
+ *(handle_T *)mem = nlua_pop_handle(L, err);
+ } else if (field->type == kObjectTypeArray) {
+ *(Array *)mem = nlua_pop_Array(L, err);
+ } else if (field->type == kObjectTypeDictionary) {
+ *(Dictionary *)mem = nlua_pop_Dictionary(L, false, err);
+ } else if (field->type == kObjectTypeLuaRef) {
+ *(LuaRef *)mem = nlua_pop_LuaRef(L, err);
+ } else {
+ abort();
+ }
+ if (ERROR_SET(err)) {
+ *err_opt = field->str;
+ break;
+ }
}
// [dict]
lua_pop(L, 1);