0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

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.
This commit is contained in:
Bram Moolenaar
2022-09-15 17:19:37 +01:00
parent 3735f11050
commit b46c083a5e
8 changed files with 315 additions and 58 deletions

View File

@@ -122,6 +122,9 @@ typedef enum {
// loop
ISN_FOR, // get next item from a list, uses isn_arg.forloop
ISN_WHILE, // jump if condition false, store funcref count, uses
// isn_arg.whileloop
ISN_ENDLOOP, // handle variables for closures, uses isn_arg.endloop
ISN_TRY, // add entry to ec_trystack, uses isn_arg.tryref
ISN_THROW, // pop value of stack, store in v:exception
@@ -240,6 +243,7 @@ typedef enum {
JUMP_ALWAYS,
JUMP_NEVER,
JUMP_IF_FALSE, // pop and jump if false
JUMP_WHILE_FALSE, // pop and jump if false for :while
JUMP_AND_KEEP_IF_TRUE, // jump if top of stack is truthy, drop if not
JUMP_IF_COND_TRUE, // jump if top of stack is true, drop if not
JUMP_IF_COND_FALSE, // jump if top of stack is false, drop if not
@@ -263,6 +267,19 @@ typedef struct {
int for_end; // position to jump to after done
} forloop_T;
// arguments to ISN_WHILE
typedef struct {
int while_funcref_idx; // variable index for funcref count
int while_end; // position to jump to after done
} whileloop_T;
// arguments to ISN_ENDLOOP
typedef struct {
short end_funcref_idx; // variable index of funcrefs.ga_len
short end_var_idx; // first variable declared in the loop
short end_var_count; // number of variables declared in the loop
} endloop_T;
// indirect arguments to ISN_TRY
typedef struct {
int try_catch; // position to jump to on throw
@@ -446,6 +463,8 @@ struct isn_S {
jump_T jump;
jumparg_T jumparg;
forloop_T forloop;
whileloop_T whileloop;
endloop_T endloop;
try_T tryref;
trycont_T trycont;
cbfunc_T bfunc;
@@ -597,6 +616,9 @@ typedef struct {
typedef struct {
int ws_top_label; // instruction idx at WHILE
endlabel_T *ws_end_label; // instructions to set end
int ws_funcref_idx; // index of var that holds funcref count
int ws_local_count; // ctx_locals.ga_len at :while
int ws_closure_count; // ctx_closure_count at :while
} whilescope_T;
/*
@@ -605,6 +627,9 @@ typedef struct {
typedef struct {
int fs_top_label; // instruction idx at FOR
endlabel_T *fs_end_label; // break instructions
int fs_funcref_idx; // index of var that holds funcref count
int fs_local_count; // ctx_locals.ga_len at :for
int fs_closure_count; // ctx_closure_count at :for
} forscope_T;
/*
@@ -726,8 +751,10 @@ struct cctx_S {
garray_T ctx_locals; // currently visible local variables
int ctx_has_closure; // set to one if a closure was created in
// the function
int ctx_has_closure; // set to one if a FUNCREF was used in the
// function
int ctx_closure_count; // incremented for each closure created in
// the function.
skip_T ctx_skip;
scope_T *ctx_scope; // current scope, NULL at toplevel