]> granicus.if.org Git - vim/commitdiff
patch 9.0.0634: evaluating "expr" options has more overhead than needed v9.0.0634
authorBram Moolenaar <Bram@vim.org>
Sat, 1 Oct 2022 18:43:52 +0000 (19:43 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 1 Oct 2022 18:43:52 +0000 (19:43 +0100)
Problem:    Evaluating "expr" options has more overhead than needed.
Solution:   Use call_simple_func() for 'foldtext', 'includeexpr', 'printexpr',
            "expr" of 'spellsuggest', 'diffexpr', 'patchexpr', 'balloonexpr',
            'formatexpr', 'indentexpr' and 'charconvert'.

24 files changed:
runtime/doc/diff.txt
runtime/doc/options.txt
runtime/doc/print.txt
src/beval.c
src/buffer.c
src/clientserver.c
src/eval.c
src/evalvars.c
src/ex_docmd.c
src/ex_eval.c
src/filepath.c
src/findfile.c
src/fold.c
src/if_ole.cpp
src/if_perl.xs
src/if_tcl.c
src/map.c
src/proto/eval.pro
src/regexp.c
src/register.c
src/screen.c
src/scriptfile.c
src/textformat.c
src/version.c

index a66df1e27305d7c53110b373a737896a9b7945a7..e5321c586d5d8a3eee6c205070a72706a0f5f15a 100644 (file)
@@ -376,6 +376,9 @@ Additionally, 'diffexpr' should take care of "icase" and "iwhite" in the
 'diffopt' option.  'diffexpr' cannot change the value of 'lines' and
 'columns'.
 
+The advantage of using a function call without arguments is that it is faster,
+see |expr-option-function|.
+
 Example (this does almost the same as 'diffexpr' being empty): >
 
        set diffexpr=MyDiff()
@@ -441,6 +444,9 @@ will have the same effect.  These variables are set to the file names used:
        v:fname_diff            patch file
        v:fname_out             resulting patched file
 
+The advantage of using a function call without arguments is that it is faster,
+see |expr-option-function|.
+
 Example (this does the same as 'patchexpr' being empty): >
 
        set patchexpr=MyPatch()
index 4ea75ba2db367707f49ee95709637abea00c136d..aa69dd1e918d6b23dadb54020f29380aaab45bda 100644 (file)
@@ -1626,6 +1626,9 @@ A jump table for the options with a short description can be found at |Q_op|.
        Note that v:charconvert_from and v:charconvert_to may be different
        from 'encoding'.  Vim internally uses UTF-8 instead of UCS-2 or UCS-4.
 
+       The advantage of using a function call without arguments is that it is
+       faster, see |expr-option-function|.
+
        Encryption is not done by Vim when using 'charconvert'.  If you want
        to encrypt the file after conversion, 'charconvert' should take care
        of this.
@@ -3664,6 +3667,9 @@ A jump table for the options with a short description can be found at |Q_op|.
 <      This will invoke the mylang#Format() function in the
        autoload/mylang.vim file in 'runtimepath'. |autoload|
 
+       The advantage of using a function call without arguments is that it is
+       faster, see |expr-option-function|.
+
        The expression is also evaluated when 'textwidth' is set and adding
        text beyond that limit.  This happens under the same conditions as
        when internal formatting is used.  Make sure the cursor is kept in the
@@ -4534,11 +4540,14 @@ A jump table for the options with a short description can be found at |Q_op|.
 
        If the expression starts with s: or |<SID>|, then it is replaced with
        the script ID (|local-function|). Example: >
-               set includeexpr=s:MyIncludeExpr(v:fname)
-               set includeexpr=<SID>SomeIncludeExpr(v:fname)
+               set includeexpr=s:MyIncludeExpr()
+               set includeexpr=<SID>SomeIncludeExpr()
 <      Otherwise, the expression is evaluated in the context of the script
        where the option was set, thus script-local items are available.
 
+       It is more efficient if the value is just a function call without
+       arguments, see |expr-option-function|.
+
        The expression will be evaluated in the |sandbox| when set from a
        modeline, see |sandbox-option|.
        This option cannot be set in a modeline when 'modelineexpr' is off.
@@ -4620,6 +4629,9 @@ A jump table for the options with a short description can be found at |Q_op|.
 <      Otherwise, the expression is evaluated in the context of the script
        where the option was set, thus script-local items are available.
 
+       The advantage of using a function call without arguments is that it is
+       faster, see |expr-option-function|.
+
        The expression must return the number of spaces worth of indent.  It
        can return "-1" to keep the current indent (this means 'autoindent' is
        used for the indent).
@@ -7470,9 +7482,11 @@ A jump table for the options with a short description can be found at |Q_op|.
                        The file is used for all languages.
 
        expr:{expr}     Evaluate expression {expr}.  Use a function to avoid
-                       trouble with spaces.  |v:val| holds the badly spelled
-                       word.  The expression must evaluate to a List of
-                       Lists, each with a suggestion and a score.
+                       trouble with spaces.  Best is to call a function
+                       without arguments, see |expr-option-function|.
+                       |v:val| holds the badly spelled word.  The expression
+                       must evaluate to a List of Lists, each with a
+                       suggestion and a score.
                        Example:
                                [['the', 33], ['that', 44]] ~
                        Set 'verbose' and use |z=| to see the scores that the
index 2774e981f664d40da4339a322e08f563b2a7b018..9f8bb20879522253f899b939075fc0694fc5a215 100644 (file)
@@ -158,13 +158,16 @@ currently specified printdevice: >
 If you change this option, using a function is an easy way to avoid having to
 escape all the spaces.  Example: >
 
-       :set printexpr=PrintFile(v:fname_in)
-       :function PrintFile(fname)
-       :  call system("ghostview " .. a:fname)
-       :  call delete(a:fname)
+       :set printexpr=PrintFile()
+       :function PrintFile()
+       :  call system("ghostview " .. v:fname_in)
+       :  call delete(v:fname_in)
        :  return v:shell_error
        :endfunc
 
+It is more efficient if the option is set to just a function call,
+see |expr-option-function|.
+
 Be aware that some print programs return control before they have read the
 file.  If you delete the file too soon it will not be printed.  These programs
 usually offer an option to have them remove the file when printing is done.
index 97fc354f134e0704dc158346e942edde8eba48ed..375795e4afb1c5b112156dad11dc405a111aeb8c 100644 (file)
@@ -278,7 +278,7 @@ bexpr_eval(
        current_sctx = curbuf->b_p_script_ctx[BV_BEXPR];
 
     vim_free(result);
-    result = eval_to_string(bexpr, TRUE);
+    result = eval_to_string(bexpr, TRUE, TRUE);
 
     // Remove one trailing newline, it is added when the result was a
     // list and it's hardly ever useful.  If the user really wants a
index be7f1fa8d4167445a4530228b87d575bda9f9a02..f74348d69229510f37f65fae5dcfef14ce99b1a0 100644 (file)
@@ -4246,7 +4246,7 @@ build_stl_str_hl(
        tv.vval.v_number = wp->w_id;
        set_var((char_u *)"g:statusline_winid", &tv, FALSE);
 
-       usefmt = eval_to_string_safe(fmt + 2, use_sandbox, FALSE);
+       usefmt = eval_to_string_safe(fmt + 2, use_sandbox, FALSE, FALSE);
        if (usefmt == NULL)
            usefmt = fmt;
 
@@ -4633,7 +4633,7 @@ build_stl_str_hl(
            if (curwin != save_curwin)
                VIsual_active = FALSE;
 
-           str = eval_to_string_safe(p, use_sandbox, FALSE);
+           str = eval_to_string_safe(p, use_sandbox, FALSE, FALSE);
 
            curwin = save_curwin;
            curbuf = save_curbuf;
index eaaba2572a8d042392cc59f8f94f5ae612ae6dec..63aec10d86967d802066b304d9b8714c43557251 100644 (file)
@@ -86,7 +86,7 @@ eval_client_expr_to_string(char_u *expr)
     // to be typed.  Do generate errors so that try/catch works.
     ++emsg_silent;
 
-    res = eval_to_string(expr, TRUE);
+    res = eval_to_string(expr, TRUE, FALSE);
 
     debug_break_level = save_dbl;
     redir_off = save_ro;
index aeb8fee7ad3fe2a0c6781b671b112f267a475e59..342f93ca2e3e10cef06535d86f27df01b73f21e4 100644 (file)
@@ -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
     {
@@ -694,6 +713,12 @@ 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;
@@ -701,8 +726,18 @@ eval_expr(char_u *arg, exarg_T *eap)
     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.
  */
 
 /*
@@ -2451,6 +2475,47 @@ eval0(
     return eval0_retarg(arg, rettv, eap, evalarg, NULL);
 }
 
+/*
+ * 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)
index 3c5b28a982c9db7ac256589da8b4fd5cd06d961d..c4b95bc17c628c48a14c000d6b8f487b946ada70 100644 (file)
@@ -380,7 +380,7 @@ eval_charconvert(
     if (ctx != NULL)
        current_sctx = *ctx;
 
-    if (eval_to_bool(p_ccv, &err, NULL, FALSE))
+    if (eval_to_bool(p_ccv, &err, NULL, FALSE, TRUE))
        err = TRUE;
 
     set_vim_var_string(VV_CC_FROM, NULL, -1);
@@ -408,7 +408,7 @@ eval_printexpr(char_u *fname, char_u *args)
     if (ctx != NULL)
        current_sctx = *ctx;
 
-    if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
+    if (eval_to_bool(p_pexpr, &err, NULL, FALSE, TRUE))
        err = TRUE;
 
     set_vim_var_string(VV_FNAME_IN, NULL, -1);
@@ -444,7 +444,7 @@ eval_diff(
        current_sctx = *ctx;
 
     // errors are ignored
-    tv = eval_expr(p_dex, NULL);
+    tv = eval_expr_ext(p_dex, NULL, TRUE);
     free_tv(tv);
 
     set_vim_var_string(VV_FNAME_IN, NULL, -1);
@@ -472,7 +472,7 @@ eval_patch(
        current_sctx = *ctx;
 
     // errors are ignored
-    tv = eval_expr(p_pex, NULL);
+    tv = eval_expr_ext(p_pex, NULL, TRUE);
     free_tv(tv);
 
     set_vim_var_string(VV_FNAME_IN, NULL, -1);
@@ -497,6 +497,7 @@ eval_spell_expr(char_u *badword, char_u *expr)
     char_u     *p = skipwhite(expr);
     sctx_T     saved_sctx = current_sctx;
     sctx_T     *ctx;
+    int                r;
 
     // Set "v:val" to the bad word.
     prepare_vimvar(VV_VAL, &save_val);
@@ -507,7 +508,10 @@ eval_spell_expr(char_u *badword, char_u *expr)
     if (ctx != NULL)
        current_sctx = *ctx;
 
-    if (eval1(&p, &rettv, &EVALARG_EVALUATE) == OK)
+    r = may_call_simple_func(p, &rettv);
+    if (r == NOTDONE)
+       r = eval1(&p, &rettv, &EVALARG_EVALUATE);
+    if (r == OK)
     {
        if (rettv.v_type != VAR_LIST)
            clear_tv(&rettv);
@@ -643,7 +647,7 @@ eval_one_expr_in_str(char_u *p, garray_T *gap, int evaluate)
     if (evaluate)
     {
        *block_end = NUL;
-       expr_val = eval_to_string(block_start, TRUE);
+       expr_val = eval_to_string(block_start, TRUE, FALSE);
        *block_end = '}';
        if (expr_val == NULL)
            return NULL;
index 912203917e2664722ff3b5121518783e89a56b62..09f0faf90dbf8f3db4db3789cd875d84180f49a6 100644 (file)
@@ -5778,7 +5778,7 @@ ex_colorscheme(exarg_T *eap)
        if (expr != NULL)
        {
            ++emsg_off;
-           p = eval_to_string(expr, FALSE);
+           p = eval_to_string(expr, FALSE, FALSE);
            --emsg_off;
            vim_free(expr);
        }
index 77d6e8bb981179465a8c080b2dc8d94eaa0bcbeb..e1c28899e1b5a244dc32baa91905c61f190191b9 100644 (file)
@@ -1047,7 +1047,7 @@ ex_if(exarg_T *eap)
        skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
                && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
 
-       result = eval_to_bool(eap->arg, &error, eap, skip);
+       result = eval_to_bool(eap->arg, &error, eap, skip, FALSE);
 
        if (!skip && !error)
        {
@@ -1176,7 +1176,7 @@ ex_else(exarg_T *eap)
        if (skip && ends_excmd(*eap->arg))
            semsg(_(e_invalid_expression_str), eap->arg);
        else
-           result = eval_to_bool(eap->arg, &error, eap, skip);
+           result = eval_to_bool(eap->arg, &error, eap, skip, FALSE);
 
        // When throwing error exceptions, we want to throw always the first
        // of several errors in a row.  This is what actually happens when
@@ -1283,7 +1283,7 @@ ex_while(exarg_T *eap)
            /*
             * ":while bool-expr"
             */
-           result = eval_to_bool(eap->arg, &error, eap, skip);
+           result = eval_to_bool(eap->arg, &error, eap, skip, FALSE);
        }
        else
        {
index 673cdb5accbe82cad586c783c4c20e457e753b2e..02e7ed7dce2ac7bedeb0035cecaa74d6099ca590 100644 (file)
@@ -3354,7 +3354,7 @@ expand_backtick(
 
 #ifdef FEAT_EVAL
     if (*cmd == '=')       // `={expr}`: Expand expression
-       buffer = eval_to_string(cmd + 1, TRUE);
+       buffer = eval_to_string(cmd + 1, TRUE, FALSE);
     else
 #endif
        buffer = get_cmd_output(cmd, NULL,
index 5751a07270c281cf2111180bd9afa310626db544..9ce733cfd687e60d0dffe4031b4cf5011a822fe7 100644 (file)
@@ -2002,7 +2002,8 @@ eval_includeexpr(char_u *ptr, int len)
     current_sctx = curbuf->b_p_script_ctx[BV_INEX];
 
     res = eval_to_string_safe(curbuf->b_p_inex,
-                was_set_insecurely((char_u *)"includeexpr", OPT_LOCAL), TRUE);
+           was_set_insecurely((char_u *)"includeexpr", OPT_LOCAL),
+                                                                  TRUE, TRUE);
 
     set_vim_var_string(VV_FNAME, NULL, 0);
     current_sctx = save_sctx;
index 83d1cf68df19cada3fd7ec1ae4fb7d870a04942f..a226d6fd2f7066e1f926b04be99b442f82df2cd6 100644 (file)
@@ -1960,7 +1960,8 @@ get_foldtext(
 
            ++emsg_off; // handle exceptions, but don't display errors
            text = eval_to_string_safe(wp->w_p_fdt,
-                   was_set_insecurely((char_u *)"foldtext", OPT_LOCAL), TRUE);
+                          was_set_insecurely((char_u *)"foldtext", OPT_LOCAL),
+                          TRUE, TRUE);
            --emsg_off;
 
            if (text == NULL || did_emsg)
index e3e4cdb889f44aea03ff3ca4ffa2ce7a2b729645..9dc15fda2793c4ec651a490b7708812ddf3fbc63 100644 (file)
@@ -381,7 +381,7 @@ CVim::Eval(BSTR expr, BSTR *result)
 
     /* Evaluate the expression */
     ++emsg_skip;
-    str = (char *)eval_to_string((char_u *)buffer, TRUE);
+    str = (char *)eval_to_string((char_u *)buffer, TRUE, FALSE);
     --emsg_skip;
     vim_free(buffer);
     if (str == NULL)
index ab2917ae006ea80e866e9014acccf6ac4ed344b2..0241c319fe267cd7b03a8c926131013aa61513cd 100644 (file)
@@ -873,7 +873,8 @@ msg_split(
     char_u *
 eval_to_string(
     char_u     *arg UNUSED,
-    int                dolist UNUSED)
+    int                convert UNUSED,
+    int                use_simple_function UNUSED)
 {
     return NULL;
 }
@@ -1599,7 +1600,7 @@ Eval(str)
     PREINIT:
        char_u *value;
     PPCODE:
-       value = eval_to_string((char_u *)str, TRUE);
+       value = eval_to_string((char_u *)str, TRUE, FALSE);
        if (value == NULL)
        {
            XPUSHs(sv_2mortal(newSViv(0)));
index 6c7768972a9caec85c60a8a9d0899e79b356294d..130e3e17ea1885d1a728f69b759030367f1c5e16 100644 (file)
@@ -1397,7 +1397,7 @@ tclvimexpr(
 
 #ifdef FEAT_EVAL
     expr = Tcl_GetStringFromObj(objv[objn], NULL);
-    str = (char *)eval_to_string((char_u *)expr, TRUE);
+    str = (char *)eval_to_string((char_u *)expr, TRUE, FALSE);
     if (str == NULL)
        Tcl_SetResult(interp, _("invalid expression"), TCL_STATIC);
     else
index d063e053ae109c3e26aea6f51be972fe954a39a7..2b213cf5f60cff110c8203d1bb0d3243277d5ceb 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -1711,7 +1711,7 @@ eval_map_expr(
     }
 
     // Note: the evaluation may make "mp" invalid.
-    p = eval_to_string(expr, FALSE);
+    p = eval_to_string(expr, FALSE, FALSE);
 
     --textlock;
     --ex_normal_lock;
index 1ac579c54abc952626838b21750aebe14706f6f8..afc4d6189df7c29c4e77fb2c0808c00d0a5ff09d 100644 (file)
@@ -4,7 +4,7 @@ varnumber_T num_modulus(varnumber_T n1, varnumber_T n2, int *failed);
 void eval_init(void);
 void eval_clear(void);
 void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, int skip);
-int eval_to_bool(char_u *arg, int *error, exarg_T *eap, int skip);
+int eval_to_bool(char_u *arg, int *error, exarg_T *eap, int skip, int use_simple_function);
 int eval_expr_valid_arg(typval_T *tv);
 funccall_T *eval_expr_get_funccal(typval_T *expr, typval_T *rettv);
 int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, funccall_T *fc_arg, typval_T *rettv);
@@ -15,11 +15,12 @@ void clear_evalarg(evalarg_T *evalarg, exarg_T *eap);
 int skip_expr(char_u **pp, evalarg_T *evalarg);
 int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg);
 char_u *typval2string(typval_T *tv, int convert);
-char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap);
-char_u *eval_to_string(char_u *arg, int convert);
-char_u *eval_to_string_safe(char_u *arg, int use_sandbox, int keep_script_version);
-varnumber_T eval_to_number(char_u *expr);
+char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap, int use_simple_function);
+char_u *eval_to_string(char_u *arg, int convert, int use_simple_function);
+char_u *eval_to_string_safe(char_u *arg, int use_sandbox, int keep_script_version, int use_simple_function);
+varnumber_T eval_to_number(char_u *expr, int use_simple_function);
 typval_T *eval_expr(char_u *arg, exarg_T *eap);
+typval_T *eval_expr_ext(char_u *arg, exarg_T *eap, int use_simple_function);
 int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv);
 void *call_func_retstr(char_u *func, int argc, typval_T *argv);
 void *call_func_retlist(char_u *func, int argc, typval_T *argv);
@@ -38,6 +39,8 @@ char_u *eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext);
 char_u *eval_next_line(char_u *arg, evalarg_T *evalarg);
 char_u *skipwhite_and_linebreak(char_u *arg, evalarg_T *evalarg);
 int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg);
