]> granicus.if.org Git - vim/commitdiff
patch 8.2.0723: Vim9: nested constant expression not evaluated compile time v8.2.0723
authorBram Moolenaar <Bram@vim.org>
Sat, 9 May 2020 16:28:34 +0000 (18:28 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 9 May 2020 16:28:34 +0000 (18:28 +0200)
Problem:    Vim9: nested constant expression not evaluated compile time.
Solution:   Use compile_expr1() for parenthesis.

src/testdir/test_vim9_disassemble.vim
src/version.c
src/vim9compile.c

index 724087d7031350f0885edac25c3bbdc6bb24977e..610c565575de3cdd3044e52bf72d5430a6d281a7 100644 (file)
@@ -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
index 741e3b304225d1ab14f0ff90294c8f23113eacb1..3084d9b7ceb9dcd0e057ebd58a02917a4c312693 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    723,
 /**/
     722,
 /**/
index 1042bb27013bff5fc8161e8e418023d198a3a017..5320cafc686d9150cf906d06e4393743722545e7 100644 (file)
@@ -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)