mirror of
https://github.com/neovim/neovim.git
synced 2025-09-10 21:38:19 +00:00
vim-patch:8.1.1803: all builtin functions are global
Problem: All builtin functions are global.
Solution: Add the method call operator ->. Implemented for a limited number
of functions.
ac92e25a33
- Note that to *exactly* port hunk @@ -7376,18 +7444,19 from
handle_subscript(), we need the :scriptversion patches (I have an open
PR for those, but this patch works fine without them anyway).
- Port call_internal_func() from v7.4.2058.
- Adjust some error messages in tests, as they rely on the Blob patches.
- Add a modeline to test_method.vim.
Ignore the global_functions and base_method tables and prefer the
current GPerf implementation. Instead, add an extra base_arg field to
VimLFuncDef that holds the number of the argument to use as the base
(1-indexed, so that 0 may be used to refer to functions that cannot be
used as methods).
This also means we support using any argument as a base from the get-go,
rather than just the first (Vim includes this ability in future patches,
however).
To mark a function as usable as a method, use the "base" key as
described in eval.lua.
This commit is contained in:
@@ -175,6 +175,50 @@ const VimLFuncDef *find_internal_func(const char *const name)
|
||||
return find_internal_func_gperf(name, len);
|
||||
}
|
||||
|
||||
int call_internal_func(const char_u *const fname, const int argcount,
|
||||
typval_T *const argvars, typval_T *const rettv)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const VimLFuncDef *const fdef = find_internal_func((const char *)fname);
|
||||
if (fdef == NULL) {
|
||||
return ERROR_UNKNOWN;
|
||||
} else if (argcount < fdef->min_argc) {
|
||||
return ERROR_TOOFEW;
|
||||
} else if (argcount > fdef->max_argc) {
|
||||
return ERROR_TOOMANY;
|
||||
}
|
||||
argvars[argcount].v_type = VAR_UNKNOWN;
|
||||
fdef->func(argvars, rettv, fdef->data);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
/// Invoke a method for base->method().
|
||||
int call_internal_method(const char_u *const fname, const int argcount,
|
||||
typval_T *const argvars, typval_T *const rettv,
|
||||
typval_T *const basetv)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const VimLFuncDef *const fdef = find_internal_func((const char *)fname);
|
||||
if (fdef == NULL || fdef->base_arg == 0) {
|
||||
return ERROR_UNKNOWN;
|
||||
} else if (argcount + 1 < fdef->min_argc) {
|
||||
return ERROR_TOOFEW;
|
||||
} else if (argcount + 1 > fdef->max_argc) {
|
||||
return ERROR_TOOMANY;
|
||||
}
|
||||
|
||||
typval_T argv[MAX_FUNC_ARGS + 1];
|
||||
const ptrdiff_t base_index = fdef->base_arg - 1;
|
||||
memcpy(argv, argvars, base_index * sizeof(typval_T));
|
||||
argv[base_index] = *basetv;
|
||||
memcpy(argv + base_index + 1, argvars + base_index,
|
||||
(argcount - base_index) * sizeof(typval_T));
|
||||
argv[argcount + 1].v_type = VAR_UNKNOWN;
|
||||
|
||||
fdef->func(argv, rettv, fdef->data);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE for a non-zero Number and a non-empty String.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user