comparison src/vim9cmds.c @ 30333:fc0830246f49 v9.0.0502

patch 9.0.0502: a closure in a nested loop in a :def function does not work Commit: https://github.com/vim/vim/commit/cc34181f9994d64f8c8fa2f5845eaf0cc963067f Author: Bram Moolenaar <Bram@vim.org> Date: Mon Sep 19 15:54:34 2022 +0100 patch 9.0.0502: a closure in a nested loop in a :def function does not work Problem: A closure in a nested loop in a :def function does not work. Solution: Use an array of loopvars, one per loop level.
author Bram Moolenaar <Bram@vim.org>
date Mon, 19 Sep 2022 17:00:07 +0200
parents bee38b1d323c
children ee039a6049ff
comparison
equal deleted inserted replaced
30332:462d122636b3 30333:fc0830246f49
345 return NULL; 345 return NULL;
346 scope->se_outer = cctx->ctx_scope; 346 scope->se_outer = cctx->ctx_scope;
347 cctx->ctx_scope = scope; 347 cctx->ctx_scope = scope;
348 scope->se_type = type; 348 scope->se_type = type;
349 scope->se_local_count = cctx->ctx_locals.ga_len; 349 scope->se_local_count = cctx->ctx_locals.ga_len;
350 if (scope->se_outer != NULL)
351 scope->se_loop_depth = scope->se_outer->se_loop_depth;
350 return scope; 352 return scope;
351 } 353 }
352 354
353 /* 355 /*
354 * Free the current scope and go back to the outer scope. 356 * Free the current scope and go back to the outer scope.
821 size_t varlen; 823 size_t varlen;
822 garray_T *instr = &cctx->ctx_instr; 824 garray_T *instr = &cctx->ctx_instr;
823 scope_T *scope; 825 scope_T *scope;
824 forscope_T *forscope; 826 forscope_T *forscope;
825 lvar_T *loop_lvar; // loop iteration variable 827 lvar_T *loop_lvar; // loop iteration variable
828 int loop_lvar_idx;
826 lvar_T *funcref_lvar; 829 lvar_T *funcref_lvar;
830 int funcref_lvar_idx;
827 lvar_T *var_lvar; // variable for "var" 831 lvar_T *var_lvar; // variable for "var"
828 type_T *vartype; 832 type_T *vartype;
829 type_T *item_type = &t_any; 833 type_T *item_type = &t_any;
830 int idx; 834 int idx;
831 int prev_lnum = cctx->ctx_prev_lnum; 835 int prev_lnum = cctx->ctx_prev_lnum;
865 } 869 }
866 870
867 scope = new_scope(cctx, FOR_SCOPE); 871 scope = new_scope(cctx, FOR_SCOPE);
868 if (scope == NULL) 872 if (scope == NULL)
869 return NULL; 873 return NULL;
874 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
875 {
876 emsg(_(e_loop_nesting_too_deep));
877 return NULL;
878 }
879 ++scope->se_loop_depth;
870 forscope = &scope->se_u.se_for; 880 forscope = &scope->se_u.se_for;
871 881
872 // Reserve a variable to store the loop iteration counter and initialize it 882 // Reserve a variable to store the loop iteration counter and initialize it
873 // to -1. 883 // to -1.
874 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number); 884 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
875 if (loop_lvar == NULL) 885 if (loop_lvar == NULL)
876 { 886 {
877 drop_scope(cctx); 887 drop_scope(cctx);
878 return NULL; // out of memory 888 return NULL; // out of memory
879 } 889 }
880 generate_STORENR(cctx, loop_lvar->lv_idx, -1); 890 // get the index before a following reserve_local() makes the lval invalid
891 loop_lvar_idx = loop_lvar->lv_idx;
892 generate_STORENR(cctx, loop_lvar_idx, -1);
881 893
882 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP. 894 // Reserve a variable to store ec_funcrefs.ga_len, used in ISN_ENDLOOP.
883 // The variable index is always the loop var index plus one. 895 // The variable index is always the loop var index plus one.
884 // It is not used when no closures are encountered, we don't know yet. 896 // It is not used when no closures are encountered, we don't know yet.
885 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number); 897 funcref_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
886 if (funcref_lvar == NULL) 898 if (funcref_lvar == NULL)
887 { 899 {
888 drop_scope(cctx); 900 drop_scope(cctx);
889 return NULL; // out of memory 901 return NULL; // out of memory
890 } 902 }
903 // get the index before a following reserve_local() makes the lval invalid
904 funcref_lvar_idx = funcref_lvar->lv_idx;
891 905
892 // compile "expr", it remains on the stack until "endfor" 906 // compile "expr", it remains on the stack until "endfor"
893 arg = p; 907 arg = p;
894 if (compile_expr0(&arg, cctx) == FAIL) 908 if (compile_expr0(&arg, cctx) == FAIL)
895 { 909 {
949 isn = generate_instr_debug(cctx); 963 isn = generate_instr_debug(cctx);
950 ++isn->isn_arg.debug.dbg_var_names_len; 964 ++isn->isn_arg.debug.dbg_var_names_len;
951 cctx->ctx_prev_lnum = save_prev_lnum; 965 cctx->ctx_prev_lnum = save_prev_lnum;
952 } 966 }
953 967
954 generate_FOR(cctx, loop_lvar->lv_idx); 968 generate_FOR(cctx, loop_lvar_idx);
955 969
956 arg = arg_start; 970 arg = arg_start;
957 if (var_list) 971 if (var_list)
958 { 972 {
959 generate_UNPACK(cctx, var_count, semicolon); 973 generate_UNPACK(cctx, var_count, semicolon);
1051 arg = skipwhite(p); 1065 arg = skipwhite(p);
1052 vim_free(name); 1066 vim_free(name);
1053 } 1067 }
1054 1068
1055 // remember the number of variables and closures, used for ENDLOOP 1069 // remember the number of variables and closures, used for ENDLOOP
1056 compile_fill_loop_info(&forscope->fs_loop_info, 1070 compile_fill_loop_info(&forscope->fs_loop_info, funcref_lvar_idx, cctx);
1057 funcref_lvar->lv_idx, cctx); 1071 forscope->fs_loop_info.li_depth = scope->se_loop_depth - 1;
1058 } 1072 }
1059 1073
1060 return arg_end; 1074 return arg_end;
1061 1075
1062 failed: 1076 failed:
1073 static int 1087 static int
1074 compile_loop_end(loop_info_T *loop_info, cctx_T *cctx) 1088 compile_loop_end(loop_info_T *loop_info, cctx_T *cctx)
1075 { 1089 {
1076 if (cctx->ctx_locals.ga_len > loop_info->li_local_count 1090 if (cctx->ctx_locals.ga_len > loop_info->li_local_count
1077 && cctx->ctx_closure_count > loop_info->li_closure_count) 1091 && cctx->ctx_closure_count > loop_info->li_closure_count)
1078 return generate_ENDLOOP(cctx, loop_info->li_funcref_idx, 1092 return generate_ENDLOOP(cctx, loop_info);
1079 loop_info->li_local_count);
1080 return OK; 1093 return OK;
1081 } 1094 }
1082 1095
1083 /* 1096 /*
1084 * compile "endfor" 1097 * compile "endfor"
1149 { 1162 {
1150 char_u *p = arg; 1163 char_u *p = arg;
1151 scope_T *scope; 1164 scope_T *scope;
1152 whilescope_T *whilescope; 1165 whilescope_T *whilescope;
1153 lvar_T *funcref_lvar; 1166 lvar_T *funcref_lvar;
1167 int funcref_lvar_idx;
1154 1168
1155 scope = new_scope(cctx, WHILE_SCOPE); 1169 scope = new_scope(cctx, WHILE_SCOPE);
1156 if (scope == NULL) 1170 if (scope == NULL)
1157 return NULL; 1171 return NULL;
1172 if (scope->se_loop_depth == MAX_LOOP_DEPTH)
1173 {
1174 emsg(_(e_loop_nesting_too_deep));
1175 return NULL;
1176 }
1177 ++scope->se_loop_depth;
1158 whilescope = &scope->se_u.se_while; 1178 whilescope = &scope->se_u.se_while;
1159 1179
1160 // "endwhile" jumps back here, one before when profiling or using cmdmods 1180 // "endwhile" jumps back here, one before when profiling or using cmdmods
1161 whilescope->ws_top_label = current_instr_idx(cctx); 1181 whilescope->ws_top_label = current_instr_idx(cctx);
1162 1182
1166 if (funcref_lvar == NULL) 1186 if (funcref_lvar == NULL)
1167 { 1187 {
1168 drop_scope(cctx); 1188 drop_scope(cctx);
1169 return NULL; // out of memory 1189 return NULL; // out of memory
1170 } 1190 }
1191 // get the index before a following reserve_local() makes the lval invalid
1192 funcref_lvar_idx = funcref_lvar->lv_idx;
1171 1193
1172 // remember the number of variables and closures, used for ENDLOOP 1194 // remember the number of variables and closures, used for ENDLOOP
1173 compile_fill_loop_info(&whilescope->ws_loop_info, 1195 compile_fill_loop_info(&whilescope->ws_loop_info, funcref_lvar_idx, cctx);
1174 funcref_lvar->lv_idx, cctx); 1196 whilescope->ws_loop_info.li_depth = scope->se_loop_depth - 1;
1175 1197
1176 // compile "expr" 1198 // compile "expr"
1177 if (compile_expr0(&p, cctx) == FAIL) 1199 if (compile_expr0(&p, cctx) == FAIL)
1178 return NULL; 1200 return NULL;
1179 1201
1191 // CMDMOD_REV must come before the jump 1213 // CMDMOD_REV must come before the jump
1192 generate_undo_cmdmods(cctx); 1214 generate_undo_cmdmods(cctx);
1193 1215
1194 // "while_end" is set when ":endwhile" is found 1216 // "while_end" is set when ":endwhile" is found
1195 if (compile_jump_to_end(&whilescope->ws_end_label, 1217 if (compile_jump_to_end(&whilescope->ws_end_label,
1196 JUMP_WHILE_FALSE, funcref_lvar->lv_idx, cctx) == FAIL) 1218 JUMP_WHILE_FALSE, funcref_lvar_idx, cctx) == FAIL)
1197 return FAIL; 1219 return FAIL;
1198 } 1220 }
1199 1221
1200 return p; 1222 return p;
1201 } 1223 }
1247 return arg; 1269 return arg;
1248 } 1270 }
1249 1271
1250 /* 1272 /*
1251 * Get the current information about variables declared inside a loop. 1273 * Get the current information about variables declared inside a loop.
1252 * Returns zero if there are none, otherwise the count. 1274 * Returns TRUE if there are any and fills "lvi".
1253 * "loop_var_idx" is then set to the index of the first variable. 1275 */
1254 */ 1276 int
1255 short 1277 get_loop_var_info(cctx_T *cctx, loopvarinfo_T *lvi)
1256 get_loop_var_info(cctx_T *cctx, short *loop_var_idx)
1257 { 1278 {
1258 scope_T *scope = cctx->ctx_scope; 1279 scope_T *scope = cctx->ctx_scope;
1259 int start_local_count; 1280 int prev_local_count = 0;
1260 1281
1261 while (scope != NULL && scope->se_type != WHILE_SCOPE 1282 CLEAR_POINTER(lvi);
1283 for (;;)
1284 {
1285 loop_info_T *loopinfo;
1286 int cur_local_last;
1287 int start_local_count;
1288
1289 while (scope != NULL && scope->se_type != WHILE_SCOPE
1262 && scope->se_type != FOR_SCOPE) 1290 && scope->se_type != FOR_SCOPE)
1291 scope = scope->se_outer;
1292 if (scope == NULL)
1293 break;
1294
1295 if (scope->se_type == WHILE_SCOPE)
1296 {
1297 loopinfo = &scope->se_u.se_while.ws_loop_info;
1298 // :while reserves one variable for funcref count
1299 cur_local_last = loopinfo->li_local_count - 1;
1300 }
1301 else
1302 {
1303 loopinfo = &scope->se_u.se_for.fs_loop_info;
1304 // :for reserves three variable: loop count, funcref count and loop
1305 // var
1306 cur_local_last = loopinfo->li_local_count - 3;
1307 }
1308
1309 start_local_count = loopinfo->li_local_count;
1310 if (cctx->ctx_locals.ga_len > start_local_count)
1311 {
1312 lvi->lvi_loop[loopinfo->li_depth].var_idx =
1313 (short)start_local_count;
1314 lvi->lvi_loop[loopinfo->li_depth].var_count =
1315 (short)(cctx->ctx_locals.ga_len - start_local_count
1316 - prev_local_count);
1317 if (lvi->lvi_depth == 0)
1318 lvi->lvi_depth = loopinfo->li_depth + 1;
1319 }
1320
1263 scope = scope->se_outer; 1321 scope = scope->se_outer;
1264 if (scope == NULL) 1322 prev_local_count = cctx->ctx_locals.ga_len - cur_local_last;
1265 return 0; 1323 }
1266 1324 return lvi->lvi_depth > 0;
1267 if (scope->se_type == WHILE_SCOPE) 1325 }
1268 start_local_count = scope->se_u.se_while.ws_loop_info.li_local_count; 1326
1269 else 1327 /*
1270 start_local_count = scope->se_u.se_for.fs_loop_info.li_local_count; 1328 * Get the index of the variable "idx" in a loop, if any.
1271 if (cctx->ctx_locals.ga_len > start_local_count) 1329 */
1272 { 1330 void
1273 *loop_var_idx = (short)start_local_count; 1331 get_loop_var_idx(cctx_T *cctx, int idx, lvar_T *lvar)
1274 return (short)(cctx->ctx_locals.ga_len - start_local_count); 1332 {
1275 } 1333 loopvarinfo_T lvi;
1276 return 0; 1334
1277 } 1335 lvar->lv_loop_depth = -1;
1278 1336 lvar->lv_loop_idx = -1;
1279 /* 1337 if (get_loop_var_info(cctx, &lvi))
1280 * Get the index of the first variable in a loop, if any. 1338 {
1281 * Returns -1 if none. 1339 int depth;
1282 */ 1340
1283 int 1341 for (depth = lvi.lvi_depth - 1; depth >= 0; --depth)
1284 get_loop_var_idx(cctx_T *cctx) 1342 if (idx >= lvi.lvi_loop[depth].var_idx
1285 { 1343 && idx < lvi.lvi_loop[depth].var_idx
1286 short loop_var_idx; 1344 + lvi.lvi_loop[depth].var_count)
1287 1345 {
1288 if (get_loop_var_info(cctx, &loop_var_idx) > 0) 1346 lvar->lv_loop_depth = depth;
1289 return loop_var_idx; 1347 lvar->lv_loop_idx = lvi.lvi_loop[depth].var_idx;
1290 return -1; 1348 return;
1349 }
1350 }
1291 } 1351 }
1292 1352
1293 /* 1353 /*
1294 * Common for :break, :continue and :return 1354 * Common for :break, :continue and :return
1295 */ 1355 */