patch 9.0.0470: in :def function all closures in loop get the same variables
Problem: In a :def function all closures in a loop get the same variables.
Solution: When in a loop and a closure refers to a variable declared in the
loop, prepare for making a copy of variables for each closure.
diff --git a/src/vim9instr.c b/src/vim9instr.c
index 6a387fa..46f0b36 100644
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -1284,6 +1284,27 @@
}
/*
+ * Generate an ISN_WHILE instruction. Similar to ISN_JUMP for :while
+ */
+ int
+generate_WHILE(cctx_T *cctx, int funcref_idx)
+{
+ isn_T *isn;
+ garray_T *stack = &cctx->ctx_type_stack;
+
+ RETURN_OK_IF_SKIP(cctx);
+ if ((isn = generate_instr(cctx, ISN_WHILE)) == NULL)
+ return FAIL;
+ isn->isn_arg.whileloop.while_funcref_idx = funcref_idx;
+ isn->isn_arg.whileloop.while_end = 0; // filled in later
+
+ if (stack->ga_len > 0)
+ --stack->ga_len;
+
+ return OK;
+}
+
+/*
* Generate an ISN_JUMP_IF_ARG_SET instruction.
*/
int
@@ -1312,6 +1333,25 @@
// type doesn't matter, will be stored next
return push_type_stack(cctx, &t_any);
}
+
+ int
+generate_ENDLOOP(
+ cctx_T *cctx,
+ int funcref_idx,
+ int prev_local_count)
+{
+ isn_T *isn;
+
+ RETURN_OK_IF_SKIP(cctx);
+ if ((isn = generate_instr(cctx, ISN_ENDLOOP)) == NULL)
+ return FAIL;
+ isn->isn_arg.endloop.end_funcref_idx = funcref_idx;
+ isn->isn_arg.endloop.end_var_idx = prev_local_count;
+ isn->isn_arg.endloop.end_var_count =
+ cctx->ctx_locals.ga_len - prev_local_count;
+ return OK;
+}
+
/*
* Generate an ISN_TRYCONT instruction.
*/
@@ -2295,6 +2335,7 @@
case ISN_ECHOERR:
case ISN_ECHOMSG:
case ISN_ECHOWINDOW:
+ case ISN_ENDLOOP:
case ISN_ENDTRY:
case ISN_EXECCONCAT:
case ISN_EXECUTE:
@@ -2341,10 +2382,10 @@
case ISN_RETURN_VOID:
case ISN_SHUFFLE:
case ISN_SLICE:
+ case ISN_SOURCE:
case ISN_STORE:
case ISN_STOREINDEX:
case ISN_STORENR:
- case ISN_SOURCE:
case ISN_STOREOUTER:
case ISN_STORERANGE:
case ISN_STOREREG:
@@ -2357,6 +2398,7 @@
case ISN_UNLETRANGE:
case ISN_UNPACK:
case ISN_USEDICT:
+ case ISN_WHILE:
// nothing allocated
break;
}