diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-08-03 21:58:38 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-08-03 21:58:38 +0200 |
commit | ac92e25a33c37ec5becbfffeccda136c73b761ac (patch) | |
tree | 64f77cc6dd9427536fd113451b1878490b5298db /src/eval.c | |
parent | b2129068a55261bea1e293a6a1ce8491a03e7de6 (diff) |
patch 8.1.1803: all builtin functions are globalv8.1.1803
Problem: All builtin functions are global.
Solution: Add the method call operator ->. Implemented for a limited number
of functions.
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 98 |
1 files changed, 87 insertions, 11 deletions
diff --git a/src/eval.c b/src/eval.c index 6d7bd66775..7875edeafe 100644 --- a/src/eval.c +++ b/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); @@ -4802,6 +4802,70 @@ eval7( } /* + * 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 '.'. * Returns FAIL or OK. "*arg" is advanced to after the ']'. @@ -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); |