summaryrefslogtreecommitdiffstats
path: root/src/vim9execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vim9execute.c')
-rw-r--r--src/vim9execute.c1507
1 files changed, 816 insertions, 691 deletions
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 60b58f98a3..6a11e8a6bc 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -34,6 +34,14 @@ typedef struct {
int tcd_return; // when TRUE return from end of :finally
} trycmd_T;
+// Data local to a function.
+// On a function call, if not empty, is saved on the stack and restored when
+// returning.
+typedef struct {
+ int floc_restore_cmdmod;
+ cmdmod_T floc_save_cmdmod;
+ int floc_restore_cmdmod_stacklen;
+} funclocal_T;
// A stack is used to store:
// - arguments passed to a :def function
@@ -60,8 +68,10 @@ typedef struct {
struct ectx_S {
garray_T ec_stack; // stack of typval_T values
int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx
+ int ec_initial_frame_idx; // frame index when called
outer_T *ec_outer; // outer scope used for closures, allocated
+ funclocal_T ec_funclocal;
garray_T ec_trystack; // stack of trycmd_T values
int ec_in_catch; // when TRUE in catch or finally block
@@ -71,6 +81,10 @@ struct ectx_S {
int ec_iidx; // index in ec_instr: instruction to execute
garray_T ec_funcrefs; // partials that might be a closure
+
+ int ec_did_emsg_before;
+ int ec_trylevel_at_start;
+ where_T ec_where;
};
#ifdef FEAT_PROFILE
@@ -125,15 +139,6 @@ exe_newlist(int count, ectx_T *ectx)
return OK;
}
-// Data local to a function.
-// On a function call, if not empty, is saved on the stack and restored when
-// returning.
-typedef struct {
- int floc_restore_cmdmod;
- cmdmod_T floc_save_cmdmod;
- int floc_restore_cmdmod_stacklen;
-} funclocal_T;
-
/*
* Call compiled function "cdf_idx" from compiled code.
* This adds a stack frame and sets the instruction pointer to the start of the
@@ -154,7 +159,6 @@ call_dfunc(
int cdf_idx,
partial_T *pt,
int argcount_arg,
- funclocal_T *funclocal,
ectx_T *ectx)
{
int argcount = argcount_arg;
@@ -254,13 +258,13 @@ call_dfunc(
return FAIL;
// Only make a copy of funclocal if it contains something to restore.
- if (funclocal->floc_restore_cmdmod)
+ if (ectx->ec_funclocal.floc_restore_cmdmod)
{
floc = ALLOC_ONE(funclocal_T);
if (floc == NULL)
return FAIL;
- *floc = *funclocal;
- funclocal->floc_restore_cmdmod = FALSE;
+ *floc = ectx->ec_funclocal;
+ ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
}
// Move the vararg-list to below the missing optional arguments.
@@ -527,7 +531,7 @@ funcstack_check_refcount(funcstack_T *funcstack)
* Return from the current function.
*/
static int
-func_return(funclocal_T *funclocal, ectx_T *ectx)
+func_return(ectx_T *ectx)
{
int idx;
int ret_idx;
@@ -598,10 +602,10 @@ func_return(funclocal_T *funclocal, ectx_T *ectx)
ectx->ec_instr = INSTRUCTIONS(prev_dfunc);
if (floc == NULL)
- funclocal->floc_restore_cmdmod = FALSE;
+ ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
else
{
- *funclocal = *floc;
+ ectx->ec_funclocal = *floc;
vim_free(floc);
}
@@ -698,7 +702,6 @@ call_ufunc(
ufunc_T *ufunc,
partial_T *pt,
int argcount,
- funclocal_T *funclocal,
ectx_T *ectx,
isn_T *iptr)
{
@@ -738,7 +741,7 @@ call_ufunc(
iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
iptr->isn_arg.dfunc.cdf_argcount = argcount;
}
- return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, funclocal, ectx);
+ return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, ectx);
}
if (call_prepare(argcount, argvars, ectx) == FAIL)
@@ -800,7 +803,6 @@ vim9_aborting(int prev_called_emsg)
call_by_name(
char_u *name,
int argcount,
- funclocal_T *funclocal,
ectx_T *ectx,
isn_T *iptr)
{
@@ -853,7 +855,7 @@ call_by_name(
}
}
- return call_ufunc(ufunc, NULL, argcount, funclocal, ectx, iptr);
+ return call_ufunc(ufunc, NULL, argcount, ectx, iptr);
}
return FAIL;
@@ -863,7 +865,6 @@ call_by_name(
call_partial(
typval_T *tv,
int argcount_arg,
- funclocal_T *funclocal,
ectx_T *ectx)
{
int argcount = argcount_arg;
@@ -893,7 +894,7 @@ call_partial(
}
if (pt->pt_func != NULL)
- return call_ufunc(pt->pt_func, pt, argcount, funclocal, ectx, NULL);
+ return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL);
name = pt->pt_name;
}
@@ -911,7 +912,7 @@ call_partial(
if (error != FCERR_NONE)
res = FAIL;
else
- res = call_by_name(fname, argcount, funclocal, ectx, NULL);
+ res = call_by_name(fname, argcount, ectx, NULL);
vim_free(tofree);
}
@@ -1184,14 +1185,13 @@ get_script_svar(scriptref_T *sref, ectx_T *ectx)
call_eval_func(
char_u *name,
int argcount,
- funclocal_T *funclocal,
ectx_T *ectx,
isn_T *iptr)
{
int called_emsg_before = called_emsg;
int res;
- res = call_by_name(name, argcount, funclocal, ectx, iptr);
+ res = call_by_name(name, argcount, ectx, iptr);
if (res == FAIL && called_emsg == called_emsg_before)
{
dictitem_T *v;
@@ -1207,7 +1207,7 @@ call_eval_func(
semsg(_(e_unknownfunc), name);
return FAIL;
}
- return call_partial(&v->di_tv, argcount, funclocal, ectx);
+ return call_partial(&v->di_tv, argcount, ectx);
}
return res;
}
@@ -1257,255 +1257,35 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
return OK;
}
-
-/*
- * Call a "def" function from old Vim script.
- * Return OK or FAIL.
- */
- int
-call_def_function(
- ufunc_T *ufunc,
- int argc_arg, // nr of arguments
- typval_T *argv, // arguments
- partial_T *partial, // optional partial for context
- typval_T *rettv) // return value
-{
- ectx_T ectx; // execution context
- int argc = argc_arg;
- int initial_frame_idx;
- typval_T *tv;
- int idx;
- int ret = FAIL;
- int defcount = ufunc->uf_args.ga_len - argc;
- sctx_T save_current_sctx = current_sctx;
- int breakcheck_count = 0;
- int did_emsg_before = did_emsg_cumul + did_emsg;
- int save_suppress_errthrow = suppress_errthrow;
- msglist_T **saved_msg_list = NULL;
- msglist_T *private_msg_list = NULL;
- funclocal_T funclocal;
- int save_emsg_silent_def = emsg_silent_def;
- int save_did_emsg_def = did_emsg_def;
- int trylevel_at_start = trylevel;
- int orig_funcdepth;
- where_T where;
+// used for substitute_instr
+typedef struct subs_expr_S {
+ ectx_T *subs_ectx;
+ isn_T *subs_instr;
+ int subs_status;
+} subs_expr_T;
// Get pointer to item in the stack.
-#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
+#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
// Get pointer to item at the bottom of the stack, -1 is the bottom.
#undef STACK_TV_BOT
-#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
+#define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx)
// Get pointer to a local variable on the stack. Negative for arguments.
-#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
-
- if (ufunc->uf_def_status == UF_NOT_COMPILED
- || ufunc->uf_def_status == UF_COMPILE_ERROR
- || (func_needs_compiling(ufunc, PROFILING(ufunc))
- && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL)
- == FAIL))
- {
- if (did_emsg_cumul + did_emsg == did_emsg_before)
- semsg(_(e_function_is_not_compiled_str),
- printable_func_name(ufunc));
- return FAIL;
- }
-
- {
- // Check the function was really compiled.
- dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
- + ufunc->uf_dfunc_idx;
- if (INSTRUCTIONS(dfunc) == NULL)
- {
- iemsg("using call_def_function() on not compiled function");
- return FAIL;
- }
- }
-
- // If depth of calling is getting too high, don't execute the function.
- orig_funcdepth = funcdepth_get();
- if (funcdepth_increment() == FAIL)
- return FAIL;
+#define STACK_TV_VAR(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx + STACK_FRAME_SIZE + idx)
- CLEAR_FIELD(funclocal);
- CLEAR_FIELD(ectx);
- ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
- ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
- if (ga_grow(&ectx.ec_stack, 20) == FAIL)
- {
- funcdepth_decrement();
- return FAIL;
- }
- ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
- ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
-
- idx = argc - ufunc->uf_args.ga_len;
- if (idx > 0 && ufunc->uf_va_name == NULL)
- {
- if (idx == 1)
- emsg(_(e_one_argument_too_many));
- else
- semsg(_(e_nr_arguments_too_many), idx);
- goto failed_early;
- }
-
- // Put arguments on the stack, but no more than what the function expects.
- // A lambda can be called with more arguments than it uses.
- for (idx = 0; idx < argc
- && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len);
- ++idx)
- {
- if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len
- && argv[idx].v_type == VAR_SPECIAL
- && argv[idx].vval.v_number == VVAL_NONE)
- {
- // Use the default value.
- STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
- }
- else
- {
- if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
- && check_typval_arg_type(
- ufunc->uf_arg_types[idx], &argv[idx], idx + 1) == FAIL)
- goto failed_early;
- copy_tv(&argv[idx], STACK_TV_BOT(0));
- }
- ++ectx.ec_stack.ga_len;
- }
-
- // Turn varargs into a list. Empty list if no args.
- if (ufunc->uf_va_name != NULL)
- {
- int vararg_count = argc - ufunc->uf_args.ga_len;
-
- if (vararg_count < 0)
- vararg_count = 0;
- else
- argc -= vararg_count;
- if (exe_newlist(vararg_count, &ectx) == FAIL)
- goto failed_early;
-
- // Check the type of the list items.
- tv = STACK_TV_BOT(-1);
- if (ufunc->uf_va_type != NULL
- && ufunc->uf_va_type != &t_list_any
- && ufunc->uf_va_type->tt_member != &t_any
- && tv->vval.v_list != NULL)
- {
- type_T *expected = ufunc->uf_va_type->tt_member;
- listitem_T *li = tv->vval.v_list->lv_first;
-
- for (idx = 0; idx < vararg_count; ++idx)
- {
- if (check_typval_arg_type(expected, &li->li_tv,
- argc + idx + 1) == FAIL)
- goto failed_early;
- li = li->li_next;
- }
- }
-
- if (defcount > 0)
- // Move varargs list to below missing default arguments.
- *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1);
- --ectx.ec_stack.ga_len;
- }
-
- // Make space for omitted arguments, will store default value below.
- // Any varargs list goes after them.
- if (defcount > 0)
- for (idx = 0; idx < defcount; ++idx)
- {
- STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
- ++ectx.ec_stack.ga_len;
- }
- if (ufunc->uf_va_name != NULL)
- ++ectx.ec_stack.ga_len;
-
- // Frame pointer points to just after arguments.
- ectx.ec_frame_idx = ectx.ec_stack.ga_len;
- initial_frame_idx = ectx.ec_frame_idx;
-
- {
- dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
- + ufunc->uf_dfunc_idx;
- ufunc_T *base_ufunc = dfunc->df_ufunc;
-
- // "uf_partial" is on the ufunc that "df_ufunc" points to, as is done
- // by copy_func().
- if (partial != NULL || base_ufunc->uf_partial != NULL)
- {
- ectx.ec_outer = ALLOC_CLEAR_ONE(outer_T);
- if (ectx.ec_outer == NULL)
- goto failed_early;
- if (partial != NULL)
- {
- if (partial->pt_outer.out_stack == NULL && current_ectx != NULL)
- {
- if (current_ectx->ec_outer != NULL)
- *ectx.ec_outer = *current_ectx->ec_outer;
- }
- else
- *ectx.ec_outer = partial->pt_outer;
- }
- else
- *ectx.ec_outer = base_ufunc->uf_partial->pt_outer;
- ectx.ec_outer->out_up_is_copy = TRUE;
- }
- }
-
- // dummy frame entries
- for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
- {
- STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
- ++ectx.ec_stack.ga_len;
- }
-
- {
- // Reserve space for local variables and any closure reference count.
- dfunc_T *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;
- if (dfunc->df_has_closure)
- {
- STACK_TV_VAR(idx)->v_type = VAR_NUMBER;
- STACK_TV_VAR(idx)->vval.v_number = 0;
- ++ectx.ec_stack.ga_len;
- }
-
- ectx.ec_instr = INSTRUCTIONS(dfunc);
- }
-
- // Following errors are in the function, not the caller.
- // Commands behave like vim9script.
- estack_push_ufunc(ufunc, 1);
- current_sctx = ufunc->uf_script_ctx;
- current_sctx.sc_version = SCRIPT_VERSION_VIM9;
-
- // Use a specific location for storing error messages to be converted to an
- // exception.
- saved_msg_list = msg_list;
- msg_list = &private_msg_list;
-
- // Do turn errors into exceptions.
- suppress_errthrow = FALSE;
-
- // Do not delete the function while executing it.
- ++ufunc->uf_calls;
-
- // When ":silent!" was used before calling then we still abort the
- // function. If ":silent!" is used in the function then we don't.
- emsg_silent_def = emsg_silent;
- did_emsg_def = 0;
-
- where.wt_index = 0;
- where.wt_variable = FALSE;
+/*
+ * Execute instructions in execution context "ectx".
+ * Return OK or FAIL;
+ */
+ static int
+exec_instructions(ectx_T *ectx)
+{
+ int breakcheck_count = 0;
+ typval_T *tv;
// Start execution at the first instruction.
- ectx.ec_iidx = 0;
+ ectx->ec_iidx = 0;
for (;;)
{
@@ -1521,7 +1301,7 @@ call_def_function(
// Turn CTRL-C into an exception.
got_int = FALSE;
if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
- goto failed;
+ return FAIL;
did_throw = TRUE;
}
@@ -1530,52 +1310,52 @@ call_def_function(
// Turn an error message into an exception.
did_emsg = FALSE;
if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL)
- goto failed;
+ return FAIL;
did_throw = TRUE;
*msg_list = NULL;
}
- if (did_throw && !ectx.ec_in_catch)
+ if (did_throw && !ectx->ec_in_catch)
{
- garray_T *trystack = &ectx.ec_trystack;
+ garray_T *trystack = &ectx->ec_trystack;
trycmd_T *trycmd = NULL;
// An exception jumps to the first catch, finally, or returns from
// the current function.
if (trystack->ga_len > 0)
trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1;
- if (trycmd != NULL && trycmd->tcd_frame_idx == ectx.ec_frame_idx)
+ if (trycmd != NULL && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
{
// jump to ":catch" or ":finally"
- ectx.ec_in_catch = TRUE;
- ectx.ec_iidx = trycmd->tcd_catch_idx;
+ ectx->ec_in_catch = TRUE;
+ ectx->ec_iidx = trycmd->tcd_catch_idx;
}
else
{
// Not inside try or need to return from current functions.
// Push a dummy return value.
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_NUMBER;
tv->vval.v_number = 0;
- ++ectx.ec_stack.ga_len;
- if (ectx.ec_frame_idx == initial_frame_idx)
+ ++ectx->ec_stack.ga_len;
+ if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
{
// At the toplevel we are done.
need_rethrow = TRUE;
- if (handle_closure_in_use(&ectx, FALSE) == FAIL)
- goto failed;
+ if (handle_closure_in_use(ectx, FALSE) == FAIL)
+ return FAIL;
goto done;
}
- if (func_return(&funclocal, &ectx) == FAIL)
- goto failed;
+ if (func_return(ectx) == FAIL)
+ return FAIL;
}
continue;
}
- iptr = &ectx.ec_instr[ectx.ec_iidx++];
+ iptr = &ectx->ec_instr[ectx->ec_iidx++];
switch (iptr->isn_type)
{
// execute Ex command line
@@ -1597,6 +1377,38 @@ call_def_function(
}
break;
+ // execute :substitute with an expression
+ case ISN_SUBSTITUTE:
+ {
+ subs_T *subs = &iptr->isn_arg.subs;
+ source_cookie_T cookie;
+ struct subs_expr_S *save_instr = substitute_instr;
+ struct subs_expr_S subs_instr;
+ int res;
+
+ subs_instr.subs_ectx = ectx;
+ subs_instr.subs_instr = subs->subs_instr;
+ subs_instr.subs_status = OK;
+ substitute_instr = &subs_instr;
+
+ SOURCING_LNUM = iptr->isn_lnum;
+ // This is very much like ISN_EXEC
+ CLEAR_FIELD(cookie);
+ cookie.sourcing_lnum = iptr->isn_lnum - 1;
+ res = do_cmdline(subs->subs_cmd,
+ getsourceline, &cookie,
+ DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
+ substitute_instr = save_instr;
+
+ if (res == FAIL || did_emsg
+ || subs_instr.subs_status == FAIL)
+ goto on_error;
+ }
+ break;
+
+ case ISN_FINISH:
+ goto done;
+
// execute Ex command from pieces on the stack
case ISN_EXECCONCAT:
{
@@ -1626,7 +1438,7 @@ call_def_function(
{
cmd = alloc(len + 1);
if (cmd == NULL)
- goto failed;
+ return FAIL;
len = 0;
}
}
@@ -1643,6 +1455,7 @@ call_def_function(
int count = iptr->isn_arg.echo.echo_count;
int atstart = TRUE;
int needclr = TRUE;
+ int idx;
for (idx = 0; idx < count; ++idx)
{
@@ -1653,7 +1466,7 @@ call_def_function(
}
if (needclr)
msg_clr_eos();
- ectx.ec_stack.ga_len -= count;
+ ectx->ec_stack.ga_len -= count;
}
break;
@@ -1670,6 +1483,7 @@ call_def_function(
char_u *p;
int len;
int failed = FALSE;
+ int idx;
ga_init2(&ga, 1, 80);
for (idx = 0; idx < count; ++idx)
@@ -1702,7 +1516,7 @@ call_def_function(
}
clear_tv(tv);
}
- ectx.ec_stack.ga_len -= count;
+ ectx->ec_stack.ga_len -= count;
if (failed)
{
ga_clear(&ga);
@@ -1742,18 +1556,18 @@ call_def_function(
// load local variable or argument
case ISN_LOAD:
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
break;
// load v: variable
case ISN_LOADV:
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
break;
// load s: variable in Vim9 script
@@ -1762,14 +1576,14 @@ call_def_function(
scriptref_T *sref = iptr->isn_arg.script.scriptref;
svar_T *sv;
- sv = get_script_svar(sref, &ectx);
+ sv = get_script_svar(sref, ectx);
if (sv == NULL)
- goto failed;
+ return FAIL;
allocate_if_null(sv->sv_tv);
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
copy_tv(sv->sv_tv, STACK_TV_BOT(0));
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
}
break;
@@ -1789,10 +1603,10 @@ call_def_function(
}
else
{
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
copy_tv(&di->di_tv, STACK_TV_BOT(0));
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
}
}
break;
@@ -1826,7 +1640,7 @@ call_def_function(
namespace = 't';
break;
default: // Cannot reach here
- goto failed;
+ return FAIL;
}
di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
@@ -1839,10 +1653,10 @@ call_def_function(
}
else
{
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
copy_tv(&di->di_tv, STACK_TV_BOT(0));
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
}
}
break;
@@ -1852,13 +1666,13 @@ call_def_function(
{
char_u *name = iptr->isn_arg.string;
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
SOURCING_LNUM = iptr->isn_lnum;
if (eval_variable(name, (int)STRLEN(name),
STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL)
goto on_error;
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
}
break;
@@ -1877,16 +1691,16 @@ call_def_function(
case ISN_LOADWDICT: d = curwin->w_vars; break;
case ISN_LOADTDICT: d = curtab->tp_vars; break;
default: // Cannot reach here
- goto failed;
+ return FAIL;
}
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_DICT;
tv->v_lock = 0;
tv->vval.v_dict = d;
++d->dv_refcount;
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
}
break;
@@ -1898,12 +1712,12 @@ call_def_function(
// This is not expected to fail, name is checked during
// compilation: don't set SOURCING_LNUM.
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
if (eval_option(&name, &optval, TRUE) == FAIL)
- goto failed;
+ return FAIL;
*STACK_TV_BOT(0) = optval;
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
}
break;
@@ -1913,19 +1727,19 @@ call_def_function(
typval_T optval;
char_u *name = iptr->isn_arg.string;
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
// name is always valid, checked when compiling
(void)eval_env_var(&name, &optval, TRUE);
*STACK_TV_BOT(0) = optval;
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
}
break;
// load @register
case ISN_LOADREG:
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_STRING;
tv->v_lock = 0;
@@ -1933,12 +1747,12 @@ call_def_function(
// empty string.
tv->vval.v_string = get_reg_contents(
iptr->isn_arg.number, GREG_EXPR_SRC);
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
break;
// store local variable
case ISN_STORE:
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
tv = STACK_TV_VAR(iptr->isn_arg.number);
clear_tv(tv);
*tv = *STACK_TV_BOT(0);
@@ -1952,7 +1766,7 @@ call_def_function(
char_u *name = iptr->isn_arg.loadstore.ls_name;
dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
if (di == NULL)
store_var(name, STACK_TV_BOT(0));
else
@@ -1975,10 +1789,10 @@ call_def_function(
scriptref_T *sref = iptr->isn_arg.script.scriptref;
svar_T *sv;
- sv = get_script_svar(sref, &ectx);
+ sv = get_script_svar(sref, ectx);
if (sv == NULL)
- goto failed;
- --ectx.ec_stack.ga_len;
+ return FAIL;
+ --ectx->ec_stack.ga_len;
// "const" and "final" are checked at compile time, locking
// the value needs to be checked here.
@@ -2001,7 +1815,7 @@ call_def_function(
char_u *s = NULL;
char *msg;
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
tv = STACK_TV_BOT(0);
if (tv->v_type == VAR_STRING)
{
@@ -2026,7 +1840,7 @@ call_def_function(
// store $ENV
case ISN_STOREENV:
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
tv = STACK_TV_BOT(0);
vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
clear_tv(tv);
@@ -2037,7 +1851,7 @@ call_def_function(
{
int reg = iptr->isn_arg.number;
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
tv = STACK_TV_BOT(0);
write_reg_contents(reg == '@' ? '"' : reg,
tv_get_string(tv), -1, FALSE);
@@ -2047,7 +1861,7 @@ call_def_function(
// store v: variable
case ISN_STOREV:
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
== FAIL)
// should not happen, type is checked when compiling
@@ -2079,10 +1893,10 @@ call_def_function(
ht = &curtab->tp_vars->dv_hashtab;
break;
default: // Cannot reach here
- goto failed;
+ return FAIL;
}
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
di = find_var_in_ht(ht, 0, name, TRUE);
if (di == NULL)
store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
@@ -2102,7 +1916,7 @@ call_def_function(
SOURCING_LNUM = iptr->isn_lnum;
set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE);
clear_tv(STACK_TV_BOT(-1));
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
break;
// store number in local variable
@@ -2184,7 +1998,7 @@ call_def_function(
goto on_error;
// append to list, only fails when out of memory
if (list_append_tv(list, tv) == FAIL)
- goto failed;
+ return FAIL;
clear_tv(tv);
}
}
@@ -2219,7 +2033,7 @@ call_def_function(
goto on_error;
// add to dict, only fails when out of memory
if (dict_add_tv(dict, (char *)key, tv) == FAIL)
- goto failed;
+ return FAIL;
clear_tv(tv);
}
}
@@ -2263,7 +2077,7 @@ call_def_function(
clear_tv(tv_idx);
clear_tv(tv_dest);
- ectx.ec_stack.ga_len -= 3;
+ ectx->ec_stack.ga_len -= 3;
if (status == FAIL)
{
clear_tv(tv);
@@ -2328,7 +2142,7 @@ call_def_function(
clear_tv(tv_idx1);
clear_tv(tv_idx2);
clear_tv(tv_dest);
- ectx.ec_stack.ga_len -= 4;
+ ectx->ec_stack.ga_len -= 4;
clear_tv(tv);
if (status == FAIL)
@@ -2341,7 +2155,7 @@ call_def_function(
case ISN_STOREOUTER:
{
int depth = iptr->isn_arg.outer.outer_depth;
- outer_T *outer = ectx.ec_outer;
+ outer_T *outer = ectx->ec_outer;
while (depth > 1 && outer != NULL)
{
@@ -2352,21 +2166,21 @@ call_def_function(
{
SOURCING_LNUM = iptr->isn_lnum;
iemsg("LOADOUTER depth more than scope levels");
- goto failed;
+ return FAIL;
}
tv = ((typval_T *)outer->out_stack->ga_data)
+ outer->out_frame_idx + STACK_FRAME_SIZE
+ iptr->isn_arg.outer.outer_idx;
if (iptr->isn_type == ISN_LOADOUTER)
{
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
copy_tv(tv, STACK_TV_BOT(0));
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
}
else
{
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
clear_tv(tv);
*tv = *STACK_TV_BOT(0);
}
@@ -2453,7 +2267,7 @@ call_def_function(
clear_tv(tv_idx);
clear_tv(tv_dest);
- ectx.ec_stack.ga_len -= 2;
+ ectx->ec_stack.ga_len -= 2;
if (status == FAIL)
goto on_error;
}
@@ -2505,7 +2319,7 @@ call_def_function(
clear_tv(tv_idx1);
clear_tv(tv_idx2);
clear_tv(tv_dest);
- ectx.ec_stack.ga_len -= 3;
+ ectx->ec_stack.ga_len -= 3;
if (status == FAIL)
goto on_error;
}
@@ -2521,11 +2335,11 @@ call_def_function(
case ISN_PUSHFUNC:
case ISN_PUSHCHANNEL:
case ISN_PUSHJOB:
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
tv = STACK_TV_BOT(0);
tv->v_lock = 0;
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
switch (iptr->isn_type)
{
case ISN_PUSHNR:
@@ -2597,8 +2411,8 @@ call_def_function(
// create a list from items on the stack; uses a single allocation
// for the list header and the items
case ISN_NEWLIST:
- if (exe_newlist(iptr->isn_arg.number, &ectx) == FAIL)
- goto failed;
+ if (exe_newlist(iptr->isn_arg.number, ectx) == FAIL)
+ return FAIL;
break;
// create a dict from items on the stack
@@ -2608,9 +2422,10 @@ call_def_function(
dict_T *dict = dict_alloc();
dictitem_T *item;
char_u *key;
+ int idx;
if (dict == NULL)
- goto failed;
+ return FAIL;
for (idx = 0; idx < count; ++idx)
{
// have already checked key type is VAR_STRING
@@ -2631,7 +2446,7 @@ call_def_function(
if (item == NULL)
{
dict_unref(dict);
- goto failed;
+ return FAIL;
}
item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
item->di_tv.v_lock = 0;
@@ -2639,16 +2454,16 @@ call_def_function(
{
// can this ever happen?
dict_unref(dict);
- goto failed;
+ return FAIL;
}
}
if (count > 0)
- ectx.ec_stack.ga_len -= 2 * count - 1;
- else if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ ectx->ec_stack.ga_len -= 2 * count - 1;
+ else if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
else
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
tv = STACK_TV_BOT(-1);
tv->v_type = VAR_DICT;
tv->v_lock = 0;
@@ -2663,8 +2478,7 @@ call_def_function(
if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
NULL,
iptr->isn_arg.dfunc.cdf_argcount,
- &funclocal,
- &ectx) == FAIL)
+ ectx) == FAIL)
goto on_error;
break;
@@ -2673,7 +2487,7 @@ call_def_function(
SOURCING_LNUM = iptr->isn_lnum;
if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
iptr->isn_arg.bfunc.cbf_argcount,
- &ectx) == FAIL)
+ ectx) == FAIL)
goto on_error;
break;
@@ -2693,12 +2507,11 @@ call_def_function(
else
{
// Get the funcref from the stack.
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
partial_tv = *STACK_TV_BOT(0);
tv = &partial_tv;
}
- r = call_partial(tv, pfunc->cpf_argcount,
- &funclocal, &ectx);
+ r = call_partial(tv, pfunc->cpf_argcount, ectx);
if (tv == &partial_tv)
clear_tv(&partial_tv);
if (r == FAIL)
@@ -2710,7 +2523,7 @@ call_def_function(
// 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;
+ --ectx->ec_stack.ga_len;
clear_tv(STACK_TV_BOT(-1));
*STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
break;
@@ -2722,17 +2535,17 @@ call_def_function(
SOURCING_LNUM = iptr->isn_lnum;
if (call_eval_func(cufunc->cuf_name, cufunc->cuf_argcount,
- &funclocal, &ectx, iptr) == FAIL)
+ ectx, iptr) == FAIL)
goto on_error;
}
break;
// return from a :def function call
case ISN_RETURN_ZERO:
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
- goto failed;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
tv = STACK_TV_BOT(0);
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
tv->v_type = VAR_NUMBER;
tv->vval.v_number = 0;
tv->v_lock = 0;
@@ -2740,20 +2553,20 @@ call_def_function(
case ISN_RETURN:
{
- garray_T *trystack = &ectx.ec_trystack;
+ garray_T *trystack = &ectx->ec_trystack;
trycmd_T *trycmd = NULL;
if (trystack->ga_len > 0)
trycmd = ((trycmd_T *)trystack->ga_data)
+ trystack->ga_len - 1;
if (trycmd != NULL
- && trycmd->tcd_frame_idx == ectx.ec_frame_idx)
+ && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
{
// jump to ":finally" or ":endtry"
if (trycmd->tcd_finally_idx != 0)
- ectx.ec_iidx = trycmd->tcd_finally_idx;
+ ectx->ec_iidx = trycmd->tcd_finally_idx;
else
- ectx.ec_iidx = trycmd->tcd_endtry_idx;
+ ectx->ec_iidx = trycmd->tcd_endtry_idx;
trycmd->tcd_return = TRUE;
}
else
@@ -2769,18 +2582,18 @@ call_def_function(
+ iptr->isn_arg.funcref.fr_func;
if (pt == NULL)
- goto failed;
- if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
+ return FAIL;
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
{
vim_free(pt);
- goto failed;
+ return FAIL;
}
if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc,
- &ectx) == FAIL)
- goto failed;
+ ectx) == FAIL)
+ return FAIL;
tv = STACK_TV_BOT(0);
- ++ectx.ec_stack.ga_len;
+ ++ectx->ec_stack.ga_len;
tv->vval.v_partial = pt;
tv->v_type = VAR_PARTIAL;
tv->v_lock = 0;
@@ -2793,8 +2606,8 @@ call_def_function(
newfunc_T *newfunc = &iptr->isn_arg.newfunc;
if (copy_func(newfunc->nf_lambda, newfunc->nf_global,
- &ectx) == FAIL)
- goto failed;
+ ectx) == FAIL)
+ return FAIL;
}
break;
@@ -2841,11 +2654,11 @@ call_def_function(
{
// drop the value from the stack
clear_tv(tv);
- --ectx.ec_stack.ga_len;
+ --ectx->ec_stack.ga_len;
}
}
if (jump)
- ectx.ec_iidx = iptr->isn_arg.jump.jump_where;