diff src/vim9.h @ 20247:e46e72aaff74 v8.2.0679

patch 8.2.0679: Vim9: incomplete support for closures Commit: https://github.com/vim/vim/commit/bf67ea1af05cbb30cd8f0b665fb567c0dca79796 Author: Bram Moolenaar <Bram@vim.org> Date: Sat May 2 17:52:42 2020 +0200 patch 8.2.0679: Vim9: incomplete support for closures Problem: Vim9: incomplete support for closures. Solution: At the end of a function copy arguments and local variables if they are still used by a referenced closure.
author Bram Moolenaar <Bram@vim.org>
date Sat, 02 May 2020 18:00:04 +0200
parents 23d75968ca5e
children 683c2da4982b
line wrap: on
line diff
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -71,7 +71,7 @@ typedef enum {
     ISN_PCALL,	    // call partial, use isn_arg.pfunc
     ISN_PCALL_END,  // cleanup after ISN_PCALL with cpf_top set
     ISN_RETURN,	    // return, result is on top of stack
-    ISN_FUNCREF,    // push a function ref to dfunc isn_arg.number
+    ISN_FUNCREF,    // push a function ref to dfunc isn_arg.funcref
 
     // expression operations
     ISN_JUMP,	    // jump if condition is matched isn_arg.jump
@@ -218,6 +218,12 @@ typedef struct {
     int		ul_forceit;	// forceit flag
 } unlet_T;
 
+// arguments to ISN_FUNCREF
+typedef struct {
+    int		fr_func;	// function index
+    int		fr_var_idx;	// variable to store partial
+} funcref_T;
+
 /*
  * Instruction
  */
@@ -249,10 +255,26 @@ struct isn_S {
 	loadstore_T	    loadstore;
 	script_T	    script;
 	unlet_T		    unlet;
+	funcref_T	    funcref;
     } isn_arg;
 };
 
 /*
+ * Structure to hold the context of a compiled function, used by closures
+ * defined in that function.
+ */
+typedef struct funcstack_S
+{
+    garray_T	fs_ga;		// contains the stack, with:
+				// - arguments
+				// - frame
+				// - local variables
+
+    int		fs_refcount;	// nr of closures referencing this funcstack
+    int		fs_copyID;	// for garray_T collection
+} funcstack_T;
+
+/*
  * Info about a function defined with :def.  Used in "def_functions".
  */
 struct dfunc_S {
@@ -264,10 +286,19 @@ struct dfunc_S {
     isn_T	*df_instr;	    // function body to be executed
     int		df_instr_count;
 
+    garray_T	*df_ectx_stack;	    // where compiled closure finds local vars
+    int		df_ectx_frame;	    // index of function frame in uf_ectx_stack
+    funcstack_T	*df_funcstack;	    // copy of stack for closure, used after
+				    // closure context function returns
+
     int		df_varcount;	    // number of local variables
+    int		df_closure_count;   // number of closures created
 };
 
 // Number of entries used by stack frame for a function call.
+// - function index
+// - instruction index
+// - previous frame index
 #define STACK_FRAME_SIZE 3