diff options
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 129 |
1 files changed, 97 insertions, 32 deletions
diff --git a/src/eval.c b/src/eval.c index aeb8fee7ad..342f93ca2e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -143,17 +143,23 @@ eval_to_bool( char_u *arg, int *error, exarg_T *eap, - int skip) // only parse, don't execute + int skip, // only parse, don't execute + int use_simple_function) { typval_T tv; varnumber_T retval = FALSE; evalarg_T evalarg; + int r; fill_evalarg_from_eap(&evalarg, eap, skip); if (skip) ++emsg_skip; - if (eval0(arg, &tv, eap, &evalarg) == FAIL) + if (use_simple_function) + r = eval0_simple_funccal(arg, &tv, eap, &evalarg); + else + r = eval0(arg, &tv, eap, &evalarg); + if (r == FAIL) *error = TRUE; else { @@ -601,14 +607,20 @@ typval2string(typval_T *tv, int convert) eval_to_string_eap( char_u *arg, int convert, - exarg_T *eap) + exarg_T *eap, + int use_simple_function) { typval_T tv; char_u *retval; evalarg_T evalarg; + int r; fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip); - if (eval0(arg, &tv, NULL, &evalarg) == FAIL) + if (use_simple_function) + r = eval0_simple_funccal(arg, &tv, NULL, &evalarg); + else + r = eval0(arg, &tv, NULL, &evalarg); + if (r == FAIL) retval = NULL; else { @@ -623,9 +635,10 @@ eval_to_string_eap( char_u * eval_to_string( char_u *arg, - int convert) + int convert, + int use_simple_function) { - return eval_to_string_eap(arg, convert, NULL); + return eval_to_string_eap(arg, convert, NULL, use_simple_function); } /* @@ -637,7 +650,8 @@ eval_to_string( eval_to_string_safe( char_u *arg, int use_sandbox, - int keep_script_version) + int keep_script_version, + int use_simple_function) { char_u *retval; funccal_entry_T funccal_entry; @@ -651,7 +665,7 @@ eval_to_string_safe( ++sandbox; ++textlock; may_garbage_collect = FALSE; - retval = eval_to_string(arg, FALSE); + retval = eval_to_string(arg, FALSE, use_simple_function); if (use_sandbox) --sandbox; --textlock; @@ -667,15 +681,20 @@ eval_to_string_safe( * Returns -1 for an error. */ varnumber_T -eval_to_number(char_u *expr) +eval_to_number(char_u *expr, int use_simple_function) { typval_T rettv; varnumber_T retval; char_u *p = skipwhite(expr); + int r = NOTDONE; ++emsg_off; - if (eval1(&p, &rettv, &EVALARG_EVALUATE) == FAIL) + if (use_simple_function) + r = may_call_simple_func(expr, &rettv); + if (r == NOTDONE) + r = eval1(&p, &rettv, &EVALARG_EVALUATE); + if (r == FAIL) retval = -1; else { @@ -695,14 +714,30 @@ eval_to_number(char_u *expr) typval_T * eval_expr(char_u *arg, exarg_T *eap) { + return eval_expr_ext(arg, eap, FALSE); +} + + typval_T * +eval_expr_ext(char_u *arg, exarg_T *eap, int use_simple_function) +{ typval_T *tv; evalarg_T evalarg; fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip); tv = ALLOC_ONE(typval_T); - if (tv != NULL && eval0(arg, tv, eap, &evalarg) == FAIL) - VIM_CLEAR(tv); + if (tv != NULL) + { + int r = NOTDONE; + + if (use_simple_function) + r = eval0_simple_funccal(arg, tv, eap, &evalarg); + if (r == NOTDONE) + r = eval0(arg, tv, eap, &evalarg); + + if (r == FAIL) + VIM_CLEAR(tv); + } clear_evalarg(&evalarg, eap); return tv; @@ -899,12 +934,11 @@ eval_foldexpr(win_T *wp, int *cp) { char_u *arg; typval_T tv; - int r = NOTDONE; varnumber_T retval; char_u *s; sctx_T saved_sctx = current_sctx; int use_sandbox = was_set_insecurely((char_u *)"foldexpr", - OPT_LOCAL); + OPT_LOCAL); arg = skipwhite(wp->w_p_fde); current_sctx = wp->w_p_script_ctx[WV_FDE]; @@ -915,20 +949,9 @@ eval_foldexpr(win_T *wp, int *cp) ++textlock; *cp = NUL; - // If the expression is "FuncName()" then we can skip a lot of overhead. - char_u *parens = (char_u *)strstr((char *)arg, "()"); - if (parens != NULL && *skipwhite(parens + 2) == NUL) - { - char_u *p = STRNCMP(arg, "<SNR>", 5) == 0 ? skipdigits(arg + 5) : arg; - - if (to_name_end(p, TRUE) == parens) - r = call_simple_func(arg, (int)(parens - arg), &tv); - } - - if (r == NOTDONE) - r = eval0(arg, &tv, NULL, &EVALARG_EVALUATE); - - if (r == FAIL) + // Evaluate the expression. If the expression is "FuncName()" call the + // function directly. + if (eval0_simple_funccal(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) retval = 0; else { @@ -2428,9 +2451,10 @@ skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg) } /* - * The "evaluate" argument: When FALSE, the argument is only parsed but not - * executed. The function may return OK, but the rettv will be of type - * VAR_UNKNOWN. The function still returns FAIL for a syntax error. + * The "eval" functions have an "evalarg" argument: When NULL or + * "evalarg->eval_flags" does not have EVAL_EVALUATE, then the argument is only + * parsed but not executed. The functions may return OK, but the rettv will be + * of type VAR_UNKNOWN. The functions still returns FAIL for a syntax error. */ /* @@ -2452,6 +2476,47 @@ eval0( } /* + * If "arg" is a simple function call without arguments then call it and return + * the result. Otherwise return NOTDONE. + */ + int +may_call_simple_func( + char_u *arg, + typval_T *rettv) +{ + char_u *parens = (char_u *)strstr((char *)arg, "()"); + int r = NOTDONE; + + // If the expression is "FuncName()" then we can skip a lot of overhead. + if (parens != NULL && *skipwhite(parens + 2) == NUL) + { + char_u *p = STRNCMP(arg, "<SNR>", 5) == 0 ? skipdigits(arg + 5) : arg; + + if (to_name_end(p, TRUE) == parens) + r = call_simple_func(arg, (int)(parens - arg), rettv); + } + return r; +} + +/* + * Handle zero level expression with optimization for a simple function call. + * Same arguments and return value as eval0(). + */ + int +eval0_simple_funccal( + char_u *arg, + typval_T *rettv, + exarg_T *eap, + evalarg_T *evalarg) +{ + int r = may_call_simple_func(arg, rettv); + + if (r == NOTDONE) + r = eval0_retarg(arg, rettv, eap, evalarg, NULL); + return r; +} + +/* * Like eval0() but when "retarg" is not NULL store the pointer to after the * expression and don't check what comes after the expression. */ @@ -6283,7 +6348,7 @@ make_expanded_name( c1 = *in_end; *in_end = NUL; - temp_result = eval_to_string(expr_start + 1, FALSE); + temp_result = eval_to_string(expr_start + 1, FALSE, FALSE); if (temp_result != NULL) { retval = alloc(STRLEN(temp_result) + (expr_start - in_start) |