+int may_call_simple_func(char_u *arg, typval_T *rettv);
+int eval0_simple_funccal(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg);
 int eval0_retarg(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg, char_u **retarg);
 int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
 void eval_addblob(typval_T *tv1, typval_T *tv2);
index 842c48038d4e000046542ad710a8e3de1da495f8..b15dc3a644f6ab7154f8884d30d18e998222b548 100644 (file)
@@ -2125,7 +2125,7 @@ vim_regsub_both(
                // Execute instructions from ISN_SUBSTITUTE.
                eval_result[nested] = exe_substitute_instr();
            else
-               eval_result[nested] = eval_to_string(source + 2, TRUE);
+               eval_result[nested] = eval_to_string(source + 2, TRUE, FALSE);
            --nesting;
 
            if (eval_result[nested] != NULL)
index ac1d6a3a52f69f78b1af6f500798925de09a1d35..bede88b9a06ff4d01b160750da710da6e74625f0 100644 (file)
@@ -151,7 +151,7 @@ get_expr_line(void)
        return expr_copy;
 
     ++nested;
-    rv = eval_to_string_eap(expr_copy, TRUE, expr_eap);
+    rv = eval_to_string_eap(expr_copy, TRUE, expr_eap, FALSE);
     --nested;
     vim_free(expr_copy);
     return rv;
index e44da0216447a1f72d3847007858002bf3bcf713..f5dfa05902d7e0d2a7f4be4520260f613136e133 100644 (file)
@@ -1198,7 +1198,7 @@ get_keymap_str(
        curwin = wp;
        STRCPY(buf, "b:keymap_name");   // must be writable
        ++emsg_skip;
-       s = p = eval_to_string(buf, FALSE);
+       s = p = eval_to_string(buf, FALSE, FALSE);
        --emsg_skip;
        curbuf = old_curbuf;
        curwin = old_curwin;
@@ -2976,7 +2976,7 @@ free_screenlines(void)
  * Clear the screen.
  * May delay if there is something the user should read.
  * Allocated the screen for resizing if needed.
- * Returns TRUE when the screen was actually claared, FALSE if all display
+ * Returns TRUE when the screen was actually cleared, FALSE if all display
  * cells were marked for updating.
  */
     int
index bdb7922363ac34a72c9dd4362e1787898093fa72..9623ea0ad916f9c845b18185d413801216dc9f93 100644 (file)
@@ -810,7 +810,7 @@ load_pack_plugin(char_u *fname)
 
        // If runtime/filetype.vim wasn't loaded yet, the scripts will be
        // found when it loads.
-       if (cmd != NULL && eval_to_number(cmd) > 0)
+       if (cmd != NULL && eval_to_number(cmd, FALSE) > 0)
        {
            do_cmdline_cmd((char_u *)"augroup filetypedetect");
            vim_snprintf((char *)pat, len, ftpat, ffname);
index 36c69450c8f520bfeeff7ebf2676141f6c502a04..dfbeed70dec1a2d43b78b8ec03b356264d0bc339 100644 (file)
@@ -938,7 +938,7 @@ fex_format(
     // Evaluate the function.
     if (use_sandbox)
        ++sandbox;
-    r = (int)eval_to_number(fex);
+    r = (int)eval_to_number(fex, TRUE);
     if (use_sandbox)
        --sandbox;
 
index 6778ce62b896f87d0021b885c371a650dbda9b90..e4c46c21b75b65b700a02f95cfc31f1b680c73f3 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    634,
 /**/
     633,
 /**/