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.
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 7329a8b..2ac7a0a 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1493,7 +1493,7 @@
return FAIL;
}
- if (ufunc->uf_dfunc_idx != UF_NOT_COMPILED)
+ if (ufunc->uf_def_status != UF_NOT_COMPILED)
{
int i;
@@ -1517,16 +1517,16 @@
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 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 @@
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 @@
/*
* 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 @@
// 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 @@
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 @@
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 @@
}
/*
- * 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)
+clear_def_function(ufunc_T *ufunc)
{
- 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;
delete_def_function_contents(dfunc);
+ ufunc->uf_def_status = UF_NOT_COMPILED;
}
}