diff src/vim9compile.c @ 20943:1693ca876049 v8.2.1023

patch 8.2.1023: Vim9: redefining a function uses a new index every time Commit: https://github.com/vim/vim/commit/0cb5bcf5836de83f7d64fb01d3ce708caacaf66c Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jun 20 18:19:09 2020 +0200 patch 8.2.1023: Vim9: redefining a function uses a new index every time Problem: Vim9: redefining a function uses a new index every time. Solution: When redefining a function clear the contents and re-use the index.
author Bram Moolenaar <Bram@vim.org>
date Sat, 20 Jun 2020 18:30:04 +0200
parents e2fd5f05342f
children 0653b9b72091
line wrap: on
line diff
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1493,7 +1493,7 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufu
 	return FAIL;
     }
 
-    if (ufunc->uf_dfunc_idx != UF_NOT_COMPILED)
+    if (ufunc->uf_def_status != UF_NOT_COMPILED)
     {
 	int		i;
 
@@ -1517,16 +1517,16 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufu
 		return FAIL;
 	    }
 	}
-	if (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED)
+	if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
 	    if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
 		return FAIL;
     }
 
     if ((isn = generate_instr(cctx,
-		    ufunc->uf_dfunc_idx != UF_NOT_COMPILED ? ISN_DCALL
+		    ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
 							 : ISN_UCALL)) == NULL)
 	return FAIL;
-    if (ufunc->uf_dfunc_idx != UF_NOT_COMPILED)
+    if (ufunc->uf_def_status != UF_NOT_COMPILED)
     {
 	isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
 	isn->isn_arg.dfunc.cdf_argcount = argcount;
@@ -3042,7 +3042,7 @@ compile_lambda(char_u **arg, cctx_T *cct
     // Compile it into instructions.
     compile_def_function(ufunc, TRUE, cctx);
 
-    if (ufunc->uf_dfunc_idx >= 0)
+    if (ufunc->uf_def_status == UF_COMPILED)
 	return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
     return FAIL;
 }
@@ -4539,7 +4539,7 @@ compile_nested_function(exarg_T *eap, cc
 
     if (ufunc == NULL)
 	return NULL;
-    if (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED
+    if (ufunc->uf_def_status == UF_TO_BE_COMPILED
 	    && compile_def_function(ufunc, TRUE, cctx) == FAIL)
 	return NULL;
 
@@ -6517,13 +6517,22 @@ theend:
 
 /*
  * Add a function to the list of :def functions.
- * This "sets ufunc->uf_dfunc_idx" but the function isn't compiled yet.
+ * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet.
  */
     static int
 add_def_function(ufunc_T *ufunc)
 {
     dfunc_T *dfunc;
 
+    if (def_functions.ga_len == 0)
+    {
+	// The first position is not used, so that a zero uf_dfunc_idx means it
+	// wasn't set.
+	if (ga_grow(&def_functions, 1) == FAIL)
+	    return FAIL;
+	++def_functions.ga_len;
+    }
+
     // Add the function to "def_functions".
     if (ga_grow(&def_functions, 1) == FAIL)
 	return FAIL;
@@ -6563,7 +6572,7 @@ compile_def_function(ufunc_T *ufunc, int
 
     // When using a function that was compiled before: Free old instructions.
     // Otherwise add a new entry in "def_functions".
-    if (ufunc->uf_dfunc_idx >= 0)
+    if (ufunc->uf_dfunc_idx > 0)
     {
 	dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
 							 + ufunc->uf_dfunc_idx;
@@ -7014,6 +7023,7 @@ compile_def_function(ufunc_T *ufunc, int
 	dfunc->df_closure_count = cctx.ctx_closure_count;
 	if (cctx.ctx_outer_used)
 	    ufunc->uf_flags |= FC_CLOSURE;
+	ufunc->uf_def_status = UF_COMPILED;
     }
 
     ret = OK;
@@ -7033,7 +7043,7 @@ erret:
 	if (!dfunc->df_deleted
 			    && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
 	    --def_functions.ga_len;
-	ufunc->uf_dfunc_idx = UF_NOT_COMPILED;
+	ufunc->uf_def_status = UF_NOT_COMPILED;
 
 	while (cctx.ctx_scope != NULL)
 	    drop_scope(&cctx);
@@ -7261,17 +7271,19 @@ delete_def_function_contents(dfunc_T *df
 }
 
 /*
- * When a user function is deleted, delete any associated def function.
+ * When a user function is deleted, clear the contents of any associated def
+ * function.  The position in def_functions can be re-used.
  */
     void
-delete_def_function(ufunc_T *ufunc)
-{
-    if (ufunc->uf_dfunc_idx >= 0)
+clear_def_function(ufunc_T *ufunc)
+{
+    if (ufunc->uf_dfunc_idx > 0)
     {
 	dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
 							 + ufunc->uf_dfunc_idx;
 
 	delete_def_function_contents(dfunc);
+	ufunc->uf_def_status = UF_NOT_COMPILED;
     }
 }