diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-05-09 18:28:34 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-05-09 18:28:34 +0200 |
commit | 1c74721233dac057778f9aef9ae20f49d934ec22 (patch) | |
tree | a07cbfbbde84c6551fd2127670622253ed0ffef5 | |
parent | 7f14155f422ffcc997fc5a0b635a20a4bafd2093 (diff) | |
download | vim-git-1c74721233dac057778f9aef9ae20f49d934ec22.tar.gz |
patch 8.2.0723: Vim9: nested constant expression not evaluated compile timev8.2.0723
Problem: Vim9: nested constant expression not evaluated compile time.
Solution: Use compile_expr1() for parenthesis.
-rw-r--r-- | src/testdir/test_vim9_disassemble.vim | 10 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 25 |
3 files changed, 33 insertions, 4 deletions
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 724087d70..610c56557 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1053,6 +1053,10 @@ def s:ComputeConst(): number return 2 + 3 * 4 / 6 + 7 enddef +def s:ComputeConstParen(): number + return ((2 + 4) * (8 / 2)) / (3 + 4) +enddef + def Test_simplify_const_expr() let res = execute('disass s:ConcatStrings') assert_match('\<SNR>\d*_ConcatStrings.*' .. @@ -1065,6 +1069,12 @@ def Test_simplify_const_expr() '\d PUSHNR 11.*' .. '\d RETURN', res) + + res = execute('disass s:ComputeConstParen') + assert_match('\<SNR>\d*_ComputeConstParen.*' .. + '\d PUSHNR 3\>.*' .. + '\d RETURN', + res) enddef " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 741e3b304..3084d9b7c 100644 --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 723, +/**/ 722, /**/ 721, diff --git a/src/vim9compile.c b/src/vim9compile.c index 1042bb270..5320cafc6 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -136,7 +136,6 @@ struct cctx_S { static char e_var_notfound[] = N_("E1001: variable not found: %s"); static char e_syntax_at[] = N_("E1002: Syntax error at %s"); -static int compile_expr0(char_u **arg, cctx_T *cctx); static void delete_def_function_contents(dfunc_T *dfunc); static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); static int check_type(type_T *expected, type_T *actual, int give_msg); @@ -2358,11 +2357,16 @@ may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx) // possible expressions on these constants are applied at compile time. If // that is not possible, the code to push the constants needs to be generated // before other instructions. +// Using 50 should be more than enough of 5 levels of (). +#define PPSIZE 50 typedef struct { - typval_T pp_tv[10]; // stack of ppconst constants + typval_T pp_tv[PPSIZE]; // stack of ppconst constants int pp_used; // active entries in pp_tv[] } ppconst_T; +static int compile_expr0(char_u **arg, cctx_T *cctx); +static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst); + /* * Generate a PUSH instruction for "tv". * "tv" will be consumed or cleared. @@ -3590,6 +3594,7 @@ compile_expr7( char_u *start_leader, *end_leader; int ret = OK; typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used]; + int used_before = ppconst->pp_used; /* * Skip '!', '-' and '+' characters. They are handled later. @@ -3725,7 +3730,19 @@ compile_expr7( * nested expression: (expression). */ case '(': *arg = skipwhite(*arg + 1); - ret = compile_expr0(arg, cctx); // recursive! + + // recursive! + if (ppconst->pp_used <= PPSIZE - 10) + { + ret = compile_expr1(arg, cctx, ppconst); + } + else + { + // Not enough space in ppconst, flush constants. + if (generate_ppconst(cctx, ppconst) == FAIL) + return FAIL; + ret = compile_expr0(arg, cctx); + } *arg = skipwhite(*arg); if (**arg == ')') ++*arg; @@ -3742,7 +3759,7 @@ compile_expr7( if (ret == FAIL) return FAIL; - if (rettv->v_type != VAR_UNKNOWN) + if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used) { // apply the '!', '-' and '+' before the constant if (apply_leader(rettv, start_leader, end_leader) == FAIL) |