mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
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.
This commit is contained in:
98
src/eval.c
98
src/eval.c
@@ -4412,6 +4412,7 @@ eval6(
|
||||
* + in front unary plus (ignored)
|
||||
* trailing [] subscript in String or List
|
||||
* trailing .name entry in Dictionary
|
||||
* trailing ->name() method call
|
||||
*
|
||||
* "arg" must point to the first non-white of the expression.
|
||||
* "arg" is advanced to the next non-white after the recognized expression.
|
||||
@@ -4690,13 +4691,12 @@ eval7(
|
||||
funcexe_T funcexe;
|
||||
|
||||
// Invoke the function.
|
||||
funcexe.argv_func = NULL;
|
||||
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||
funcexe.firstline = curwin->w_cursor.lnum;
|
||||
funcexe.lastline = curwin->w_cursor.lnum;
|
||||
funcexe.doesrange = &len;
|
||||
funcexe.evaluate = evaluate;
|
||||
funcexe.partial = partial;
|
||||
funcexe.selfdict = NULL;
|
||||
ret = get_func_tv(s, len, rettv, arg, &funcexe);
|
||||
}
|
||||
vim_free(s);
|
||||
@@ -4801,6 +4801,70 @@ eval7(
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate "->method()".
|
||||
* "*arg" points to the '-'.
|
||||
* Returns FAIL or OK. "*arg" is advanced to after the ')'.
|
||||
*/
|
||||
static int
|
||||
eval_method(
|
||||
char_u **arg,
|
||||
typval_T *rettv,
|
||||
int evaluate,
|
||||
int verbose) /* give error messages */
|
||||
{
|
||||
char_u *name;
|
||||
long len;
|
||||
funcexe_T funcexe;
|
||||
int ret = OK;
|
||||
typval_T base = *rettv;
|
||||
|
||||
// Skip over the ->.
|
||||
*arg += 2;
|
||||
|
||||
// Locate the method name.
|
||||
name = *arg;
|
||||
for (len = 0; ASCII_ISALNUM(name[len]) || name[len] == '_'; ++len)
|
||||
;
|
||||
if (len == 0)
|
||||
{
|
||||
if (verbose)
|
||||
emsg(_("E260: Missing name after ->"));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// Check for the "(". Skip over white space after it.
|
||||
if (name[len] != '(')
|
||||
{
|
||||
if (verbose)
|
||||
semsg(_(e_missingparen), name);
|
||||
return FAIL;
|
||||
}
|
||||
*arg += len;
|
||||
|
||||
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||
funcexe.evaluate = evaluate;
|
||||
funcexe.basetv = &base;
|
||||
rettv->v_type = VAR_UNKNOWN;
|
||||
ret = get_func_tv(name, len, rettv, arg, &funcexe);
|
||||
|
||||
/* Clear the funcref afterwards, so that deleting it while
|
||||
* evaluating the arguments is possible (see test55). */
|
||||
if (evaluate)
|
||||
clear_tv(&base);
|
||||
|
||||
/* Stop the expression evaluation when immediately aborting on
|
||||
* error, or when an interrupt occurred or an exception was thrown
|
||||
* but not caught. */
|
||||
if (aborting())
|
||||
{
|
||||
if (ret == OK)
|
||||
clear_tv(rettv);
|
||||
ret = FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
|
||||
* "*arg" points to the '[' or '.'.
|
||||
@@ -7359,9 +7423,13 @@ check_vars(char_u *name, int len)
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle expr[expr], expr[expr:expr] subscript and .name lookup.
|
||||
* Also handle function call with Funcref variable: func(expr)
|
||||
* Can all be combined: dict.func(expr)[idx]['func'](expr)
|
||||
* Handle:
|
||||
* - expr[expr], expr[expr:expr] subscript
|
||||
* - ".name" lookup
|
||||
* - function call with Funcref variable: func(expr)
|
||||
* - method call: var->method()
|
||||
*
|
||||
* Can all be combined in any order: dict.func(expr)[idx]['func'](expr)->len()
|
||||
*/
|
||||
int
|
||||
handle_subscript(
|
||||
@@ -7378,14 +7446,15 @@ handle_subscript(
|
||||
// "." is ".name" lookup when we found a dict or when evaluating and
|
||||
// scriptversion is at least 2, where string concatenation is "..".
|
||||
while (ret == OK
|
||||
&& (**arg == '['
|
||||
|| (**arg == '.' && (rettv->v_type == VAR_DICT
|
||||
&& (((**arg == '['
|
||||
|| (**arg == '.' && (rettv->v_type == VAR_DICT
|
||||
|| (!evaluate
|
||||
&& (*arg)[1] != '.'
|
||||
&& current_sctx.sc_version >= 2)))
|
||||
|| (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
|
||||
|| (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
|
||||
|| rettv->v_type == VAR_PARTIAL)))
|
||||
&& !VIM_ISWHITE(*(*arg - 1)))
|
||||
&& !VIM_ISWHITE(*(*arg - 1)))
|
||||
|| (**arg == '-' && (*arg)[1] == '>')))
|
||||
{
|
||||
if (**arg == '(')
|
||||
{
|
||||
@@ -7410,10 +7479,9 @@ handle_subscript(
|
||||
else
|
||||
s = (char_u *)"";
|
||||
|
||||
funcexe.argv_func = NULL;
|
||||
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||
funcexe.firstline = curwin->w_cursor.lnum;
|
||||
funcexe.lastline = curwin->w_cursor.lnum;
|
||||
funcexe.doesrange = NULL;
|
||||
funcexe.evaluate = evaluate;
|
||||
funcexe.partial = pt;
|
||||
funcexe.selfdict = selfdict;
|
||||
@@ -7436,6 +7504,14 @@ handle_subscript(
|
||||
dict_unref(selfdict);
|
||||
selfdict = NULL;
|
||||
}
|
||||
else if (**arg == '-')
|
||||
{
|
||||
if (eval_method(arg, rettv, evaluate, verbose) == FAIL)
|
||||
{
|
||||
clear_tv(rettv);
|
||||
ret = FAIL;
|
||||
}
|
||||
}
|
||||
else /* **arg == '[' || **arg == '.' */
|
||||
{
|
||||
dict_unref(selfdict);
|
||||
|
Reference in New Issue
Block a user