Mercurial > vim
comparison src/ex_eval.c @ 30247:327bca7b70ea v9.0.0459
patch 9.0.0459: Vim9: block in for loop doesn't behave like a code block
Commit: https://github.com/vim/vim/commit/353b68a99189875a8460124d44fc33eae6def74e
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Sep 13 21:10:45 2022 +0100
patch 9.0.0459: Vim9: block in for loop doesn't behave like a code block
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.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 13 Sep 2022 22:15:04 +0200 |
parents | 6a8c2ff5b2ef |
children | c0f0118b6790 |
comparison
equal
deleted
inserted
replaced
30246:23088f4486a5 | 30247:327bca7b70ea |
---|---|
1228 { | 1228 { |
1229 if (in_vim9script() && SCRIPT_ID_VALID(current_sctx.sc_sid)) | 1229 if (in_vim9script() && SCRIPT_ID_VALID(current_sctx.sc_sid)) |
1230 { | 1230 { |
1231 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); | 1231 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); |
1232 int i; | 1232 int i; |
1233 int first; | |
1233 int func_defined = cstack->cs_flags[cstack->cs_idx] | 1234 int func_defined = cstack->cs_flags[cstack->cs_idx] |
1234 & CSF_FUNC_DEF; | 1235 & CSF_FUNC_DEF; |
1235 | 1236 |
1236 // Any variables defined in the previous round are no longer | 1237 // Any variables defined in the previous round are no longer |
1237 // visible. Keep the first one for ":for", it is the loop | 1238 // visible. Keep the first one for ":for", it is the loop |
1238 // variable that we reuse every time around. | 1239 // variable that we reuse every time around. |
1239 for (i = cstack->cs_script_var_len[cstack->cs_idx] | 1240 // Do this backwards, so that vars defined in a later round are |
1241 // found first. | |
1242 first = cstack->cs_script_var_len[cstack->cs_idx] | |
1240 + (eap->cmdidx == CMD_while ? 0 : 1); | 1243 + (eap->cmdidx == CMD_while ? 0 : 1); |
1241 i < si->sn_var_vals.ga_len; ++i) | 1244 for (i = si->sn_var_vals.ga_len - 1; i >= first; --i) |
1242 { | 1245 { |
1243 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i; | 1246 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i; |
1244 | 1247 |
1245 // sv_name is set to NULL if it was already removed. This | 1248 // sv_name is set to NULL if it was already removed. This |
1246 // happens when it was defined in an inner block and no | 1249 // happens when it was defined in an inner block and no |
1248 if (sv->sv_name != NULL) | 1251 if (sv->sv_name != NULL) |
1249 // Remove a variable declared inside the block, if it | 1252 // Remove a variable declared inside the block, if it |
1250 // still exists, from sn_vars. | 1253 // still exists, from sn_vars. |
1251 hide_script_var(si, i, func_defined); | 1254 hide_script_var(si, i, func_defined); |
1252 } | 1255 } |
1256 | |
1257 // Start a new block ID, so that variables defined inside the | |
1258 // loop are created new and not shared with the previous loop. | |
1259 // Matters when used in a closure. | |
1260 cstack->cs_block_id[cstack->cs_idx] = ++si->sn_last_block_id; | |
1261 si->sn_current_block_id = si->sn_last_block_id; | |
1253 } | 1262 } |
1254 } | 1263 } |
1255 cstack->cs_flags[cstack->cs_idx] = | 1264 cstack->cs_flags[cstack->cs_idx] = |
1256 eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR; | 1265 eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR; |
1257 | 1266 |