From: LemonBoy Date: Sat, 2 Apr 2022 20:59:06 +0000 (+0100) Subject: patch 8.2.4669: in compiled code len('string') is not inlined X-Git-Tag: v8.2.4669 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58f331a05f5b7bdddf04e68b6e51a827fd0c43f0;p=vim patch 8.2.4669: in compiled code len('string') is not inlined Problem: In compiled code len('string') is not inlined. Solution: Compute the length at compile time if possible. (closes #10065) --- diff --git a/src/evalfunc.c b/src/evalfunc.c index 60ca50a11..768b27f92 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -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) diff --git a/src/proto/evalfunc.pro b/src/proto/evalfunc.pro index bcb4ef557..4e9ad5b22 100644 --- a/src/proto/evalfunc.pro +++ b/src/proto/evalfunc.pro @@ -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); diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index e55e38e93..f040ba6fd 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -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*' .. diff --git a/src/version.c b/src/version.c index 311b878e6..92198be33 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 4669, /**/ 4668, /**/ diff --git a/src/vim9expr.c b/src/vim9expr.c index 1b4c7b806..69f670b24 100644 --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -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;