Mercurial > vim
diff src/eval.c @ 17612:e259d11e2900 v8.1.1803
patch 8.1.1803: all builtin functions are global
commit https://github.com/vim/vim/commit/ac92e25a33c37ec5becbfffeccda136c73b761ac
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Aug 3 21:58:38 2019 +0200
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.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 03 Aug 2019 22:00:07 +0200 |
parents | ff097edaae89 |
children | 9ffec4eb8d33 |
line wrap: on
line diff
--- 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);