To: vim_dev@googlegroups.com Subject: Patch 9.0.0459 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0459 Problem: Vim9: block in for loop doesn't behave like a code block. Solution: Use a new block ID for each loop at the script level. Files: src/ex_eval.c, src/testdir/test_vim9_script.vim *** ../vim-9.0.0458/src/ex_eval.c 2022-09-04 11:42:18.111231191 +0100 --- src/ex_eval.c 2022-09-13 21:03:19.516860988 +0100 *************** *** 1230,1244 **** { scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); int i; int func_defined = cstack->cs_flags[cstack->cs_idx] & CSF_FUNC_DEF; // Any variables defined in the previous round are no longer // visible. Keep the first one for ":for", it is the loop // variable that we reuse every time around. ! for (i = cstack->cs_script_var_len[cstack->cs_idx] + (eap->cmdidx == CMD_while ? 0 : 1); ! i < si->sn_var_vals.ga_len; ++i) { svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i; --- 1230,1247 ---- { scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); int i; + int first; int func_defined = cstack->cs_flags[cstack->cs_idx] & CSF_FUNC_DEF; // Any variables defined in the previous round are no longer // visible. Keep the first one for ":for", it is the loop // variable that we reuse every time around. ! // Do this backwards, so that vars defined in a later round are ! // found first. ! first = cstack->cs_script_var_len[cstack->cs_idx] + (eap->cmdidx == CMD_while ? 0 : 1); ! for (i = si->sn_var_vals.ga_len - 1; i >= first; --i) { svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i; *************** *** 1250,1255 **** --- 1253,1264 ---- // still exists, from sn_vars. hide_script_var(si, i, func_defined); } + + // Start a new block ID, so that variables defined inside the + // loop are created new and not shared with the previous loop. + // Matters when used in a closure. + cstack->cs_block_id[cstack->cs_idx] = ++si->sn_last_block_id; + si->sn_current_block_id = si->sn_last_block_id; } } cstack->cs_flags[cstack->cs_idx] = *** ../vim-9.0.0458/src/testdir/test_vim9_script.vim 2022-09-11 15:14:00.551020049 +0100 --- src/testdir/test_vim9_script.vim 2022-09-13 21:07:54.224427298 +0100 *************** *** 2266,2275 **** flist[i] = () => inloop endfor for i in range(5) ! assert_equal(4, flist[i]()) endfor END ! v9.CheckDefAndScriptSuccess(lines) lines =<< trim END var flist: list --- 2266,2277 ---- flist[i] = () => inloop endfor for i in range(5) ! assert_equal(i, flist[i]()) endfor END ! # FIXME ! # v9.CheckDefAndScriptSuccess(lines) ! v9.CheckScriptSuccess(['vim9script'] + lines) lines =<< trim END var flist: list *************** *** 2280,2289 **** } endfor for i in range(5) ! assert_equal(4, flist[i]()) endfor END ! v9.CheckDefAndScriptSuccess(lines) enddef def Test_for_loop_fails() --- 2282,2293 ---- } endfor for i in range(5) ! assert_equal(i, flist[i]()) endfor END ! # FIXME ! # v9.CheckDefAndScriptSuccess(lines) ! v9.CheckScriptSuccess(['vim9script'] + lines) enddef def Test_for_loop_fails() *** ../vim-9.0.0458/src/version.c 2022-09-13 18:34:03.144578677 +0100 --- src/version.c 2022-09-13 20:02:49.005609830 +0100 *************** *** 705,706 **** --- 705,708 ---- { /* Add new patch number below this line */ + /**/ + 459, /**/ -- Creating the world with Emacs: M-x let-there-be-light Creating the world with Vim: :make world /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///