diff src/vim9.h @ 30269:42a6345b91fd v9.0.0470

patch 9.0.0470: in :def function all closures in loop get the same variables Commit: https://github.com/vim/vim/commit/b46c083a5ed9e0c4ac5f3aec577946dcbe8c9dc5 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Sep 15 17:19:37 2022 +0100 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.
author Bram Moolenaar <Bram@vim.org>
date Thu, 15 Sep 2022 18:30:04 +0200
parents 6575d0bf6061
children 61a688be1899
line wrap: on
line diff
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -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