summaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c129
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)