]> granicus.if.org Git - vim/commitdiff
patch 8.2.2657: Vim9: error message for declaring variable in for loop v8.2.2657
authorBram Moolenaar <Bram@vim.org>
Fri, 26 Mar 2021 17:49:22 +0000 (18:49 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 26 Mar 2021 17:49:22 +0000 (18:49 +0100)
Problem:    Vim9: error message for declaring variable in for loop.
Solution:   Clear variables when entering block again. (closes #8012)

src/ex_eval.c
src/testdir/test_vim9_script.vim
src/version.c

index 1af21c2a8e7b8574a3174677c6a238641ead8c47..8d1fd87bcda00d722615b584d28a69dbe2cb3580 100644 (file)
@@ -1154,6 +1154,32 @@ ex_while(exarg_T *eap)
            ++cstack->cs_looplevel;
            cstack->cs_line[cstack->cs_idx] = -1;
        }
+       else
+       {
+           if (in_vim9script() && SCRIPT_ID_VALID(current_sctx.sc_sid))
+           {
+               scriptitem_T    *si = SCRIPT_ITEM(current_sctx.sc_sid);
+               int             i;
+
+               // Any variables defined in the previous round are no longer
+               // visible.
+               for (i = cstack->cs_script_var_len[cstack->cs_idx];
+                                              i < si->sn_var_vals.ga_len; ++i)
+               {
+                   svar_T      *sv = ((svar_T *)si->sn_var_vals.ga_data) + i;
+
+                   // sv_name is set to NULL if it was already removed.  This
+                   // happens when it was defined in an inner block and no
+                   // functions were defined there.
+                   if (sv->sv_name != NULL)
+                       // Remove a variable declared inside the block, if it
+                       // still exists, from sn_vars.
+                       hide_script_var(si, i, FALSE);
+               }
+               cstack->cs_script_var_len[cstack->cs_idx] =
+                                                       si->sn_var_vals.ga_len;
+           }
+       }
        cstack->cs_flags[cstack->cs_idx] =
                               eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR;
 
@@ -1175,6 +1201,9 @@ ex_while(exarg_T *eap)
            void        *fi;
            evalarg_T   evalarg;
 
+           /*
+            * ":for var in list-expr"
+            */
            CLEAR_FIELD(evalarg);
            evalarg.eval_flags = skip ? 0 : EVAL_EVALUATE;
            if (getline_equal(eap->getline, eap->cookie, getsourceline))
@@ -1183,9 +1212,6 @@ ex_while(exarg_T *eap)
                evalarg.eval_cookie = eap->cookie;
            }
 
-           /*
-            * ":for var in list-expr"
-            */
            if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0)
            {
                // Jumping here from a ":continue" or ":endfor": use the
@@ -1384,10 +1410,8 @@ ex_endwhile(exarg_T *eap)
                && dbg_check_skipped(eap))
            (void)do_intthrow(cstack);
 
-       /*
-        * Set loop flag, so do_cmdline() will jump back to the matching
-        * ":while" or ":for".
-        */
+       // Set loop flag, so do_cmdline() will jump back to the matching
+       // ":while" or ":for".
        cstack->cs_lflags |= CSL_HAD_ENDLOOP;
     }
 }
index 49ecbea650ad5ae9e15e87e01bc3f24779af1861..b9c1c57488e441d0a9e30de6be3e756087e60a43 100644 (file)
@@ -2263,6 +2263,13 @@ def Test_for_outside_of_function()
     endfor
     assert_equal(['', '0', '1', '2', '3'], getline(1, '$'))
     bwipe!
+
+    var result = ''
+    for i in [1, 2, 3]
+      var loop = ' loop ' .. i
+      result ..= loop
+    endfor
+    assert_equal(' loop 1 loop 2 loop 3', result)
   END
   writefile(lines, 'Xvim9for.vim')
   source Xvim9for.vim
index c1e795be14bab4f15299a870a78e72e7950c318b..e09153fe286dfa7e0c14b5885da1ece3d3fee5cf 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2657,
 /**/
     2656,
 /**/