summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-03-26 18:49:22 +0100
committerBram Moolenaar <Bram@vim.org>2021-03-26 18:49:22 +0100
commit522eefd9a247c574a51bfe9bf73467a8dc3bac42 (patch)
tree3c25b743231d46639076f8f84cbdf603ec20f6ba
parenta2b3e7dc9201fb3d8782c6b4ab53862160e254da (diff)
patch 8.2.2657: Vim9: error message for declaring variable in for loopv8.2.2657
Problem: Vim9: error message for declaring variable in for loop. Solution: Clear variables when entering block again. (closes #8012)
-rw-r--r--src/ex_eval.c38
-rw-r--r--src/testdir/test_vim9_script.vim7
-rw-r--r--src/version.c2
3 files changed, 40 insertions, 7 deletions
diff --git a/src/ex_eval.c b/src/ex_eval.c
index 1af21c2a8e..8d1fd87bcd 100644
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -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;
}
}
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 49ecbea650..b9c1c57488 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index c1e795be14..e09153fe28 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 */
/**/
+ 2657,
+/**/
2656,
/**/
2655,