Skip to content

Commit 0186e58

Browse files
committed
patch 8.2.2322: Vim9: closure nested limiting to one level
Problem: Vim9: closure nested limiting to one level. Solution: Add outer_T. Also make STOREOUTER work.
1 parent ab36052 commit 0186e58

5 files changed

Lines changed: 156 additions & 129 deletions

File tree

src/structs.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,14 @@ typedef struct funcstack_S
19651965
int fs_copyID; // for garray_T collection
19661966
} funcstack_T;
19671967

1968+
typedef struct outer_S outer_T;
1969+
struct outer_S {
1970+
garray_T *out_stack; // stack from outer scope
1971+
int out_frame_idx; // index of stack frame in out_stack
1972+
outer_T *out_up; // outer scope of outer scope or NULL
1973+
int out_up_is_copy; // don't free out_up
1974+
};
1975+
19681976
struct partial_S
19691977
{
19701978
int pt_refcount; // reference count
@@ -1975,13 +1983,11 @@ struct partial_S
19751983
int pt_auto; // when TRUE the partial was created for using
19761984
// dict.member in handle_subscript()
19771985

1978-
// For a compiled closure: the arguments and local variables.
1979-
garray_T *pt_ectx_stack; // where to find local vars
1980-
int pt_ectx_frame; // index of function frame in uf_ectx_stack
1981-
garray_T *pt_outer_stack; // pt_ectx_stack one level up
1982-
int pt_outer_frame; // pt_ectx_frame one level up.
1983-
funcstack_T *pt_funcstack; // copy of stack, used after context
1984-
// function returns
1986+
// For a compiled closure: the arguments and local variables scope
1987+
outer_T pt_outer;
1988+
1989+
funcstack_T *pt_funcstack; // copy of stack, used after context
1990+
// function returns
19851991

19861992
int pt_argc; // number of arguments
19871993
typval_T *pt_argv; // arguments in allocated array

src/testdir/test_vim9_func.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,6 +1822,13 @@ def Test_nested_closure_using_argument()
18221822
assert_equal(['x', 'x2'], DoFilterThis('x'))
18231823
enddef
18241824

1825+
def Test_triple_nested_closure()
1826+
var what = 'x'
1827+
var Match = (val: string, cmp: string): bool => stridx(val, cmp) == 0
1828+
var Filter = (l) => filter(l, (_, v) => Match(v, what))
1829+
assert_equal(['x', 'x2'], ['x', 'y', 'a', 'x2', 'c']->Filter())
1830+
enddef
1831+
18251832
func Test_silent_echo()
18261833
CheckScreendump
18271834

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2322,
753755
/**/
754756
2321,
755757
/**/

src/vim9.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ typedef struct {
307307
typedef struct {
308308
int outer_idx; // index
309309
int outer_depth; // nesting level, stack frames to go up
310-
} outer_T;
310+
} isn_outer_T;
311311

312312
/*
313313
* Instruction
@@ -348,7 +348,7 @@ struct isn_S {
348348
put_T put;
349349
cmod_T cmdmod;
350350
unpack_T unpack;
351-
outer_T outer;
351+
isn_outer_T outer;
352352
} isn_arg;
353353
};
354354

@@ -375,10 +375,13 @@ struct dfunc_S {
375375
// Number of entries used by stack frame for a function call.
376376
// - ec_dfunc_idx: function index
377377
// - ec_iidx: instruction index
378-
// - ec_outer_stack: stack used for closures TODO: can we avoid this?
379-
// - ec_outer_frame: stack frame for closures
378+
// - ec_outer: stack used for closures
380379
// - ec_frame_idx: previous frame index
381-
#define STACK_FRAME_SIZE 5
380+
#define STACK_FRAME_FUNC_OFF 0
381+
#define STACK_FRAME_IIDX_OFF 1
382+
#define STACK_FRAME_OUTER_OFF 2
383+
#define STACK_FRAME_IDX_OFF 3
384+
#define STACK_FRAME_SIZE 4
382385

383386

384387
#ifdef DEFINE_VIM9_GLOBALS

0 commit comments

Comments
 (0)