endfor
END
v9.CheckDefAndScriptSuccess(lines)
+
+ # assigning to a variable declared in the loop from a closure
+ lines =<< trim END
+ for i in range(3)
+ var inloop = 0
+ var F = () => {
+ inloop = i + 1
+ }
+ F()
+ assert_equal(i + 1, inloop)
+ endfor
+ END
+ v9.CheckDefAndScriptSuccess(lines)
+
+ # same in a nested loop
+ lines =<< trim END
+ var result: list<number>
+ for i in range(2)
+ for j in range(2)
+ var inloop = 0
+ var F = () => {
+ inloop = i * 10 + j
+ }
+ F()
+ result += [inloop]
+ endfor
+ endfor
+ assert_equal([0, 1, 10, 11], result)
+ END
+ v9.CheckDefAndScriptSuccess(lines)
enddef
def Test_define_global_closure_in_loops()
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 877,
/**/
876,
/**/
// arguments to ISN_LOADOUTER and ISN_STOREOUTER
typedef struct {
int outer_idx; // index
- int outer_depth; // nesting level, stack frames to go up
+ int outer_depth; // nesting level, stack frames to go up;
+ // negative for a loop variable, the loop
+ // depth is -outer_depth - 1
} isn_outer_T;
-#define OUTER_LOOP_DEPTH -9 // used for outer_depth for loop variables
-
// arguments to ISN_SUBSTITUTE
typedef struct {
char_u *subs_cmd; // :s command
{
isn_outer_T *outer = &iptr->isn_arg.outer;
- if (outer->outer_depth == OUTER_LOOP_DEPTH)
- smsg("%s%4d STOREOUTER level 1 $%d in loop",
- pfx, current, outer->outer_idx);
+ if (outer->outer_depth < 0)
+ smsg("%s%4d STOREOUTER $%d in loop level %d",
+ pfx, current, outer->outer_idx,
+ -outer->outer_depth);
else
smsg("%s%4d STOREOUTER level %d $%d", pfx, current,
outer->outer_depth, outer->outer_idx);
* Generate an ISN_STOREOUTER instruction.
*/
static int
-generate_STOREOUTER(cctx_T *cctx, int idx, int level, int loop_idx)
+generate_STOREOUTER(
+ cctx_T *cctx,
+ int idx,
+ int level,
+ int loop_depth,
+ int loop_idx)
{
isn_T *isn;
if (level == 1 && loop_idx >= 0 && idx >= loop_idx)
{
// Store a variable defined in a loop. A copy will be made at the end
- // of the loop. TODO: how about deeper nesting?
+ // of the loop.
isn->isn_arg.outer.outer_idx = idx - loop_idx;
- isn->isn_arg.outer.outer_depth = OUTER_LOOP_DEPTH;
+ isn->isn_arg.outer.outer_depth = -loop_depth - 1;
}
else
{
}
else if (lhs->lhs_lvar->lv_from_outer > 0)
generate_STOREOUTER(cctx, lhs->lhs_lvar->lv_idx,
- lhs->lhs_lvar->lv_from_outer, lhs->lhs_lvar->lv_loop_idx);
+ lhs->lhs_lvar->lv_from_outer, lhs->lhs_lvar->lv_loop_depth,
+ lhs->lhs_lvar->lv_loop_idx);
else
generate_STORE(cctx, ISN_STORE, lhs->lhs_lvar->lv_idx, NULL);
return OK;