]> granicus.if.org Git - vim/commitdiff
patch 8.2.4669: in compiled code len('string') is not inlined v8.2.4669
authorLemonBoy <thatlemon@gmail.com>
Sat, 2 Apr 2022 20:59:06 +0000 (21:59 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 2 Apr 2022 20:59:06 +0000 (21:59 +0100)
Problem:    In compiled code len('string') is not inlined.
Solution:   Compute the length at compile time if possible. (closes #10065)

src/evalfunc.c
src/proto/evalfunc.pro
src/testdir/test_vim9_disassemble.vim
src/version.c
src/vim9expr.c

index 60ca50a111709968872d1fd4d1986e5efeceac8d..768b27f9272f252871fb2ac47123c20160e3de8e 100644 (file)
@@ -90,7 +90,6 @@ static void f_interrupt(typval_T *argvars, typval_T *rettv);
 static void f_invert(typval_T *argvars, typval_T *rettv);
 static void f_islocked(typval_T *argvars, typval_T *rettv);
 static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv);
-static void f_len(typval_T *argvars, typval_T *rettv);
 static void f_libcall(typval_T *argvars, typval_T *rettv);
 static void f_libcallnr(typval_T *argvars, typval_T *rettv);
 static void f_line(typval_T *argvars, typval_T *rettv);
@@ -7019,7 +7018,7 @@ f_last_buffer_nr(typval_T *argvars UNUSED, typval_T *rettv)
 /*
  * "len()" function
  */
-    static void
+    void
 f_len(typval_T *argvars, typval_T *rettv)
 {
     switch (argvars[0].v_type)
index bcb4ef55707cd31f2a60d5396e91dff1cafb8bdb..4e9ad5b22686952be9e722f573b0e871b2d7fea7 100644 (file)
@@ -20,6 +20,7 @@ void execute_cmds_from_string(char_u *str);
 void execute_common(typval_T *argvars, typval_T *rettv, int arg_off);
 void f_exists(typval_T *argvars, typval_T *rettv);
 void f_has(typval_T *argvars, typval_T *rettv);
+void f_len(typval_T *argvars, typval_T *rettv);
 int dynamic_feature(char_u *feature);
 void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
 void range_list_materialize(list_T *list);
index e55e38e939fef3ee79a34398cfafdacadda86195..f040ba6fd09c39559d1e249e43f8b4c44bbc81af 100644 (file)
@@ -1015,9 +1015,20 @@ def s:HasGuiRunning()
   endif
 enddef
 
+def s:LenConstant(): number
+  return len("foo") + len("fighters")
+enddef
+
 def Test_disassemble_const_expr()
+  var instr = execute('disassemble LenConstant')
+  assert_match('LenConstant\_s*' ..
+    'return len("foo") + len("fighters")\_s*' ..
+    '\d PUSHNR 11\_s*',
+    instr)
+  assert_notmatch('BCALL len', instr)
+
   assert_equal("\nyes", execute('HasEval()'))
-  var instr = execute('disassemble HasEval')
+  instr = execute('disassemble HasEval')
   assert_match('HasEval\_s*' ..
         'if has("eval")\_s*' ..
         'echo "yes"\_s*' ..
index 311b878e6a9442cd3f1aeb8c67cabe1a390b82e3..92198be33746594339c3c0635076259aef0cdcc0 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4669,
 /**/
     4668,
 /**/
index 1b4c7b806552f3d5097c39e15a3ccdfcd77ea763..69f670b24f3af55445707b91d749969688423eb7 100644 (file)
@@ -724,13 +724,16 @@ compile_call(
     }
 
     // We can evaluate "has('name')" at compile time.
+    // We can evaluate "len('string')" at compile time.
     // We always evaluate "exists_compiled()" at compile time.
-    if ((varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
+    if ((varlen == 3
+            && (STRNCMP(*arg, "has", 3) == 0 || STRNCMP(*arg, "len", 3) == 0))
            || (varlen == 15 && STRNCMP(*arg, "exists_compiled", 6) == 0))
     {
        char_u      *s = skipwhite(*arg + varlen + 1);
        typval_T    argvars[2];
        int         is_has = **arg == 'h';
+       int         is_len = **arg == 'l';
 
        argvars[0].v_type = VAR_UNKNOWN;
        if (*s == '"')
@@ -750,6 +753,8 @@ compile_call(
            tv->vval.v_number = 0;
            if (is_has)
                f_has(argvars, tv);
+           else if (is_len)
+               f_len(argvars, tv);
            else
                f_exists(argvars, tv);
            clear_tv(&argvars[0]);
@@ -757,7 +762,7 @@ compile_call(
            return OK;
        }
        clear_tv(&argvars[0]);
-       if (!is_has)
+       if (!is_has && !is_len)
        {
            emsg(_(e_argument_of_exists_compiled_must_be_literal_string));
            return FAIL;