diff src/vim9compile.c @ 28173:b0c885507de4 v8.2.4612

patch 8.2.4612: Vim9: cannot use a recursive call in a nested function Commit: https://github.com/vim/vim/commit/a915fa010330ee7212e06d3511acd363d04d2d28 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Mar 23 11:29:15 2022 +0000 patch 8.2.4612: Vim9: cannot use a recursive call in a nested function Problem: Vim9: cannot use a recursive call in a nested function. (Sergey Vlasov) Solution: Define the funcref before compiling the function. (closes #9989)
author Bram Moolenaar <Bram@vim.org>
date Wed, 23 Mar 2022 12:30:04 +0100
parents 088d8dc22045
children 662d2d5db9a6
line wrap: on
line diff
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -818,6 +818,7 @@ compile_nested_function(exarg_T *eap, cc
     ufunc_T	*ufunc;
     int		r = FAIL;
     compiletype_T   compile_type;
+    isn_T	*funcref_isn = NULL;
 
     if (eap->forceit)
     {
@@ -913,6 +914,27 @@ compile_nested_function(exarg_T *eap, cc
 	}
     }
 
+    // Define the funcref before compiling, so that it is found by any
+    // recursive call.
+    if (is_global)
+    {
+	r = generate_NEWFUNC(cctx, lambda_name, func_name);
+	func_name = NULL;
+	lambda_name = NULL;
+    }
+    else
+    {
+	// Define a local variable for the function reference.
+	lvar_T	*lvar = reserve_local(cctx, func_name, name_end - name_start,
+						    TRUE, ufunc->uf_func_type);
+
+	if (lvar == NULL)
+	    goto theend;
+	if (generate_FUNCREF(cctx, ufunc, &funcref_isn) == FAIL)
+	    goto theend;
+	r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
+    }
+
     compile_type = get_compile_type(ufunc);
 #ifdef FEAT_PROFILE
     // If the outer function is profiled, also compile the nested function for
@@ -934,24 +956,9 @@ compile_nested_function(exarg_T *eap, cc
 	compile_def_function(ufunc, FALSE, CT_NONE, cctx);
 #endif
 
-    if (is_global)
-    {
-	r = generate_NEWFUNC(cctx, lambda_name, func_name);
-	func_name = NULL;
-	lambda_name = NULL;
-    }
-    else
-    {
-	// Define a local variable for the function reference.
-	lvar_T	*lvar = reserve_local(cctx, func_name, name_end - name_start,
-						    TRUE, ufunc->uf_func_type);
-
-	if (lvar == NULL)
-	    goto theend;
-	if (generate_FUNCREF(cctx, ufunc) == FAIL)
-	    goto theend;
-	r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
-    }
+    // If a FUNCREF instruction was generated, set the index after compiling.
+    if (funcref_isn != NULL && ufunc->uf_def_status == UF_COMPILED)
+	funcref_isn->isn_arg.funcref.fr_dfunc_idx = ufunc->uf_dfunc_idx;
 
 theend:
     vim_free(lambda_name);