diff src/vim9execute.c @ 19862:846fbbacce3a v8.2.0487

patch 8.2.0487: Vim9: compiling not sufficiently tested Commit: https://github.com/vim/vim/commit/bd5da371aafe5a2207065643502f4d1ff6b286c7 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Mar 31 23:13:10 2020 +0200 patch 8.2.0487: Vim9: compiling not sufficiently tested Problem: Vim9: compiling not sufficiently tested. Solution: Add more tests. Fix bug with PCALL.
author Bram Moolenaar <Bram@vim.org>
date Tue, 31 Mar 2020 23:15:04 +0200
parents e4ade28bfaf7
children 8a7bede7b138
line wrap: on
line diff
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -345,7 +345,7 @@ call_by_name(char_u *name, int argcount,
     static int
 call_partial(typval_T *tv, int argcount, ectx_T *ectx)
 {
-    char_u	*name;
+    char_u	*name = NULL;
     int		called_emsg_before = called_emsg;
 
     if (tv->v_type == VAR_PARTIAL)
@@ -356,9 +356,9 @@ call_partial(typval_T *tv, int argcount,
 	    return call_ufunc(pt->pt_func, argcount, ectx, NULL);
 	name = pt->pt_name;
     }
-    else
+    else if (tv->v_type == VAR_FUNC)
 	name = tv->vval.v_string;
-    if (call_by_name(name, argcount, ectx, NULL) == FAIL)
+    if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL)
     {
 	if (called_emsg == called_emsg_before)
 	    semsg(_(e_unknownfunc), name);
@@ -421,7 +421,6 @@ call_def_function(
     typval_T	*tv;
     int		idx;
     int		ret = FAIL;
-    dfunc_T	*dfunc;
     int		defcount = ufunc->uf_args.ga_len - argc;
 
 // Get pointer to item in the stack.
@@ -467,13 +466,17 @@ call_def_function(
 	++ectx.ec_stack.ga_len;
     }
 
-    // Reserve space for local variables.
-    dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
-    for (idx = 0; idx < dfunc->df_varcount; ++idx)
-	STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
-    ectx.ec_stack.ga_len += dfunc->df_varcount;
+    {
+	// Reserve space for local variables.
+	dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
+							 + ufunc->uf_dfunc_idx;
 
-    ectx.ec_instr = dfunc->df_instr;
+	for (idx = 0; idx < dfunc->df_varcount; ++idx)
+	    STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
+	ectx.ec_stack.ga_len += dfunc->df_varcount;
+
+	ectx.ec_instr = dfunc->df_instr;
+    }
 
     // Decide where to start execution, handles optional arguments.
     init_instr_idx(ufunc, argc, &ectx);
@@ -1022,16 +1025,16 @@ call_def_function(
 			clear_tv(&partial);
 		    if (r == FAIL)
 			goto failed;
+		}
+		break;
 
-		    if (pfunc->cpf_top)
-		    {
-			// Get the funcref from the stack, overwrite with the
-			// return value.
-			clear_tv(tv);
-			--ectx.ec_stack.ga_len;
-			*STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
-		    }
-		}
+	    case ISN_PCALL_END:
+		// PCALL finished, arguments have been consumed and replaced by
+		// the return value.  Now clear the funcref from the stack,
+		// and move the return value in its place.
+		--ectx.ec_stack.ga_len;
+		clear_tv(STACK_TV_BOT(-1));
+		*STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
 		break;
 
 	    // call a user defined function or funcref/partial
@@ -1078,6 +1081,7 @@ call_def_function(
 	    case ISN_FUNCREF:
 		{
 		    partial_T   *pt = NULL;
+		    dfunc_T	*dfunc;
 
 		    pt = ALLOC_CLEAR_ONE(partial_T);
 		    if (pt == NULL)
@@ -2005,6 +2009,9 @@ ex_disassemble(exarg_T *eap)
 			   cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
 		}
 		break;
+	    case ISN_PCALL_END:
+		smsg("%4d PCALL end", current);
+		break;
 	    case ISN_RETURN:
 		smsg("%4d RETURN", current);
 		break;