mirror of
https://github.com/neovim/neovim.git
synced 2025-10-13 13:26:06 +00:00
Merge pull request #20100 from bfredl/luafunc
refactor(typval): change FC_CFUNC abstraction into FC_LUAREF
This commit is contained in:
@@ -65,8 +65,8 @@ typedef struct {
|
|||||||
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
|
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
|
||||||
do { \
|
do { \
|
||||||
ufunc_T *fp = find_func(fun); \
|
ufunc_T *fp = find_func(fun); \
|
||||||
if (fp != NULL && fp->uf_cb == nlua_CFunction_func_call) { \
|
if (fp != NULL && (fp->uf_flags & FC_LUAREF)) { \
|
||||||
LuaRef ref = api_new_luaref(((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \
|
LuaRef ref = api_new_luaref(fp->uf_luaref); \
|
||||||
kvi_push(edata->stack, LUAREF_OBJ(ref)); \
|
kvi_push(edata->stack, LUAREF_OBJ(ref)); \
|
||||||
} else { \
|
} else { \
|
||||||
TYPVAL_ENCODE_CONV_NIL(tv); \
|
TYPVAL_ENCODE_CONV_NIL(tv); \
|
||||||
@@ -351,10 +351,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case kObjectTypeLuaRef: {
|
case kObjectTypeLuaRef: {
|
||||||
LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState));
|
char *name = (char *)register_luafunc(api_new_luaref(obj.data.luaref));
|
||||||
state->lua_callable.func_ref = api_new_luaref(obj.data.luaref);
|
|
||||||
char *name =
|
|
||||||
(char *)register_cfunc(&nlua_CFunction_func_call, &nlua_CFunction_func_free, state);
|
|
||||||
tv->v_type = VAR_FUNC;
|
tv->v_type = VAR_FUNC;
|
||||||
tv->vval.v_string = xstrdup(name);
|
tv->vval.v_string = xstrdup(name);
|
||||||
break;
|
break;
|
||||||
|
@@ -286,12 +286,6 @@ typedef struct {
|
|||||||
/// Number of fixed variables used for arguments
|
/// Number of fixed variables used for arguments
|
||||||
#define FIXVAR_CNT 12
|
#define FIXVAR_CNT 12
|
||||||
|
|
||||||
/// Callback interface for C function reference>
|
|
||||||
/// Used for managing functions that were registered with |register_cfunc|
|
|
||||||
typedef int (*cfunc_T)(int argcount, typval_T *argvars, typval_T *rettv, void *state); // NOLINT
|
|
||||||
/// Callback to clear cfunc_T and any associated state.
|
|
||||||
typedef void (*cfunc_free_T)(void *state);
|
|
||||||
|
|
||||||
// Structure to hold info for a function that is currently being executed.
|
// Structure to hold info for a function that is currently being executed.
|
||||||
typedef struct funccall_S funccall_T;
|
typedef struct funccall_S funccall_T;
|
||||||
|
|
||||||
@@ -330,10 +324,7 @@ struct ufunc {
|
|||||||
garray_T uf_lines; ///< function lines
|
garray_T uf_lines; ///< function lines
|
||||||
int uf_profiling; ///< true when func is being profiled
|
int uf_profiling; ///< true when func is being profiled
|
||||||
int uf_prof_initialized;
|
int uf_prof_initialized;
|
||||||
// Managing cfuncs
|
LuaRef uf_luaref; ///< lua callback, used if (uf_flags & FC_LUAREF)
|
||||||
cfunc_T uf_cb; ///< C function extension callback
|
|
||||||
cfunc_free_T uf_cb_free; ///< C function extension free callback
|
|
||||||
void *uf_cb_state; ///< State of C function extension.
|
|
||||||
// Profiling the function as a whole.
|
// Profiling the function as a whole.
|
||||||
int uf_tm_count; ///< nr of calls
|
int uf_tm_count; ///< nr of calls
|
||||||
proftime_T uf_tm_total; ///< time spent in function + children
|
proftime_T uf_tm_total; ///< time spent in function + children
|
||||||
|
@@ -28,20 +28,6 @@
|
|||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
|
|
||||||
// flags used in uf_flags
|
|
||||||
#define FC_ABORT 0x01 // abort function on error
|
|
||||||
#define FC_RANGE 0x02 // function accepts range
|
|
||||||
#define FC_DICT 0x04 // Dict function, uses "self"
|
|
||||||
#define FC_CLOSURE 0x08 // closure, uses outer scope variables
|
|
||||||
#define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0
|
|
||||||
#define FC_REMOVED 0x20 // function redefined while uf_refcount > 0
|
|
||||||
#define FC_SANDBOX 0x40 // function defined in the sandbox
|
|
||||||
#define FC_DEAD 0x80 // function kept only for reference to dfunc
|
|
||||||
#define FC_EXPORT 0x100 // "export def Func()"
|
|
||||||
#define FC_NOARGS 0x200 // no a: variables in lambda
|
|
||||||
#define FC_VIM9 0x400 // defined in vim9 script file
|
|
||||||
#define FC_CFUNC 0x800 // C function extension
|
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "eval/userfunc.c.generated.h"
|
# include "eval/userfunc.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -758,9 +744,9 @@ static void func_clear_items(ufunc_T *fp)
|
|||||||
ga_clear_strings(&(fp->uf_lines));
|
ga_clear_strings(&(fp->uf_lines));
|
||||||
XFREE_CLEAR(fp->uf_name_exp);
|
XFREE_CLEAR(fp->uf_name_exp);
|
||||||
|
|
||||||
if (fp->uf_cb_free != NULL) {
|
if (fp->uf_flags & FC_LUAREF) {
|
||||||
fp->uf_cb_free(fp->uf_cb_state);
|
api_free_luaref(fp->uf_luaref);
|
||||||
fp->uf_cb_free = NULL;
|
fp->uf_luaref = LUA_NOREF;
|
||||||
}
|
}
|
||||||
|
|
||||||
XFREE_CLEAR(fp->uf_tml_count);
|
XFREE_CLEAR(fp->uf_tml_count);
|
||||||
@@ -1538,9 +1524,8 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
|
|||||||
|
|
||||||
if (fp != NULL && (fp->uf_flags & FC_DELETED)) {
|
if (fp != NULL && (fp->uf_flags & FC_DELETED)) {
|
||||||
error = ERROR_DELETED;
|
error = ERROR_DELETED;
|
||||||
} else if (fp != NULL && (fp->uf_flags & FC_CFUNC)) {
|
} else if (fp != NULL && (fp->uf_flags & FC_LUAREF)) {
|
||||||
cfunc_T cb = fp->uf_cb;
|
error = typval_exec_lua_callable(fp->uf_luaref, argcount, argvars, rettv);
|
||||||
error = (*cb)(argcount, argvars, rettv, fp->uf_cb_state);
|
|
||||||
} else if (fp != NULL) {
|
} else if (fp != NULL) {
|
||||||
if (funcexe->argv_func != NULL) {
|
if (funcexe->argv_func != NULL) {
|
||||||
// postponed filling in the arguments, do it now
|
// postponed filling in the arguments, do it now
|
||||||
@@ -3552,20 +3537,18 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
|
|||||||
return abort;
|
return abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers a C extension user function.
|
/// Registers a luaref as a lambda.
|
||||||
char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
|
char_u *register_luafunc(LuaRef ref)
|
||||||
{
|
{
|
||||||
char_u *name = get_lambda_name();
|
char_u *name = get_lambda_name();
|
||||||
ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
|
ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
|
||||||
|
|
||||||
fp->uf_refcount = 1;
|
fp->uf_refcount = 1;
|
||||||
fp->uf_varargs = true;
|
fp->uf_varargs = true;
|
||||||
fp->uf_flags = FC_CFUNC;
|
fp->uf_flags = FC_LUAREF;
|
||||||
fp->uf_calls = 0;
|
fp->uf_calls = 0;
|
||||||
fp->uf_script_ctx = current_sctx;
|
fp->uf_script_ctx = current_sctx;
|
||||||
fp->uf_cb = cb;
|
fp->uf_luaref = ref;
|
||||||
fp->uf_cb_free = cb_free;
|
|
||||||
fp->uf_cb_state = state;
|
|
||||||
|
|
||||||
STRCPY(fp->uf_name, name);
|
STRCPY(fp->uf_name, name);
|
||||||
hash_add(&func_hashtab, UF2HIKEY(fp));
|
hash_add(&func_hashtab, UF2HIKEY(fp));
|
||||||
|
@@ -9,6 +9,20 @@
|
|||||||
#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name)))
|
#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name)))
|
||||||
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
|
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
|
||||||
|
|
||||||
|
// flags used in uf_flags
|
||||||
|
#define FC_ABORT 0x01 // abort function on error
|
||||||
|
#define FC_RANGE 0x02 // function accepts range
|
||||||
|
#define FC_DICT 0x04 // Dict function, uses "self"
|
||||||
|
#define FC_CLOSURE 0x08 // closure, uses outer scope variables
|
||||||
|
#define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0
|
||||||
|
#define FC_REMOVED 0x20 // function redefined while uf_refcount > 0
|
||||||
|
#define FC_SANDBOX 0x40 // function defined in the sandbox
|
||||||
|
#define FC_DEAD 0x80 // function kept only for reference to dfunc
|
||||||
|
#define FC_EXPORT 0x100 // "export def Func()"
|
||||||
|
#define FC_NOARGS 0x200 // no a: variables in lambda
|
||||||
|
#define FC_VIM9 0x400 // defined in vim9 script file
|
||||||
|
#define FC_LUAREF 0x800 // luaref callback
|
||||||
|
|
||||||
///< Structure used by trans_function_name()
|
///< Structure used by trans_function_name()
|
||||||
typedef struct {
|
typedef struct {
|
||||||
dict_T *fd_dict; ///< Dictionary used.
|
dict_T *fd_dict; ///< Dictionary used.
|
||||||
|
@@ -385,12 +385,9 @@ nlua_pop_typval_table_processing_end:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_TFUNCTION: {
|
case LUA_TFUNCTION: {
|
||||||
LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState));
|
LuaRef func = nlua_ref_global(lstate, -1);
|
||||||
state->lua_callable.func_ref = nlua_ref_global(lstate, -1);
|
|
||||||
|
|
||||||
char *name = (char *)register_cfunc(&nlua_CFunction_func_call,
|
char *name = (char *)register_luafunc(func);
|
||||||
&nlua_CFunction_func_free,
|
|
||||||
state);
|
|
||||||
|
|
||||||
cur.tv->v_type = VAR_FUNC;
|
cur.tv->v_type = VAR_FUNC;
|
||||||
cur.tv->vval.v_string = xstrdup(name);
|
cur.tv->vval.v_string = xstrdup(name);
|
||||||
@@ -476,8 +473,8 @@ static bool typval_conv_special = false;
|
|||||||
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
|
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
|
||||||
do { \
|
do { \
|
||||||
ufunc_T *fp = find_func(fun); \
|
ufunc_T *fp = find_func(fun); \
|
||||||
if (fp != NULL && fp->uf_cb == nlua_CFunction_func_call) { \
|
if (fp != NULL && fp->uf_flags & FC_LUAREF) { \
|
||||||
nlua_pushref(lstate, ((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \
|
nlua_pushref(lstate, fp->uf_luaref); \
|
||||||
} else { \
|
} else { \
|
||||||
TYPVAL_ENCODE_CONV_NIL(tv); \
|
TYPVAL_ENCODE_CONV_NIL(tv); \
|
||||||
} \
|
} \
|
||||||
|
@@ -9,14 +9,6 @@
|
|||||||
#include "nvim/eval/typval.h"
|
#include "nvim/eval/typval.h"
|
||||||
#include "nvim/func_attr.h"
|
#include "nvim/func_attr.h"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
LuaRef func_ref;
|
|
||||||
} LuaCallable;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
LuaCallable lua_callable;
|
|
||||||
} LuaCFunctionState;
|
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "lua/converter.h.generated.h"
|
# include "lua/converter.h.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1425,12 +1425,11 @@ int nlua_source_using_linegetter(LineGetter fgetline, void *cookie, char *name)
|
|||||||
/// @param[in] argcount Count of typval arguments
|
/// @param[in] argcount Count of typval arguments
|
||||||
/// @param[in] argvars Typval Arguments
|
/// @param[in] argvars Typval Arguments
|
||||||
/// @param[out] rettv The return value from the called function.
|
/// @param[out] rettv The return value from the called function.
|
||||||
int typval_exec_lua_callable(lua_State *lstate, LuaCallable lua_cb, int argcount, typval_T *argvars,
|
int typval_exec_lua_callable(LuaRef lua_cb, int argcount, typval_T *argvars, typval_T *rettv)
|
||||||
typval_T *rettv)
|
|
||||||
{
|
{
|
||||||
LuaRef cb = lua_cb.func_ref;
|
lua_State *lstate = global_lstate;
|
||||||
|
|
||||||
nlua_pushref(lstate, cb);
|
nlua_pushref(lstate, lua_cb);
|
||||||
|
|
||||||
PUSH_ALL_TYPVALS(lstate, argvars, argcount, false);
|
PUSH_ALL_TYPVALS(lstate, argvars, argcount, false);
|
||||||
|
|
||||||
@@ -1833,26 +1832,6 @@ static int nlua_is_thread(lua_State *lstate)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required functions for lua c functions as VimL callbacks
|
|
||||||
|
|
||||||
int nlua_CFunction_func_call(int argcount, typval_T *argvars, typval_T *rettv, void *state)
|
|
||||||
{
|
|
||||||
lua_State *const lstate = global_lstate;
|
|
||||||
LuaCFunctionState *funcstate = (LuaCFunctionState *)state;
|
|
||||||
|
|
||||||
return typval_exec_lua_callable(lstate, funcstate->lua_callable,
|
|
||||||
argcount, argvars, rettv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nlua_CFunction_func_free(void *state)
|
|
||||||
{
|
|
||||||
lua_State *const lstate = global_lstate;
|
|
||||||
LuaCFunctionState *funcstate = (LuaCFunctionState *)state;
|
|
||||||
|
|
||||||
nlua_unref_global(lstate, funcstate->lua_callable.func_ref);
|
|
||||||
xfree(funcstate);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nlua_is_table_from_lua(typval_T *const arg)
|
bool nlua_is_table_from_lua(typval_T *const arg)
|
||||||
{
|
{
|
||||||
if (arg->v_type == VAR_DICT) {
|
if (arg->v_type == VAR_DICT) {
|
||||||
@@ -1898,11 +1877,9 @@ char_u *nlua_register_table_as_callable(typval_T *const arg)
|
|||||||
}
|
}
|
||||||
lua_pop(lstate, 2); // [table]
|
lua_pop(lstate, 2); // [table]
|
||||||
|
|
||||||
LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState));
|
LuaRef func = nlua_ref_global(lstate, -1);
|
||||||
state->lua_callable.func_ref = nlua_ref_global(lstate, -1);
|
|
||||||
|
|
||||||
char_u *name = register_cfunc(&nlua_CFunction_func_call,
|
char_u *name = register_luafunc(func);
|
||||||
&nlua_CFunction_func_free, state);
|
|
||||||
|
|
||||||
lua_pop(lstate, 1); // []
|
lua_pop(lstate, 1); // []
|
||||||
assert(top == lua_gettop(lstate));
|
assert(top == lua_gettop(lstate));
|
||||||
|
Reference in New Issue
Block a user