summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2022-04-02 21:59:06 +0100
committerBram Moolenaar <Bram@vim.org>2022-04-02 21:59:06 +0100
commit58f331a05f5b7bdddf04e68b6e51a827fd0c43f0 (patch)
tree349de5cab822dc0ccaea9c127fc960f6ab335d2f /src
parent0dac1ab5791819ee9a496273eea38f69a217ac45 (diff)
patch 8.2.4669: in compiled code len('string') is not inlinedv8.2.4669
Problem: In compiled code len('string') is not inlined. Solution: Compute the length at compile time if possible. (closes #10065)
Diffstat (limited to 'src')
-rw-r--r--src/evalfunc.c3
-rw-r--r--src/proto/evalfunc.pro1
-rw-r--r--src/testdir/test_vim9_disassemble.vim13
-rw-r--r--src/version.c2
-rw-r--r--src/vim9expr.c9
5 files changed, 23 insertions, 5 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 60ca50a111..768b27f927 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 bcb4ef5570..4e9ad5b226 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 e55e38e939..f040ba6fd0 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 311b878e6a..92198be337 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4669,
+/**/
4668,
/**/
4667,
diff --git a/src/vim9expr.c b/src/vim9expr.c
index 1b4c7b8065..69f670b24f 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;