From bb7ee7abe1ea1e60b8a5dadd2bed8cdbe4f3e8fb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 2 Aug 2021 20:06:50 +0200 Subject: [PATCH] patch 8.2.3276: Vim9: exists() can only be evaluated at runtime Problem: Vim9: exists() can only be evaluated at runtime. Solution: Evaluate at compile time for option name literals. (closes #8437) --- src/evalfunc.c | 3 +-- src/proto/evalfunc.pro | 1 + src/testdir/test_vim9_builtin.vim | 19 +++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 15 +++++++++++---- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index ff0d33a4c..6db930ef2 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -49,7 +49,6 @@ static void f_escape(typval_T *argvars, typval_T *rettv); static void f_eval(typval_T *argvars, typval_T *rettv); static void f_eventhandler(typval_T *argvars, typval_T *rettv); static void f_execute(typval_T *argvars, typval_T *rettv); -static void f_exists(typval_T *argvars, typval_T *rettv); static void f_expand(typval_T *argvars, typval_T *rettv); static void f_expandcmd(typval_T *argvars, typval_T *rettv); static void f_feedkeys(typval_T *argvars, typval_T *rettv); @@ -3521,7 +3520,7 @@ f_execute(typval_T *argvars, typval_T *rettv) /* * "exists()" function */ - static void + void f_exists(typval_T *argvars, typval_T *rettv) { char_u *p; diff --git a/src/proto/evalfunc.pro b/src/proto/evalfunc.pro index 67bb5e4d3..5bb38b00f 100644 --- a/src/proto/evalfunc.pro +++ b/src/proto/evalfunc.pro @@ -18,6 +18,7 @@ buf_T *get_buf_arg(typval_T *arg); win_T *get_optional_window(typval_T *argvars, int idx); void execute_redir_str(char_u *value, int value_len); 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); int dynamic_feature(char_u *feature); void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv); diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index f4d7448f5..19baada10 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -790,6 +790,25 @@ enddef def Test_exists() CheckDefAndScriptFailure2(['exists(10)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') call assert_equal(1, exists('&tabstop')) + + if exists('+newoption') + if &newoption == 'ok' + endif + endif + if exists('&newoption') + if &newoption == 'ok' + endif + endif + if exists('+tabstop') + assert_equal(8, &tabstop) + else + assert_report('tabstop option not existing?') + endif + if exists('&tabstop') + assert_equal(8, &tabstop) + else + assert_report('tabstop option not existing?') + endif enddef def Test_expand() diff --git a/src/version.c b/src/version.c index fae2fd63c..879800260 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 3276, /**/ 3275, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 15e6e63a8..c4eed5428 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3395,8 +3395,10 @@ compile_call( int is_autoload; int is_searchpair; - // we can evaluate "has('name')" at compile time - if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0) + // We can evaluate "has('name')" at compile time. + // We can evaluate some "exists()" values at compile time. + if ((varlen == 3 && STRNCMP(*arg, "has", 3) == 0) + || (varlen == 6 && STRNCMP(*arg, "exists", 6) == 0)) { char_u *s = skipwhite(*arg + varlen + 1); typval_T argvars[2]; @@ -3408,7 +3410,9 @@ compile_call( (void)eval_lit_string(&s, &argvars[0], TRUE); s = skipwhite(s); if (*s == ')' && argvars[0].v_type == VAR_STRING - && !dynamic_feature(argvars[0].vval.v_string)) + && ((**arg == 'h' && !dynamic_feature(argvars[0].vval.v_string)) + || (**arg == 'e' && (*argvars[0].vval.v_string == '+' + || *argvars[0].vval.v_string == '&')))) { typval_T *tv = &ppconst->pp_tv[ppconst->pp_used]; @@ -3416,7 +3420,10 @@ compile_call( argvars[1].v_type = VAR_UNKNOWN; tv->v_type = VAR_NUMBER; tv->vval.v_number = 0; - f_has(argvars, tv); + if (**arg == 'h') + f_has(argvars, tv); + else + f_exists(argvars, tv); clear_tv(&argvars[0]); ++ppconst->pp_used; return OK; -- 2.40.0