xref: /vim-8.2.3635/src/vim9execute.c (revision 21c1a0c2)
18a7d6542SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
28a7d6542SBram Moolenaar  *
38a7d6542SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
48a7d6542SBram Moolenaar  *
58a7d6542SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
68a7d6542SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
78a7d6542SBram Moolenaar  * See README.txt for an overview of the Vim source code.
88a7d6542SBram Moolenaar  */
98a7d6542SBram Moolenaar 
108a7d6542SBram Moolenaar /*
118a7d6542SBram Moolenaar  * vim9execute.c: execute Vim9 script instructions
128a7d6542SBram Moolenaar  */
138a7d6542SBram Moolenaar 
148a7d6542SBram Moolenaar #define USING_FLOAT_STUFF
158a7d6542SBram Moolenaar #include "vim.h"
168a7d6542SBram Moolenaar 
178a7d6542SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
188a7d6542SBram Moolenaar 
198a7d6542SBram Moolenaar #ifdef VMS
208a7d6542SBram Moolenaar # include <float.h>
218a7d6542SBram Moolenaar #endif
228a7d6542SBram Moolenaar 
238a7d6542SBram Moolenaar #include "vim9.h"
248a7d6542SBram Moolenaar 
258a7d6542SBram Moolenaar // Structure put on ec_trystack when ISN_TRY is encountered.
268a7d6542SBram Moolenaar typedef struct {
27d9d7789bSBram Moolenaar     int	    tcd_frame_idx;	// ec_frame_idx at ISN_TRY
28d9d7789bSBram Moolenaar     int	    tcd_stack_len;	// size of ectx.ec_stack at ISN_TRY
29d3d8feebSBram Moolenaar     int	    tcd_in_catch;	// in catch or finally block
30d3d8feebSBram Moolenaar     int	    tcd_did_throw;	// set did_throw in :endtry
317e82c5f3SBram Moolenaar     int	    tcd_catch_idx;	// instruction of the first :catch or :finally
327e82c5f3SBram Moolenaar     int	    tcd_finally_idx;	// instruction of the :finally block or zero
337e82c5f3SBram Moolenaar     int	    tcd_endtry_idx;	// instruction of the :endtry
348a7d6542SBram Moolenaar     int	    tcd_caught;		// catch block entered
352e34c34bSBram Moolenaar     int	    tcd_cont;		// :continue encountered, jump here (minus one)
368a7d6542SBram Moolenaar     int	    tcd_return;		// when TRUE return from end of :finally
378a7d6542SBram Moolenaar } trycmd_T;
388a7d6542SBram Moolenaar 
394c137214SBram Moolenaar // Data local to a function.
404c137214SBram Moolenaar // On a function call, if not empty, is saved on the stack and restored when
414c137214SBram Moolenaar // returning.
424c137214SBram Moolenaar typedef struct {
434c137214SBram Moolenaar     int		floc_restore_cmdmod;
444c137214SBram Moolenaar     cmdmod_T	floc_save_cmdmod;
454c137214SBram Moolenaar     int		floc_restore_cmdmod_stacklen;
464c137214SBram Moolenaar } funclocal_T;
478a7d6542SBram Moolenaar 
48c04f2a4cSBram Moolenaar // Structure to hold a reference to an outer_T, with information of whether it
49c04f2a4cSBram Moolenaar // was allocated.
50c04f2a4cSBram Moolenaar typedef struct {
51c04f2a4cSBram Moolenaar     outer_T	*or_outer;
52c04f2a4cSBram Moolenaar     partial_T	*or_partial;	// decrement "or_partial->pt_refcount" later
53c04f2a4cSBram Moolenaar     int		or_outer_allocated;  // free "or_outer" later
54c04f2a4cSBram Moolenaar } outer_ref_T;
55c04f2a4cSBram Moolenaar 
568a7d6542SBram Moolenaar // A stack is used to store:
578a7d6542SBram Moolenaar // - arguments passed to a :def function
588a7d6542SBram Moolenaar // - info about the calling function, to use when returning
598a7d6542SBram Moolenaar // - local variables
608a7d6542SBram Moolenaar // - temporary values
618a7d6542SBram Moolenaar //
628a7d6542SBram Moolenaar // In detail (FP == Frame Pointer):
638a7d6542SBram Moolenaar //	  arg1		first argument from caller (if present)
648a7d6542SBram Moolenaar //	  arg2		second argument from caller (if present)
658a7d6542SBram Moolenaar //	  extra_arg1	any missing optional argument default value
668a7d6542SBram Moolenaar // FP ->  cur_func	calling function
678a7d6542SBram Moolenaar //        current	previous instruction pointer
688a7d6542SBram Moolenaar //        frame_ptr	previous Frame Pointer
698a7d6542SBram Moolenaar //        var1		space for local variable
708a7d6542SBram Moolenaar //        var2		space for local variable
718a7d6542SBram Moolenaar //        ....		fixed space for max. number of local variables
728a7d6542SBram Moolenaar //        temp		temporary values
738a7d6542SBram Moolenaar //        ....		flexible space for temporary values (can grow big)
748a7d6542SBram Moolenaar 
758a7d6542SBram Moolenaar /*
768a7d6542SBram Moolenaar  * Execution context.
778a7d6542SBram Moolenaar  */
78cd45ed03SBram Moolenaar struct ectx_S {
798a7d6542SBram Moolenaar     garray_T	ec_stack;	// stack of typval_T values
80bf67ea1aSBram Moolenaar     int		ec_frame_idx;	// index in ec_stack: context of ec_dfunc_idx
814c137214SBram Moolenaar     int		ec_initial_frame_idx;	// frame index when called
828a7d6542SBram Moolenaar 
83c04f2a4cSBram Moolenaar     outer_ref_T	*ec_outer_ref;	// outer scope used for closures, allocated
844c137214SBram Moolenaar     funclocal_T ec_funclocal;
85c8cd2b34SBram Moolenaar 
868a7d6542SBram Moolenaar     garray_T	ec_trystack;	// stack of trycmd_T values
878a7d6542SBram Moolenaar 
888a7d6542SBram Moolenaar     isn_T	*ec_instr;	// array with instructions
893276f584SDominique Pelle     int		ec_dfunc_idx;	// current function index
908a7d6542SBram Moolenaar     int		ec_iidx;	// index in ec_instr: instruction to execute
91148ce7aeSBram Moolenaar 
92148ce7aeSBram Moolenaar     garray_T	ec_funcrefs;	// partials that might be a closure
934c137214SBram Moolenaar 
944c137214SBram Moolenaar     int		ec_did_emsg_before;
954c137214SBram Moolenaar     int		ec_trylevel_at_start;
964c137214SBram Moolenaar     where_T	ec_where;
97cd45ed03SBram Moolenaar };
988a7d6542SBram Moolenaar 
9912d26531SBram Moolenaar #ifdef FEAT_PROFILE
10012d26531SBram Moolenaar // stack of profinfo_T used when profiling.
10112d26531SBram Moolenaar static garray_T profile_info_ga = {0, 0, sizeof(profinfo_T), 20, NULL};
10212d26531SBram Moolenaar #endif
10312d26531SBram Moolenaar 
1048a7d6542SBram Moolenaar // Get pointer to item relative to the bottom of the stack, -1 is the last one.
10511107babSBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx))
1068a7d6542SBram Moolenaar 
107418f1df5SBram Moolenaar     void
to_string_error(vartype_T vartype)108418f1df5SBram Moolenaar to_string_error(vartype_T vartype)
109418f1df5SBram Moolenaar {
110451c2e35SBram Moolenaar     semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype));
111418f1df5SBram Moolenaar }
112418f1df5SBram Moolenaar 
1138a7d6542SBram Moolenaar /*
114170fcfcfSBram Moolenaar  * Return the number of arguments, including optional arguments and any vararg.
1158a7d6542SBram Moolenaar  */
1168a7d6542SBram Moolenaar     static int
ufunc_argcount(ufunc_T * ufunc)1178a7d6542SBram Moolenaar ufunc_argcount(ufunc_T *ufunc)
1188a7d6542SBram Moolenaar {
1198a7d6542SBram Moolenaar     return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0);
1208a7d6542SBram Moolenaar }
1218a7d6542SBram Moolenaar 
1228a7d6542SBram Moolenaar /*
123fe270817SBram Moolenaar  * Create a new list from "count" items at the bottom of the stack.
124fe270817SBram Moolenaar  * When "count" is zero an empty list is added to the stack.
125fe270817SBram Moolenaar  */
126fe270817SBram Moolenaar     static int
exe_newlist(int count,ectx_T * ectx)127fe270817SBram Moolenaar exe_newlist(int count, ectx_T *ectx)
128fe270817SBram Moolenaar {
129fe270817SBram Moolenaar     list_T	*list = list_alloc_with_items(count);
130fe270817SBram Moolenaar     int		idx;
131fe270817SBram Moolenaar     typval_T	*tv;
132fe270817SBram Moolenaar 
133fe270817SBram Moolenaar     if (list == NULL)
134fe270817SBram Moolenaar 	return FAIL;
135fe270817SBram Moolenaar     for (idx = 0; idx < count; ++idx)
136fe270817SBram Moolenaar 	list_set_item(list, idx, STACK_TV_BOT(idx - count));
137fe270817SBram Moolenaar 
138fe270817SBram Moolenaar     if (count > 0)
139fe270817SBram Moolenaar 	ectx->ec_stack.ga_len -= count - 1;
14035578168SBram Moolenaar     else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
141fe270817SBram Moolenaar 	return FAIL;
142fe270817SBram Moolenaar     else
143fe270817SBram Moolenaar 	++ectx->ec_stack.ga_len;
144fe270817SBram Moolenaar     tv = STACK_TV_BOT(-1);
145fe270817SBram Moolenaar     tv->v_type = VAR_LIST;
146fe270817SBram Moolenaar     tv->vval.v_list = list;
147fe270817SBram Moolenaar     ++list->lv_refcount;
148fe270817SBram Moolenaar     return OK;
149fe270817SBram Moolenaar }
150fe270817SBram Moolenaar 
151fe270817SBram Moolenaar /*
1524f8f5428SBram Moolenaar  * If debug_tick changed check if "ufunc" has a breakpoint and update
1534f8f5428SBram Moolenaar  * "uf_has_breakpoint".
1544f8f5428SBram Moolenaar  */
1554f8f5428SBram Moolenaar     static void
update_has_breakpoint(ufunc_T * ufunc)1564f8f5428SBram Moolenaar update_has_breakpoint(ufunc_T *ufunc)
1574f8f5428SBram Moolenaar {
1584f8f5428SBram Moolenaar     if (ufunc->uf_debug_tick != debug_tick)
1594f8f5428SBram Moolenaar     {
1604f8f5428SBram Moolenaar 	linenr_T breakpoint;
1614f8f5428SBram Moolenaar 
1624f8f5428SBram Moolenaar 	ufunc->uf_debug_tick = debug_tick;
1634f8f5428SBram Moolenaar 	breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name, 0);
1644f8f5428SBram Moolenaar 	ufunc->uf_has_breakpoint = breakpoint > 0;
1654f8f5428SBram Moolenaar     }
1664f8f5428SBram Moolenaar }
1674f8f5428SBram Moolenaar 
168b1b6f4deSBram Moolenaar static garray_T dict_stack = GA_EMPTY;
169b1b6f4deSBram Moolenaar 
170b1b6f4deSBram Moolenaar /*
171b1b6f4deSBram Moolenaar  * Put a value on the dict stack.  This consumes "tv".
172b1b6f4deSBram Moolenaar  */
173b1b6f4deSBram Moolenaar     static int
dict_stack_save(typval_T * tv)174b1b6f4deSBram Moolenaar dict_stack_save(typval_T *tv)
175b1b6f4deSBram Moolenaar {
176b1b6f4deSBram Moolenaar     if (dict_stack.ga_growsize == 0)
177b1b6f4deSBram Moolenaar 	ga_init2(&dict_stack, (int)sizeof(typval_T), 10);
178b1b6f4deSBram Moolenaar     if (ga_grow(&dict_stack, 1) == FAIL)
179b1b6f4deSBram Moolenaar 	return FAIL;
180b1b6f4deSBram Moolenaar     ((typval_T *)dict_stack.ga_data)[dict_stack.ga_len] = *tv;
181b1b6f4deSBram Moolenaar     ++dict_stack.ga_len;
182b1b6f4deSBram Moolenaar     return OK;
183b1b6f4deSBram Moolenaar }
184b1b6f4deSBram Moolenaar 
185b1b6f4deSBram Moolenaar /*
186b1b6f4deSBram Moolenaar  * Get the typval at top of the dict stack.
187b1b6f4deSBram Moolenaar  */
188b1b6f4deSBram Moolenaar     static typval_T *
dict_stack_get_tv(void)189b1b6f4deSBram Moolenaar dict_stack_get_tv(void)
190b1b6f4deSBram Moolenaar {
191b1b6f4deSBram Moolenaar     if (dict_stack.ga_len == 0)
192b1b6f4deSBram Moolenaar 	return NULL;
193b1b6f4deSBram Moolenaar     return ((typval_T *)dict_stack.ga_data) + dict_stack.ga_len - 1;
194b1b6f4deSBram Moolenaar }
195b1b6f4deSBram Moolenaar 
196b1b6f4deSBram Moolenaar /*
197b1b6f4deSBram Moolenaar  * Get the dict at top of the dict stack.
198b1b6f4deSBram Moolenaar  */
199b1b6f4deSBram Moolenaar     static dict_T *
dict_stack_get_dict(void)200b1b6f4deSBram Moolenaar dict_stack_get_dict(void)
201b1b6f4deSBram Moolenaar {
202b1b6f4deSBram Moolenaar     typval_T *tv;
203b1b6f4deSBram Moolenaar 
204b1b6f4deSBram Moolenaar     if (dict_stack.ga_len == 0)
205b1b6f4deSBram Moolenaar 	return NULL;
206b1b6f4deSBram Moolenaar     tv = ((typval_T *)dict_stack.ga_data) + dict_stack.ga_len - 1;
207b1b6f4deSBram Moolenaar     if (tv->v_type == VAR_DICT)
208b1b6f4deSBram Moolenaar 	return tv->vval.v_dict;
209b1b6f4deSBram Moolenaar     return NULL;
210b1b6f4deSBram Moolenaar }
211b1b6f4deSBram Moolenaar 
212b1b6f4deSBram Moolenaar /*
213b1b6f4deSBram Moolenaar  * Drop an item from the dict stack.
214b1b6f4deSBram Moolenaar  */
215b1b6f4deSBram Moolenaar     static void
dict_stack_drop(void)216b1b6f4deSBram Moolenaar dict_stack_drop(void)
217b1b6f4deSBram Moolenaar {
218b1b6f4deSBram Moolenaar     if (dict_stack.ga_len == 0)
219b1b6f4deSBram Moolenaar     {
220b1b6f4deSBram Moolenaar 	iemsg("Dict stack underflow");
221b1b6f4deSBram Moolenaar 	return;
222b1b6f4deSBram Moolenaar     }
223b1b6f4deSBram Moolenaar     --dict_stack.ga_len;
224b1b6f4deSBram Moolenaar     clear_tv(((typval_T *)dict_stack.ga_data) + dict_stack.ga_len);
225b1b6f4deSBram Moolenaar }
226b1b6f4deSBram Moolenaar 
227b1b6f4deSBram Moolenaar /*
228b1b6f4deSBram Moolenaar  * Drop items from the dict stack until the length is equal to "len".
229b1b6f4deSBram Moolenaar  */
230b1b6f4deSBram Moolenaar     static void
dict_stack_clear(int len)231b1b6f4deSBram Moolenaar dict_stack_clear(int len)
232b1b6f4deSBram Moolenaar {
233b1b6f4deSBram Moolenaar     while (dict_stack.ga_len > len)
234b1b6f4deSBram Moolenaar 	dict_stack_drop();
235b1b6f4deSBram Moolenaar }
236b1b6f4deSBram Moolenaar 
2374f8f5428SBram Moolenaar /*
2388a7d6542SBram Moolenaar  * Call compiled function "cdf_idx" from compiled code.
239ab360526SBram Moolenaar  * This adds a stack frame and sets the instruction pointer to the start of the
240ab360526SBram Moolenaar  * called function.
241c04f2a4cSBram Moolenaar  * If "pt" is not null use "pt->pt_outer" for ec_outer_ref->or_outer.
2428a7d6542SBram Moolenaar  *
2438a7d6542SBram Moolenaar  * Stack has:
2448a7d6542SBram Moolenaar  * - current arguments (already there)
2458a7d6542SBram Moolenaar  * - omitted optional argument (default values) added here
2468a7d6542SBram Moolenaar  * - stack frame:
2478a7d6542SBram Moolenaar  *	- pointer to calling function
2488a7d6542SBram Moolenaar  *	- Index of next instruction in calling function
2498a7d6542SBram Moolenaar  *	- previous frame pointer
2508a7d6542SBram Moolenaar  * - reserved space for local variables
2518a7d6542SBram Moolenaar  */
2528a7d6542SBram Moolenaar     static int
call_dfunc(int cdf_idx,partial_T * pt,int argcount_arg,ectx_T * ectx)2532fecb531SBram Moolenaar call_dfunc(
2542fecb531SBram Moolenaar 	int		cdf_idx,
2552fecb531SBram Moolenaar 	partial_T	*pt,
2562fecb531SBram Moolenaar 	int		argcount_arg,
2572fecb531SBram Moolenaar 	ectx_T		*ectx)
2588a7d6542SBram Moolenaar {
2591378fbc4SBram Moolenaar     int		argcount = argcount_arg;
2608a7d6542SBram Moolenaar     dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
2618a7d6542SBram Moolenaar     ufunc_T	*ufunc = dfunc->df_ufunc;
262b69c6fb7SBram Moolenaar     int		did_emsg_before = did_emsg_cumul + did_emsg;
2631378fbc4SBram Moolenaar     int		arg_to_add;
2641378fbc4SBram Moolenaar     int		vararg_count = 0;
265148ce7aeSBram Moolenaar     int		varcount;
2668a7d6542SBram Moolenaar     int		idx;
267c620c055SBram Moolenaar     estack_T	*entry;
2682fecb531SBram Moolenaar     funclocal_T	*floc = NULL;
269648594eaSBram Moolenaar     int		res = OK;
2708a7d6542SBram Moolenaar 
2718a7d6542SBram Moolenaar     if (dfunc->df_deleted)
2728a7d6542SBram Moolenaar     {
273cd45ed03SBram Moolenaar 	// don't use ufunc->uf_name, it may have been freed
274cd45ed03SBram Moolenaar 	emsg_funcname(e_func_deleted,
275cd45ed03SBram Moolenaar 		dfunc->df_name == NULL ? (char_u *)"unknown" : dfunc->df_name);
2768a7d6542SBram Moolenaar 	return FAIL;
2778a7d6542SBram Moolenaar     }
2788a7d6542SBram Moolenaar 
279e5ea346aSBram Moolenaar #ifdef FEAT_PROFILE
28012d26531SBram Moolenaar     if (do_profiling == PROF_YES)
28112d26531SBram Moolenaar     {
28235578168SBram Moolenaar 	if (GA_GROW_OK(&profile_info_ga, 1))
28312d26531SBram Moolenaar 	{
28412d26531SBram Moolenaar 	    profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data)
28512d26531SBram Moolenaar 						      + profile_info_ga.ga_len;
28612d26531SBram Moolenaar 	    ++profile_info_ga.ga_len;
28712d26531SBram Moolenaar 	    CLEAR_POINTER(info);
28812d26531SBram Moolenaar 	    profile_may_start_func(info, ufunc,
28912d26531SBram Moolenaar 			(((dfunc_T *)def_functions.ga_data)
29012d26531SBram Moolenaar 					      + ectx->ec_dfunc_idx)->df_ufunc);
29112d26531SBram Moolenaar 	}
29212d26531SBram Moolenaar     }
293e5ea346aSBram Moolenaar #endif
294e5ea346aSBram Moolenaar 
2952ac4b253SBram Moolenaar     // Update uf_has_breakpoint if needed.
2962ac4b253SBram Moolenaar     update_has_breakpoint(ufunc);
2972ac4b253SBram Moolenaar 
298b69c6fb7SBram Moolenaar     // When debugging and using "cont" switches to the not-debugged
299b69c6fb7SBram Moolenaar     // instructions, may need to still compile them.
300648594eaSBram Moolenaar     if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc)))
301648594eaSBram Moolenaar     {
302648594eaSBram Moolenaar 	res = compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL);
303648594eaSBram Moolenaar 
304648594eaSBram Moolenaar 	// compile_def_function() may cause def_functions.ga_data to change
305648594eaSBram Moolenaar 	dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
306648594eaSBram Moolenaar     }
307648594eaSBram Moolenaar     if (res == FAIL || INSTRUCTIONS(dfunc) == NULL)
308b69c6fb7SBram Moolenaar     {
309b69c6fb7SBram Moolenaar 	if (did_emsg_cumul + did_emsg == did_emsg_before)
310b69c6fb7SBram Moolenaar 	    semsg(_(e_function_is_not_compiled_str),
311b69c6fb7SBram Moolenaar 						   printable_func_name(ufunc));
312b69c6fb7SBram Moolenaar 	return FAIL;
313b69c6fb7SBram Moolenaar     }
314b69c6fb7SBram Moolenaar 
3151378fbc4SBram Moolenaar     if (ufunc->uf_va_name != NULL)
3161378fbc4SBram Moolenaar     {
317fe270817SBram Moolenaar 	// Need to make a list out of the vararg arguments.
3181378fbc4SBram Moolenaar 	// Stack at time of call with 2 varargs:
3191378fbc4SBram Moolenaar 	//   normal_arg
3201378fbc4SBram Moolenaar 	//   optional_arg
3211378fbc4SBram Moolenaar 	//   vararg_1
3221378fbc4SBram Moolenaar 	//   vararg_2
323fe270817SBram Moolenaar 	// After creating the list:
3241378fbc4SBram Moolenaar 	//   normal_arg
3251378fbc4SBram Moolenaar 	//   optional_arg
326fe270817SBram Moolenaar 	//   vararg-list
327fe270817SBram Moolenaar 	// With missing optional arguments we get:
328fe270817SBram Moolenaar 	//    normal_arg
329fe270817SBram Moolenaar 	// After creating the list
330fe270817SBram Moolenaar 	//    normal_arg
331fe270817SBram Moolenaar 	//    (space for optional_arg)
332fe270817SBram Moolenaar 	//    vararg-list
3331378fbc4SBram Moolenaar 	vararg_count = argcount - ufunc->uf_args.ga_len;
3341378fbc4SBram Moolenaar 	if (vararg_count < 0)
3351378fbc4SBram Moolenaar 	    vararg_count = 0;
3361378fbc4SBram Moolenaar 	else
3371378fbc4SBram Moolenaar 	    argcount -= vararg_count;
338fe270817SBram Moolenaar 	if (exe_newlist(vararg_count, ectx) == FAIL)
3391378fbc4SBram Moolenaar 	    return FAIL;
340fe270817SBram Moolenaar 
341fe270817SBram Moolenaar 	vararg_count = 1;
3421378fbc4SBram Moolenaar     }
3431378fbc4SBram Moolenaar 
344fe270817SBram Moolenaar     arg_to_add = ufunc->uf_args.ga_len - argcount;
3451378fbc4SBram Moolenaar     if (arg_to_add < 0)
3461378fbc4SBram Moolenaar     {
34779e8db9aSBram Moolenaar 	if (arg_to_add == -1)
348451c2e35SBram Moolenaar 	    emsg(_(e_one_argument_too_many));
34979e8db9aSBram Moolenaar 	else
350451c2e35SBram Moolenaar 	    semsg(_(e_nr_arguments_too_many), -arg_to_add);
3511378fbc4SBram Moolenaar 	return FAIL;
3521378fbc4SBram Moolenaar     }
353148ce7aeSBram Moolenaar 
354148ce7aeSBram Moolenaar     // Reserve space for:
355148ce7aeSBram Moolenaar     // - missing arguments
356148ce7aeSBram Moolenaar     // - stack frame
357148ce7aeSBram Moolenaar     // - local variables
358148ce7aeSBram Moolenaar     // - if needed: a counter for number of closures created in
359148ce7aeSBram Moolenaar     //   ectx->ec_funcrefs.
360148ce7aeSBram Moolenaar     varcount = dfunc->df_varcount + dfunc->df_has_closure;
36135578168SBram Moolenaar     if (GA_GROW_FAILS(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE + varcount))
3628a7d6542SBram Moolenaar 	return FAIL;
3638a7d6542SBram Moolenaar 
3640ba48e8cSBram Moolenaar     // If depth of calling is getting too high, don't execute the function.
3650ba48e8cSBram Moolenaar     if (funcdepth_increment() == FAIL)
3660ba48e8cSBram Moolenaar 	return FAIL;
367e99d422bSBram Moolenaar     ++ex_nesting_level;
3680ba48e8cSBram Moolenaar 
3692fecb531SBram Moolenaar     // Only make a copy of funclocal if it contains something to restore.
3704c137214SBram Moolenaar     if (ectx->ec_funclocal.floc_restore_cmdmod)
3712fecb531SBram Moolenaar     {
3722fecb531SBram Moolenaar 	floc = ALLOC_ONE(funclocal_T);
3732fecb531SBram Moolenaar 	if (floc == NULL)
3742fecb531SBram Moolenaar 	    return FAIL;
3754c137214SBram Moolenaar 	*floc = ectx->ec_funclocal;
3764c137214SBram Moolenaar 	ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
3772fecb531SBram Moolenaar     }
3782fecb531SBram Moolenaar 
379fe270817SBram Moolenaar     // Move the vararg-list to below the missing optional arguments.
380fe270817SBram Moolenaar     if (vararg_count > 0 && arg_to_add > 0)
381fe270817SBram Moolenaar 	*STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
382170fcfcfSBram Moolenaar 
383170fcfcfSBram Moolenaar     // Reserve space for omitted optional arguments, filled in soon.
3841378fbc4SBram Moolenaar     for (idx = 0; idx < arg_to_add; ++idx)
385fe270817SBram Moolenaar 	STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN;
3861378fbc4SBram Moolenaar     ectx->ec_stack.ga_len += arg_to_add;
3878a7d6542SBram Moolenaar 
3888a7d6542SBram Moolenaar     // Store current execution state in stack frame for ISN_RETURN.
3890186e586SBram Moolenaar     STACK_TV_BOT(STACK_FRAME_FUNC_OFF)->vval.v_number = ectx->ec_dfunc_idx;
3900186e586SBram Moolenaar     STACK_TV_BOT(STACK_FRAME_IIDX_OFF)->vval.v_number = ectx->ec_iidx;
3915930ddcdSBram Moolenaar     STACK_TV_BOT(STACK_FRAME_INSTR_OFF)->vval.v_string = (void *)ectx->ec_instr;
392c04f2a4cSBram Moolenaar     STACK_TV_BOT(STACK_FRAME_OUTER_OFF)->vval.v_string =
393c04f2a4cSBram Moolenaar 						    (void *)ectx->ec_outer_ref;
3942fecb531SBram Moolenaar     STACK_TV_BOT(STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string = (void *)floc;
3950186e586SBram Moolenaar     STACK_TV_BOT(STACK_FRAME_IDX_OFF)->vval.v_number = ectx->ec_frame_idx;
396bf67ea1aSBram Moolenaar     ectx->ec_frame_idx = ectx->ec_stack.ga_len;
3978a7d6542SBram Moolenaar 
3988a7d6542SBram Moolenaar     // Initialize local variables
399148ce7aeSBram Moolenaar     for (idx = 0; idx < dfunc->df_varcount; ++idx)
4008a7d6542SBram Moolenaar 	STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN;
401148ce7aeSBram Moolenaar     if (dfunc->df_has_closure)
402148ce7aeSBram Moolenaar     {
403148ce7aeSBram Moolenaar 	typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + dfunc->df_varcount);
404148ce7aeSBram Moolenaar 
405148ce7aeSBram Moolenaar 	tv->v_type = VAR_NUMBER;
406148ce7aeSBram Moolenaar 	tv->vval.v_number = 0;
407148ce7aeSBram Moolenaar     }
408148ce7aeSBram Moolenaar     ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount;
4098a7d6542SBram Moolenaar 
4100d3de8cbSBram Moolenaar     if (pt != NULL || ufunc->uf_partial != NULL
4110d3de8cbSBram Moolenaar 					     || (ufunc->uf_flags & FC_CLOSURE))
412cd45ed03SBram Moolenaar     {
413c04f2a4cSBram Moolenaar 	outer_ref_T *ref = ALLOC_CLEAR_ONE(outer_ref_T);
4140186e586SBram Moolenaar 
415c04f2a4cSBram Moolenaar 	if (ref == NULL)
4160186e586SBram Moolenaar 	    return FAIL;
4170186e586SBram Moolenaar 	if (pt != NULL)
418ab360526SBram Moolenaar 	{
419c04f2a4cSBram Moolenaar 	    ref->or_outer = &pt->pt_outer;
420c04f2a4cSBram Moolenaar 	    ++pt->pt_refcount;
421c04f2a4cSBram Moolenaar 	    ref->or_partial = pt;
422cd45ed03SBram Moolenaar 	}
4230186e586SBram Moolenaar 	else if (ufunc->uf_partial != NULL)
4240186e586SBram Moolenaar 	{
425c04f2a4cSBram Moolenaar 	    ref->or_outer = &ufunc->uf_partial->pt_outer;
426c04f2a4cSBram Moolenaar 	    ++ufunc->uf_partial->pt_refcount;
427c04f2a4cSBram Moolenaar 	    ref->or_partial = ufunc->uf_partial;
4280186e586SBram Moolenaar 	}
4290186e586SBram Moolenaar 	else
4300186e586SBram Moolenaar 	{
431c04f2a4cSBram Moolenaar 	    ref->or_outer = ALLOC_CLEAR_ONE(outer_T);
4325a9e5845SDominique Pelle 	    if (unlikely(ref->or_outer == NULL))
433c04f2a4cSBram Moolenaar 	    {
434c04f2a4cSBram Moolenaar 		vim_free(ref);
435c04f2a4cSBram Moolenaar 		return FAIL;
4360186e586SBram Moolenaar 	    }
437c04f2a4cSBram Moolenaar 	    ref->or_outer_allocated = TRUE;
438c04f2a4cSBram Moolenaar 	    ref->or_outer->out_stack = &ectx->ec_stack;
439c04f2a4cSBram Moolenaar 	    ref->or_outer->out_frame_idx = ectx->ec_frame_idx;
440c04f2a4cSBram Moolenaar 	    if (ectx->ec_outer_ref != NULL)
441c04f2a4cSBram Moolenaar 		ref->or_outer->out_up = ectx->ec_outer_ref->or_outer;
442c04f2a4cSBram Moolenaar 	}
443c04f2a4cSBram Moolenaar 	ectx->ec_outer_ref = ref;
4440186e586SBram Moolenaar     }
4450186e586SBram Moolenaar     else
446c04f2a4cSBram Moolenaar 	ectx->ec_outer_ref = NULL;
447cd45ed03SBram Moolenaar 
448c970e422SBram Moolenaar     ++ufunc->uf_calls;
449c970e422SBram Moolenaar 
4508a7d6542SBram Moolenaar     // Set execution state to the start of the called function.
4518a7d6542SBram Moolenaar     ectx->ec_dfunc_idx = cdf_idx;
452e5ea346aSBram Moolenaar     ectx->ec_instr = INSTRUCTIONS(dfunc);
453b2049903SBram Moolenaar     entry = estack_push_ufunc(ufunc, 1);
454c620c055SBram Moolenaar     if (entry != NULL)
455c620c055SBram Moolenaar     {
456c620c055SBram Moolenaar 	// Set the script context to the script where the function was defined.
457c70fe460SBram Moolenaar 	// Save the current context so it can be restored on return.
458c70fe460SBram Moolenaar 	entry->es_save_sctx = current_sctx;
459c70fe460SBram Moolenaar 	current_sctx = ufunc->uf_script_ctx;
460c620c055SBram Moolenaar     }
461170fcfcfSBram Moolenaar 
46238a3bfa9SBram Moolenaar     // Start execution at the first instruction.
46338a3bfa9SBram Moolenaar     ectx->ec_iidx = 0;
4648a7d6542SBram Moolenaar 
4658a7d6542SBram Moolenaar     return OK;
4668a7d6542SBram Moolenaar }
4678a7d6542SBram Moolenaar 
4688a7d6542SBram Moolenaar // Get pointer to item in the stack.
4698a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
4708a7d6542SBram Moolenaar 
4718a7d6542SBram Moolenaar /*
472bf67ea1aSBram Moolenaar  * Used when returning from a function: Check if any closure is still
473bf67ea1aSBram Moolenaar  * referenced.  If so then move the arguments and variables to a separate piece
474bf67ea1aSBram Moolenaar  * of stack to be used when the closure is called.
475bf67ea1aSBram Moolenaar  * When "free_arguments" is TRUE the arguments are to be freed.
476bf67ea1aSBram Moolenaar  * Returns FAIL when out of memory.
477bf67ea1aSBram Moolenaar  */
478bf67ea1aSBram Moolenaar     static int
handle_closure_in_use(ectx_T * ectx,int free_arguments)479bf67ea1aSBram Moolenaar handle_closure_in_use(ectx_T *ectx, int free_arguments)
480bf67ea1aSBram Moolenaar {
481bf67ea1aSBram Moolenaar     dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
482bf67ea1aSBram Moolenaar 							  + ectx->ec_dfunc_idx;
483fdeab65dSBram Moolenaar     int		argcount;
484fdeab65dSBram Moolenaar     int		top;
485bf67ea1aSBram Moolenaar     int		idx;
486bf67ea1aSBram Moolenaar     typval_T	*tv;
487bf67ea1aSBram Moolenaar     int		closure_in_use = FALSE;
488148ce7aeSBram Moolenaar     garray_T	*gap = &ectx->ec_funcrefs;
489148ce7aeSBram Moolenaar     varnumber_T	closure_count;
490bf67ea1aSBram Moolenaar 
491fdeab65dSBram Moolenaar     if (dfunc->df_ufunc == NULL)
492148ce7aeSBram Moolenaar 	return OK;  // function was freed
493148ce7aeSBram Moolenaar     if (dfunc->df_has_closure == 0)
494148ce7aeSBram Moolenaar 	return OK;  // no closures
495148ce7aeSBram Moolenaar     tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + dfunc->df_varcount);
496148ce7aeSBram Moolenaar     closure_count = tv->vval.v_number;
497148ce7aeSBram Moolenaar     if (closure_count == 0)
498148ce7aeSBram Moolenaar 	return OK;  // no funcrefs created
499148ce7aeSBram Moolenaar 
500fdeab65dSBram Moolenaar     argcount = ufunc_argcount(dfunc->df_ufunc);
501fdeab65dSBram Moolenaar     top = ectx->ec_frame_idx - argcount;
502fdeab65dSBram Moolenaar 
503bf67ea1aSBram Moolenaar     // Check if any created closure is still in use.
504148ce7aeSBram Moolenaar     for (idx = 0; idx < closure_count; ++idx)
505bf67ea1aSBram Moolenaar     {
506c70bdab0SBram Moolenaar 	partial_T   *pt;
507c70bdab0SBram Moolenaar 	int	    off = gap->ga_len - closure_count + idx;
508148ce7aeSBram Moolenaar 
509c70bdab0SBram Moolenaar 	if (off < 0)
510c70bdab0SBram Moolenaar 	    continue;  // count is off or already done
511c70bdab0SBram Moolenaar 	pt = ((partial_T **)gap->ga_data)[off];
512148ce7aeSBram Moolenaar 	if (pt->pt_refcount > 1)
513221fcc74SBram Moolenaar 	{
514148ce7aeSBram Moolenaar 	    int refcount = pt->pt_refcount;
515221fcc74SBram Moolenaar 	    int i;
516221fcc74SBram Moolenaar 
517f821ddaaSBram Moolenaar 	    // A Reference in a local variables doesn't count, it gets
518221fcc74SBram Moolenaar 	    // unreferenced on return.
519221fcc74SBram Moolenaar 	    for (i = 0; i < dfunc->df_varcount; ++i)
520221fcc74SBram Moolenaar 	    {
521221fcc74SBram Moolenaar 		typval_T *stv = STACK_TV(ectx->ec_frame_idx
522221fcc74SBram Moolenaar 						       + STACK_FRAME_SIZE + i);
523148ce7aeSBram Moolenaar 		if (stv->v_type == VAR_PARTIAL && pt == stv->vval.v_partial)
524221fcc74SBram Moolenaar 		    --refcount;
525221fcc74SBram Moolenaar 	    }
526221fcc74SBram Moolenaar 	    if (refcount > 1)
527f7779c63SBram Moolenaar 	    {
528bf67ea1aSBram Moolenaar 		closure_in_use = TRUE;
529f7779c63SBram Moolenaar 		break;
530f7779c63SBram Moolenaar 	    }
531bf67ea1aSBram Moolenaar 	}
532221fcc74SBram Moolenaar     }
533bf67ea1aSBram Moolenaar 
534bf67ea1aSBram Moolenaar     if (closure_in_use)
535bf67ea1aSBram Moolenaar     {
536bf67ea1aSBram Moolenaar 	funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T);
537bf67ea1aSBram Moolenaar 	typval_T    *stack;
538bf67ea1aSBram Moolenaar 
539bf67ea1aSBram Moolenaar 	// A closure is using the arguments and/or local variables.
540bf67ea1aSBram Moolenaar 	// Move them to the called function.
541bf67ea1aSBram Moolenaar 	if (funcstack == NULL)
542bf67ea1aSBram Moolenaar 	    return FAIL;
54385d5e2b7SBram Moolenaar 	funcstack->fs_var_offset = argcount + STACK_FRAME_SIZE;
54485d5e2b7SBram Moolenaar 	funcstack->fs_ga.ga_len = funcstack->fs_var_offset + dfunc->df_varcount;
545bf67ea1aSBram Moolenaar 	stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len);
546bf67ea1aSBram Moolenaar 	funcstack->fs_ga.ga_data = stack;
547bf67ea1aSBram Moolenaar 	if (stack == NULL)
548bf67ea1aSBram Moolenaar 	{
549bf67ea1aSBram Moolenaar 	    vim_free(funcstack);
550bf67ea1aSBram Moolenaar 	    return FAIL;
551bf67ea1aSBram Moolenaar 	}
552bf67ea1aSBram Moolenaar 
553bf67ea1aSBram Moolenaar 	// Move or copy the arguments.
554bf67ea1aSBram Moolenaar 	for (idx = 0; idx < argcount; ++idx)
555bf67ea1aSBram Moolenaar 	{
556bf67ea1aSBram Moolenaar 	    tv = STACK_TV(top + idx);
557bf67ea1aSBram Moolenaar 	    if (free_arguments)
558bf67ea1aSBram Moolenaar 	    {
559bf67ea1aSBram Moolenaar 		*(stack + idx) = *tv;
560bf67ea1aSBram Moolenaar 		tv->v_type = VAR_UNKNOWN;
561bf67ea1aSBram Moolenaar 	    }
562bf67ea1aSBram Moolenaar 	    else
563bf67ea1aSBram Moolenaar 		copy_tv(tv, stack + idx);
564bf67ea1aSBram Moolenaar 	}
565bf67ea1aSBram Moolenaar 	// Move the local variables.
566bf67ea1aSBram Moolenaar 	for (idx = 0; idx < dfunc->df_varcount; ++idx)
567bf67ea1aSBram Moolenaar 	{
568bf67ea1aSBram Moolenaar 	    tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx);
569f821ddaaSBram Moolenaar 
57085d5e2b7SBram Moolenaar 	    // A partial created for a local function, that is also used as a
57185d5e2b7SBram Moolenaar 	    // local variable, has a reference count for the variable, thus
57285d5e2b7SBram Moolenaar 	    // will never go down to zero.  When all these refcounts are one
57385d5e2b7SBram Moolenaar 	    // then the funcstack is unused.  We need to count how many we have
57485d5e2b7SBram Moolenaar 	    // so we need when to check.
575f821ddaaSBram Moolenaar 	    if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
576f821ddaaSBram Moolenaar 	    {
577f821ddaaSBram Moolenaar 		int	    i;
578f821ddaaSBram Moolenaar 
579148ce7aeSBram Moolenaar 		for (i = 0; i < closure_count; ++i)
58085d5e2b7SBram Moolenaar 		    if (tv->vval.v_partial == ((partial_T **)gap->ga_data)[
58185d5e2b7SBram Moolenaar 					      gap->ga_len - closure_count + i])
58285d5e2b7SBram Moolenaar 			++funcstack->fs_min_refcount;
583f821ddaaSBram Moolenaar 	    }
584f821ddaaSBram Moolenaar 
58585d5e2b7SBram Moolenaar 	    *(stack + funcstack->fs_var_offset + idx) = *tv;
586bf67ea1aSBram Moolenaar 	    tv->v_type = VAR_UNKNOWN;
587bf67ea1aSBram Moolenaar 	}
588bf67ea1aSBram Moolenaar 
589148ce7aeSBram Moolenaar 	for (idx = 0; idx < closure_count; ++idx)
590bf67ea1aSBram Moolenaar 	{
591148ce7aeSBram Moolenaar 	    partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len
592148ce7aeSBram Moolenaar 							- closure_count + idx];
593148ce7aeSBram Moolenaar 	    if (pt->pt_refcount > 1)
594f7779c63SBram Moolenaar 	    {
595bf67ea1aSBram Moolenaar 		++funcstack->fs_refcount;
596148ce7aeSBram Moolenaar 		pt->pt_funcstack = funcstack;
5970186e586SBram Moolenaar 		pt->pt_outer.out_stack = &funcstack->fs_ga;
5980186e586SBram Moolenaar 		pt->pt_outer.out_frame_idx = ectx->ec_frame_idx - top;
599f7779c63SBram Moolenaar 	    }
600bf67ea1aSBram Moolenaar 	}
601bf67ea1aSBram Moolenaar     }
602148ce7aeSBram Moolenaar 
603148ce7aeSBram Moolenaar     for (idx = 0; idx < closure_count; ++idx)
604148ce7aeSBram Moolenaar 	partial_unref(((partial_T **)gap->ga_data)[gap->ga_len
605148ce7aeSBram Moolenaar 						       - closure_count + idx]);
606148ce7aeSBram Moolenaar     gap->ga_len -= closure_count;
607148ce7aeSBram Moolenaar     if (gap->ga_len == 0)
608148ce7aeSBram Moolenaar 	ga_clear(gap);
609bf67ea1aSBram Moolenaar 
610bf67ea1aSBram Moolenaar     return OK;
611bf67ea1aSBram Moolenaar }
612bf67ea1aSBram Moolenaar 
613bf67ea1aSBram Moolenaar /*
61485d5e2b7SBram Moolenaar  * Called when a partial is freed or its reference count goes down to one.  The
61585d5e2b7SBram Moolenaar  * funcstack may be the only reference to the partials in the local variables.
61685d5e2b7SBram Moolenaar  * Go over all of them, the funcref and can be freed if all partials
61785d5e2b7SBram Moolenaar  * referencing the funcstack have a reference count of one.
61885d5e2b7SBram Moolenaar  */
61985d5e2b7SBram Moolenaar     void
funcstack_check_refcount(funcstack_T * funcstack)62085d5e2b7SBram Moolenaar funcstack_check_refcount(funcstack_T *funcstack)
62185d5e2b7SBram Moolenaar {
62285d5e2b7SBram Moolenaar     int		    i;
62385d5e2b7SBram Moolenaar     garray_T	    *gap = &funcstack->fs_ga;
62485d5e2b7SBram Moolenaar     int		    done = 0;
62585d5e2b7SBram Moolenaar 
62685d5e2b7SBram Moolenaar     if (funcstack->fs_refcount > funcstack->fs_min_refcount)
62785d5e2b7SBram Moolenaar 	return;
62885d5e2b7SBram Moolenaar     for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i)
62985d5e2b7SBram Moolenaar     {
63085d5e2b7SBram Moolenaar 	typval_T *tv = ((typval_T *)gap->ga_data) + i;
63185d5e2b7SBram Moolenaar 
63285d5e2b7SBram Moolenaar 	if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL
63385d5e2b7SBram Moolenaar 		&& tv->vval.v_partial->pt_funcstack == funcstack
63485d5e2b7SBram Moolenaar 		&& tv->vval.v_partial->pt_refcount == 1)
63585d5e2b7SBram Moolenaar 	    ++done;
63685d5e2b7SBram Moolenaar     }
63785d5e2b7SBram Moolenaar     if (done == funcstack->fs_min_refcount)
63885d5e2b7SBram Moolenaar     {
63985d5e2b7SBram Moolenaar 	typval_T	*stack = gap->ga_data;
64085d5e2b7SBram Moolenaar 
64185d5e2b7SBram Moolenaar 	// All partials referencing the funcstack have a reference count of
64285d5e2b7SBram Moolenaar 	// one, thus the funcstack is no longer of use.
64385d5e2b7SBram Moolenaar 	for (i = 0; i < gap->ga_len; ++i)
64485d5e2b7SBram Moolenaar 	    clear_tv(stack + i);
64585d5e2b7SBram Moolenaar 	vim_free(stack);
64685d5e2b7SBram Moolenaar 	vim_free(funcstack);
64785d5e2b7SBram Moolenaar     }
64885d5e2b7SBram Moolenaar }
64985d5e2b7SBram Moolenaar 
65085d5e2b7SBram Moolenaar /*
6518a7d6542SBram Moolenaar  * Return from the current function.
6528a7d6542SBram Moolenaar  */
653bf67ea1aSBram Moolenaar     static int
func_return(ectx_T * ectx)6544c137214SBram Moolenaar func_return(ectx_T *ectx)
6558a7d6542SBram Moolenaar {
6568a7d6542SBram Moolenaar     int		idx;
65734c54eb6SBram Moolenaar     int		ret_idx;
658bf67ea1aSBram Moolenaar     dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
659bf67ea1aSBram Moolenaar 							  + ectx->ec_dfunc_idx;
660bf67ea1aSBram Moolenaar     int		argcount = ufunc_argcount(dfunc->df_ufunc);
661bf67ea1aSBram Moolenaar     int		top = ectx->ec_frame_idx - argcount;
662c620c055SBram Moolenaar     estack_T	*entry;
66312d26531SBram Moolenaar     int		prev_dfunc_idx = STACK_TV(ectx->ec_frame_idx
66412d26531SBram Moolenaar 					+ STACK_FRAME_FUNC_OFF)->vval.v_number;
665b06b50dfSBram Moolenaar     funclocal_T	*floc;
666b06b50dfSBram Moolenaar #ifdef FEAT_PROFILE
66712d26531SBram Moolenaar     dfunc_T	*prev_dfunc = ((dfunc_T *)def_functions.ga_data)
66812d26531SBram Moolenaar 							      + prev_dfunc_idx;
6698a7d6542SBram Moolenaar 
67012d26531SBram Moolenaar     if (do_profiling == PROF_YES)
67112d26531SBram Moolenaar     {
67212d26531SBram Moolenaar 	ufunc_T *caller = prev_dfunc->df_ufunc;
67312d26531SBram Moolenaar 
67412d26531SBram Moolenaar 	if (dfunc->df_ufunc->uf_profiling
67512d26531SBram Moolenaar 				   || (caller != NULL && caller->uf_profiling))
67612d26531SBram Moolenaar 	{
67712d26531SBram Moolenaar 	    profile_may_end_func(((profinfo_T *)profile_info_ga.ga_data)
67812d26531SBram Moolenaar 			+ profile_info_ga.ga_len - 1, dfunc->df_ufunc, caller);
67912d26531SBram Moolenaar 	    --profile_info_ga.ga_len;
68012d26531SBram Moolenaar 	}
68112d26531SBram Moolenaar     }
68212d26531SBram Moolenaar #endif
683c970e422SBram Moolenaar     // TODO: when is it safe to delete the function when it is no longer used?
684c970e422SBram Moolenaar     --dfunc->df_ufunc->uf_calls;
685c970e422SBram Moolenaar 
6868a7d6542SBram Moolenaar     // execution context goes one level up
687c620c055SBram Moolenaar     entry = estack_pop();
688c620c055SBram Moolenaar     if (entry != NULL)
689c70fe460SBram Moolenaar 	current_sctx = entry->es_save_sctx;
6908a7d6542SBram Moolenaar 
691bf67ea1aSBram Moolenaar     if (handle_closure_in_use(ectx, TRUE) == FAIL)
692bf67ea1aSBram Moolenaar 	return FAIL;
693bf67ea1aSBram Moolenaar 
694bf67ea1aSBram Moolenaar     // Clear the arguments.
695bf67ea1aSBram Moolenaar     for (idx = top; idx < ectx->ec_frame_idx; ++idx)
696bf67ea1aSBram Moolenaar 	clear_tv(STACK_TV(idx));
697bf67ea1aSBram Moolenaar 
698bf67ea1aSBram Moolenaar     // Clear local variables and temp values, but not the return value.
699bf67ea1aSBram Moolenaar     for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE;
7008a7d6542SBram Moolenaar 					idx < ectx->ec_stack.ga_len - 1; ++idx)
7018a7d6542SBram Moolenaar 	clear_tv(STACK_TV(idx));
702170fcfcfSBram Moolenaar 
70334c54eb6SBram Moolenaar     // The return value should be on top of the stack.  However, when aborting
70434c54eb6SBram Moolenaar     // it may not be there and ec_frame_idx is the top of the stack.
70534c54eb6SBram Moolenaar     ret_idx = ectx->ec_stack.ga_len - 1;
7060186e586SBram Moolenaar     if (ret_idx == ectx->ec_frame_idx + STACK_FRAME_IDX_OFF)
70734c54eb6SBram Moolenaar 	ret_idx = 0;
70834c54eb6SBram Moolenaar 
709c04f2a4cSBram Moolenaar     if (ectx->ec_outer_ref != NULL)
710c04f2a4cSBram Moolenaar     {
711c04f2a4cSBram Moolenaar 	if (ectx->ec_outer_ref->or_outer_allocated)
712c04f2a4cSBram Moolenaar 	    vim_free(ectx->ec_outer_ref->or_outer);
713c04f2a4cSBram Moolenaar 	partial_unref(ectx->ec_outer_ref->or_partial);
714c04f2a4cSBram Moolenaar 	vim_free(ectx->ec_outer_ref);
715c04f2a4cSBram Moolenaar     }
7160186e586SBram Moolenaar 
717170fcfcfSBram Moolenaar     // Restore the previous frame.
71812d26531SBram Moolenaar     ectx->ec_dfunc_idx = prev_dfunc_idx;
7190186e586SBram Moolenaar     ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx
7200186e586SBram Moolenaar 					+ STACK_FRAME_IIDX_OFF)->vval.v_number;
7215930ddcdSBram Moolenaar     ectx->ec_instr = (void *)STACK_TV(ectx->ec_frame_idx
7225930ddcdSBram Moolenaar 				       + STACK_FRAME_INSTR_OFF)->vval.v_string;
723c04f2a4cSBram Moolenaar     ectx->ec_outer_ref = (void *)STACK_TV(ectx->ec_frame_idx
7240186e586SBram Moolenaar 				       + STACK_FRAME_OUTER_OFF)->vval.v_string;
7252fecb531SBram Moolenaar     floc = (void *)STACK_TV(ectx->ec_frame_idx
7262fecb531SBram Moolenaar 				   + STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string;
7275366e1aeSBram Moolenaar     // restoring ec_frame_idx must be last
7280186e586SBram Moolenaar     ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx
7290186e586SBram Moolenaar 				       + STACK_FRAME_IDX_OFF)->vval.v_number;
730d386e923SBram Moolenaar 
7312fecb531SBram Moolenaar     if (floc == NULL)
7324c137214SBram Moolenaar 	ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
7332fecb531SBram Moolenaar     else
7342fecb531SBram Moolenaar     {
7354c137214SBram Moolenaar 	ectx->ec_funclocal = *floc;
7362fecb531SBram Moolenaar 	vim_free(floc);
7372fecb531SBram Moolenaar     }
7382fecb531SBram Moolenaar 
73934c54eb6SBram Moolenaar     if (ret_idx > 0)
74034c54eb6SBram Moolenaar     {
74134c54eb6SBram Moolenaar 	// Reset the stack to the position before the call, with a spot for the
74234c54eb6SBram Moolenaar 	// return value, moved there from above the frame.
743170fcfcfSBram Moolenaar 	ectx->ec_stack.ga_len = top + 1;
74434c54eb6SBram Moolenaar 	*STACK_TV_BOT(-1) = *STACK_TV(ret_idx);
74534c54eb6SBram Moolenaar     }
74634c54eb6SBram Moolenaar     else
74734c54eb6SBram Moolenaar 	// Reset the stack to the position before the call.
74834c54eb6SBram Moolenaar 	ectx->ec_stack.ga_len = top;
749bf67ea1aSBram Moolenaar 
7500ba48e8cSBram Moolenaar     funcdepth_decrement();
751e99d422bSBram Moolenaar     --ex_nesting_level;
752bf67ea1aSBram Moolenaar     return OK;
7538a7d6542SBram Moolenaar }
7548a7d6542SBram Moolenaar 
7558a7d6542SBram Moolenaar #undef STACK_TV
7568a7d6542SBram Moolenaar 
7578a7d6542SBram Moolenaar /*
7588a7d6542SBram Moolenaar  * Prepare arguments and rettv for calling a builtin or user function.
7598a7d6542SBram Moolenaar  */
7608a7d6542SBram Moolenaar     static int
call_prepare(int argcount,typval_T * argvars,ectx_T * ectx)7618a7d6542SBram Moolenaar call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
7628a7d6542SBram Moolenaar {
7638a7d6542SBram Moolenaar     int		idx;
7648a7d6542SBram Moolenaar     typval_T	*tv;
7658a7d6542SBram Moolenaar 
7668a7d6542SBram Moolenaar     // Move arguments from bottom of the stack to argvars[] and add terminator.
7678a7d6542SBram Moolenaar     for (idx = 0; idx < argcount; ++idx)
7688a7d6542SBram Moolenaar 	argvars[idx] = *STACK_TV_BOT(idx - argcount);
7698a7d6542SBram Moolenaar     argvars[argcount].v_type = VAR_UNKNOWN;
7708a7d6542SBram Moolenaar 
7718a7d6542SBram Moolenaar     // Result replaces the arguments on the stack.
7728a7d6542SBram Moolenaar     if (argcount > 0)
7738a7d6542SBram Moolenaar 	ectx->ec_stack.ga_len -= argcount - 1;
77435578168SBram Moolenaar     else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
7758a7d6542SBram Moolenaar 	return FAIL;
7768a7d6542SBram Moolenaar     else
7778a7d6542SBram Moolenaar 	++ectx->ec_stack.ga_len;
7788a7d6542SBram Moolenaar 
7798a7d6542SBram Moolenaar     // Default return value is zero.
7808a7d6542SBram Moolenaar     tv = STACK_TV_BOT(-1);
7818a7d6542SBram Moolenaar     tv->v_type = VAR_NUMBER;
7828a7d6542SBram Moolenaar     tv->vval.v_number = 0;
7838a7d6542SBram Moolenaar 
7848a7d6542SBram Moolenaar     return OK;
7858a7d6542SBram Moolenaar }
7868a7d6542SBram Moolenaar 
78708f7a41bSBram Moolenaar // Ugly global to avoid passing the execution context around through many
78808f7a41bSBram Moolenaar // layers.
78908f7a41bSBram Moolenaar static ectx_T *current_ectx = NULL;
79008f7a41bSBram Moolenaar 
7918a7d6542SBram Moolenaar /*
7928a7d6542SBram Moolenaar  * Call a builtin function by index.
7938a7d6542SBram Moolenaar  */
7948a7d6542SBram Moolenaar     static int
call_bfunc(int func_idx,int argcount,ectx_T * ectx)7958a7d6542SBram Moolenaar call_bfunc(int func_idx, int argcount, ectx_T *ectx)
7968a7d6542SBram Moolenaar {
7978a7d6542SBram Moolenaar     typval_T	argvars[MAX_FUNC_ARGS];
7988a7d6542SBram Moolenaar     int		idx;
799171fb923SBram Moolenaar     int		did_emsg_before = did_emsg;
80008f7a41bSBram Moolenaar     ectx_T	*prev_ectx = current_ectx;
8017a3fe3e1SBram Moolenaar     char	*save_func_name = ectx->ec_where.wt_func_name;
8028a7d6542SBram Moolenaar 
8038a7d6542SBram Moolenaar     if (call_prepare(argcount, argvars, ectx) == FAIL)
8048a7d6542SBram Moolenaar 	return FAIL;
8057a3fe3e1SBram Moolenaar     ectx->ec_where.wt_func_name = internal_func_name(func_idx);
8068a7d6542SBram Moolenaar 
80708f7a41bSBram Moolenaar     // Call the builtin function.  Set "current_ectx" so that when it
80808f7a41bSBram Moolenaar     // recursively invokes call_def_function() a closure context can be set.
80908f7a41bSBram Moolenaar     current_ectx = ectx;
8108a7d6542SBram Moolenaar     call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1));
81108f7a41bSBram Moolenaar     current_ectx = prev_ectx;
8127a3fe3e1SBram Moolenaar     ectx->ec_where.wt_func_name = save_func_name;
8138a7d6542SBram Moolenaar 
8148a7d6542SBram Moolenaar     // Clear the arguments.
8158a7d6542SBram Moolenaar     for (idx = 0; idx < argcount; ++idx)
8168a7d6542SBram Moolenaar 	clear_tv(&argvars[idx]);
817015f4267SBram Moolenaar 
81857f799e6SBram Moolenaar     if (did_emsg > did_emsg_before)
819015f4267SBram Moolenaar 	return FAIL;
8208a7d6542SBram Moolenaar     return OK;
8218a7d6542SBram Moolenaar }
8228a7d6542SBram Moolenaar 
8238a7d6542SBram Moolenaar /*
8248a7d6542SBram Moolenaar  * Execute a user defined function.
825ab360526SBram Moolenaar  * If the function is compiled this will add a stack frame and set the
826ab360526SBram Moolenaar  * instruction pointer at the start of the function.
827ab360526SBram Moolenaar  * Otherwise the function is called here.
828c04f2a4cSBram Moolenaar  * If "pt" is not null use "pt->pt_outer" for ec_outer_ref->or_outer.
8297eeefd4aSBram Moolenaar  * "iptr" can be used to replace the instruction with a more efficient one.
8308a7d6542SBram Moolenaar  */
8318a7d6542SBram Moolenaar     static int
call_ufunc(ufunc_T * ufunc,partial_T * pt,int argcount,ectx_T * ectx,isn_T * iptr,dict_T * selfdict)8320186e586SBram Moolenaar call_ufunc(
8330186e586SBram Moolenaar 	ufunc_T	    *ufunc,
8340186e586SBram Moolenaar 	partial_T   *pt,
8350186e586SBram Moolenaar 	int	    argcount,
8360186e586SBram Moolenaar 	ectx_T	    *ectx,
837b1b6f4deSBram Moolenaar 	isn_T	    *iptr,
838b1b6f4deSBram Moolenaar 	dict_T	    *selfdict)
8398a7d6542SBram Moolenaar {
8408a7d6542SBram Moolenaar     typval_T	argvars[MAX_FUNC_ARGS];
8418a7d6542SBram Moolenaar     funcexe_T   funcexe;
8428a7d6542SBram Moolenaar     int		error;
8438a7d6542SBram Moolenaar     int		idx;
84428ee892aSBram Moolenaar     int		did_emsg_before = did_emsg;
845968a5b62SBram Moolenaar     compiletype_T compile_type = COMPILE_TYPE(ufunc);
8468a7d6542SBram Moolenaar 
847e99d422bSBram Moolenaar     if (func_needs_compiling(ufunc, compile_type)
848e99d422bSBram Moolenaar 		&& compile_def_function(ufunc, FALSE, compile_type, NULL)
849e99d422bSBram Moolenaar 								       == FAIL)
850822ba247SBram Moolenaar 	return FAIL;
8510cb5bcf5SBram Moolenaar     if (ufunc->uf_def_status == UF_COMPILED)
8527eeefd4aSBram Moolenaar     {
85352c124d3SBram Moolenaar 	error = check_user_func_argcount(ufunc, argcount);
8545082471fSBram Moolenaar 	if (error != FCERR_UNKNOWN)
8555082471fSBram Moolenaar 	{
8565082471fSBram Moolenaar 	    if (error == FCERR_TOOMANY)
8575082471fSBram Moolenaar 		semsg(_(e_toomanyarg), ufunc->uf_name);
8585082471fSBram Moolenaar 	    else
8595082471fSBram Moolenaar 		semsg(_(e_toofewarg), ufunc->uf_name);
8605082471fSBram Moolenaar 	    return FAIL;
8615082471fSBram Moolenaar 	}
8625082471fSBram Moolenaar 
8637eeefd4aSBram Moolenaar 	// The function has been compiled, can call it quickly.  For a function
8647eeefd4aSBram Moolenaar 	// that was defined later: we can call it directly next time.
865cd45ed03SBram Moolenaar 	// TODO: what if the function was deleted and then defined again?
8667eeefd4aSBram Moolenaar 	if (iptr != NULL)
8677eeefd4aSBram Moolenaar 	{
86820431c9dSBram Moolenaar 	    delete_instr(iptr);
8697eeefd4aSBram Moolenaar 	    iptr->isn_type = ISN_DCALL;
8707eeefd4aSBram Moolenaar 	    iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
8717eeefd4aSBram Moolenaar 	    iptr->isn_arg.dfunc.cdf_argcount = argcount;
8727eeefd4aSBram Moolenaar 	}
8734c137214SBram Moolenaar 	return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, ectx);
8747eeefd4aSBram Moolenaar     }
8758a7d6542SBram Moolenaar 
8768a7d6542SBram Moolenaar     if (call_prepare(argcount, argvars, ectx) == FAIL)
8778a7d6542SBram Moolenaar 	return FAIL;
878a80faa89SBram Moolenaar     CLEAR_FIELD(funcexe);
8798a7d6542SBram Moolenaar     funcexe.evaluate = TRUE;
880b1b6f4deSBram Moolenaar     funcexe.selfdict = selfdict != NULL ? selfdict : dict_stack_get_dict();
8818a7d6542SBram Moolenaar 
8828a7d6542SBram Moolenaar     // Call the user function.  Result goes in last position on the stack.
8838a7d6542SBram Moolenaar     // TODO: add selfdict if there is one
8848a7d6542SBram Moolenaar     error = call_user_func_check(ufunc, argcount, argvars,
885b1b6f4deSBram Moolenaar 				 STACK_TV_BOT(-1), &funcexe, funcexe.selfdict);
8868a7d6542SBram Moolenaar 
8878a7d6542SBram Moolenaar     // Clear the arguments.
8888a7d6542SBram Moolenaar     for (idx = 0; idx < argcount; ++idx)
8898a7d6542SBram Moolenaar 	clear_tv(&argvars[idx]);
8908a7d6542SBram Moolenaar 
8918a7d6542SBram Moolenaar     if (error != FCERR_NONE)
8928a7d6542SBram Moolenaar     {
8938a7d6542SBram Moolenaar 	user_func_error(error, ufunc->uf_name);
8948a7d6542SBram Moolenaar 	return FAIL;
8958a7d6542SBram Moolenaar     }
89628ee892aSBram Moolenaar     if (did_emsg > did_emsg_before)
897ed677f55SBram Moolenaar 	// Error other than from calling the function itself.
898ed677f55SBram Moolenaar 	return FAIL;
8998a7d6542SBram Moolenaar     return OK;
9008a7d6542SBram Moolenaar }
9018a7d6542SBram Moolenaar 
9028a7d6542SBram Moolenaar /*
903a91a7132SBram Moolenaar  * If command modifiers were applied restore them.
904a91a7132SBram Moolenaar  */
905a91a7132SBram Moolenaar     static void
may_restore_cmdmod(funclocal_T * funclocal)906a91a7132SBram Moolenaar may_restore_cmdmod(funclocal_T *funclocal)
907a91a7132SBram Moolenaar {
908a91a7132SBram Moolenaar     if (funclocal->floc_restore_cmdmod)
909a91a7132SBram Moolenaar     {
910a91a7132SBram Moolenaar 	cmdmod.cmod_filter_regmatch.regprog = NULL;
911a91a7132SBram Moolenaar 	undo_cmdmod(&cmdmod);
912a91a7132SBram Moolenaar 	cmdmod = funclocal->floc_save_cmdmod;
913a91a7132SBram Moolenaar 	funclocal->floc_restore_cmdmod = FALSE;
914a91a7132SBram Moolenaar     }
915a91a7132SBram Moolenaar }
916a91a7132SBram Moolenaar 
917a91a7132SBram Moolenaar /*
91888c89c77SBram Moolenaar  * Return TRUE if an error was given (not caught in try/catch) or CTRL-C was
91988c89c77SBram Moolenaar  * pressed.
920a177344dSBram Moolenaar  */
921a177344dSBram Moolenaar     static int
vim9_aborting(int prev_uncaught_emsg)92288c89c77SBram Moolenaar vim9_aborting(int prev_uncaught_emsg)
923a177344dSBram Moolenaar {
92488c89c77SBram Moolenaar     return uncaught_emsg > prev_uncaught_emsg || got_int || did_throw;
925a177344dSBram Moolenaar }
926a177344dSBram Moolenaar 
927a177344dSBram Moolenaar /*
9288a7d6542SBram Moolenaar  * Execute a function by "name".
9298a7d6542SBram Moolenaar  * This can be a builtin function or a user function.
9307eeefd4aSBram Moolenaar  * "iptr" can be used to replace the instruction with a more efficient one.
9318a7d6542SBram Moolenaar  * Returns FAIL if not found without an error message.
9328a7d6542SBram Moolenaar  */
9338a7d6542SBram Moolenaar     static int
call_by_name(char_u * name,int argcount,ectx_T * ectx,isn_T * iptr,dict_T * selfdict)9342fecb531SBram Moolenaar call_by_name(
9352fecb531SBram Moolenaar 	char_u	    *name,
9362fecb531SBram Moolenaar 	int	    argcount,
9372fecb531SBram Moolenaar 	ectx_T	    *ectx,
938b1b6f4deSBram Moolenaar 	isn_T	    *iptr,
939b1b6f4deSBram Moolenaar 	dict_T	    *selfdict)
9408a7d6542SBram Moolenaar {
9418a7d6542SBram Moolenaar     ufunc_T *ufunc;
9428a7d6542SBram Moolenaar 
9438a7d6542SBram Moolenaar     if (builtin_function(name, -1))
9448a7d6542SBram Moolenaar     {
9458a7d6542SBram Moolenaar 	int func_idx = find_internal_func(name);
9468a7d6542SBram Moolenaar 
9478a7d6542SBram Moolenaar 	if (func_idx < 0)
9488a7d6542SBram Moolenaar 	    return FAIL;
949389df259SBram Moolenaar 	if (check_internal_func(func_idx, argcount) < 0)
9508a7d6542SBram Moolenaar 	    return FAIL;
9518a7d6542SBram Moolenaar 	return call_bfunc(func_idx, argcount, ectx);
9528a7d6542SBram Moolenaar     }
9538a7d6542SBram Moolenaar 
9544c17ad94SBram Moolenaar     ufunc = find_func(name, FALSE, NULL);
955a177344dSBram Moolenaar 
956a177344dSBram Moolenaar     if (ufunc == NULL)
957a177344dSBram Moolenaar     {
95888c89c77SBram Moolenaar 	int prev_uncaught_emsg = uncaught_emsg;
959a177344dSBram Moolenaar 
960a177344dSBram Moolenaar 	if (script_autoload(name, TRUE))
961a177344dSBram Moolenaar 	    // loaded a package, search for the function again
962a177344dSBram Moolenaar 	    ufunc = find_func(name, FALSE, NULL);
96388c89c77SBram Moolenaar 
96488c89c77SBram Moolenaar 	if (vim9_aborting(prev_uncaught_emsg))
965a177344dSBram Moolenaar 	    return FAIL;  // bail out if loading the script caused an error
966a177344dSBram Moolenaar     }
967a177344dSBram Moolenaar 
9688a7d6542SBram Moolenaar     if (ufunc != NULL)
96904947cc6SBram Moolenaar     {
9706ce46b99SBram Moolenaar 	if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL)
97104947cc6SBram Moolenaar 	{
97204947cc6SBram Moolenaar 	    int i;
97304947cc6SBram Moolenaar 	    typval_T	*argv = STACK_TV_BOT(0) - argcount;
97404947cc6SBram Moolenaar 
97504947cc6SBram Moolenaar 	    // The function can change at runtime, check that the argument
97604947cc6SBram Moolenaar 	    // types are correct.
97704947cc6SBram Moolenaar 	    for (i = 0; i < argcount; ++i)
97804947cc6SBram Moolenaar 	    {
979e3ffcd99SBram Moolenaar 		type_T *type = NULL;
98004947cc6SBram Moolenaar 
9816ce46b99SBram Moolenaar 		if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
982e3ffcd99SBram Moolenaar 		    type = ufunc->uf_arg_types[i];
983e3ffcd99SBram Moolenaar 		else if (ufunc->uf_va_type != NULL)
984e3ffcd99SBram Moolenaar 		    type = ufunc->uf_va_type->tt_member;
98504947cc6SBram Moolenaar 		if (type != NULL && check_typval_arg_type(type,
9867a3fe3e1SBram Moolenaar 						&argv[i], NULL, i + 1) == FAIL)
98704947cc6SBram Moolenaar 		    return FAIL;
98804947cc6SBram Moolenaar 	    }
98904947cc6SBram Moolenaar 	}
99004947cc6SBram Moolenaar 
991b1b6f4deSBram Moolenaar 	return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict);
99204947cc6SBram Moolenaar     }
9938a7d6542SBram Moolenaar 
9948a7d6542SBram Moolenaar     return FAIL;
9958a7d6542SBram Moolenaar }
9968a7d6542SBram Moolenaar 
9978a7d6542SBram Moolenaar     static int
call_partial(typval_T * tv,int argcount_arg,ectx_T * ectx)9982fecb531SBram Moolenaar call_partial(
9992fecb531SBram Moolenaar 	typval_T    *tv,
10002fecb531SBram Moolenaar 	int	    argcount_arg,
10012fecb531SBram Moolenaar 	ectx_T	    *ectx)
10028a7d6542SBram Moolenaar {
1003a90afb9aSBram Moolenaar     int		argcount = argcount_arg;
1004bd5da371SBram Moolenaar     char_u	*name = NULL;
10058a7d6542SBram Moolenaar     int		called_emsg_before = called_emsg;
1006cb6cbf29SBram Moolenaar     int		res = FAIL;
1007b1b6f4deSBram Moolenaar     dict_T	*selfdict = NULL;
10088a7d6542SBram Moolenaar 
10098a7d6542SBram Moolenaar     if (tv->v_type == VAR_PARTIAL)
10108a7d6542SBram Moolenaar     {
10118a7d6542SBram Moolenaar 	partial_T   *pt = tv->vval.v_partial;
1012a90afb9aSBram Moolenaar 	int	    i;
1013a90afb9aSBram Moolenaar 
1014a90afb9aSBram Moolenaar 	if (pt->pt_argc > 0)
1015a90afb9aSBram Moolenaar 	{
1016a90afb9aSBram Moolenaar 	    // Make space for arguments from the partial, shift the "argcount"
1017a90afb9aSBram Moolenaar 	    // arguments up.
101835578168SBram Moolenaar 	    if (GA_GROW_FAILS(&ectx->ec_stack, pt->pt_argc))
1019a90afb9aSBram Moolenaar 		return FAIL;
1020a90afb9aSBram Moolenaar 	    for (i = 1; i <= argcount; ++i)
1021a90afb9aSBram Moolenaar 		*STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i);
1022a90afb9aSBram Moolenaar 	    ectx->ec_stack.ga_len += pt->pt_argc;
1023a90afb9aSBram Moolenaar 	    argcount += pt->pt_argc;
1024a90afb9aSBram Moolenaar 
1025a90afb9aSBram Moolenaar 	    // copy the arguments from the partial onto the stack
1026a90afb9aSBram Moolenaar 	    for (i = 0; i < pt->pt_argc; ++i)
1027a90afb9aSBram Moolenaar 		copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i));
1028a90afb9aSBram Moolenaar 	}
1029b1b6f4deSBram Moolenaar 	selfdict = pt->pt_dict;
10308a7d6542SBram Moolenaar 
10318a7d6542SBram Moolenaar 	if (pt->pt_func != NULL)
1032b1b6f4deSBram Moolenaar 	    return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL, selfdict);
1033f7779c63SBram Moolenaar 
10348a7d6542SBram Moolenaar 	name = pt->pt_name;
10358a7d6542SBram Moolenaar     }
1036bd5da371SBram Moolenaar     else if (tv->v_type == VAR_FUNC)
10378a7d6542SBram Moolenaar 	name = tv->vval.v_string;
103895006e3dSBram Moolenaar     if (name != NULL)
103995006e3dSBram Moolenaar     {
104095006e3dSBram Moolenaar 	char_u	fname_buf[FLEN_FIXED + 1];
104195006e3dSBram Moolenaar 	char_u	*tofree = NULL;
104295006e3dSBram Moolenaar 	int	error = FCERR_NONE;
104395006e3dSBram Moolenaar 	char_u	*fname;
104495006e3dSBram Moolenaar 
104595006e3dSBram Moolenaar 	// May need to translate <SNR>123_ to K_SNR.
104695006e3dSBram Moolenaar 	fname = fname_trans_sid(name, fname_buf, &tofree, &error);
104795006e3dSBram Moolenaar 	if (error != FCERR_NONE)
104895006e3dSBram Moolenaar 	    res = FAIL;
104995006e3dSBram Moolenaar 	else
1050b1b6f4deSBram Moolenaar 	    res = call_by_name(fname, argcount, ectx, NULL, selfdict);
105195006e3dSBram Moolenaar 	vim_free(tofree);
105295006e3dSBram Moolenaar     }
105395006e3dSBram Moolenaar 
1054cb6cbf29SBram Moolenaar     if (res == FAIL)
10558a7d6542SBram Moolenaar     {
10568a7d6542SBram Moolenaar 	if (called_emsg == called_emsg_before)
1057015f4267SBram Moolenaar 	    semsg(_(e_unknownfunc),
1058015f4267SBram Moolenaar 				  name == NULL ? (char_u *)"[unknown]" : name);
10598a7d6542SBram Moolenaar 	return FAIL;
10608a7d6542SBram Moolenaar     }
10618a7d6542SBram Moolenaar     return OK;
10628a7d6542SBram Moolenaar }
10638a7d6542SBram Moolenaar 
10648a7d6542SBram Moolenaar /*
10650b4c66c6SBram Moolenaar  * Check if "lock" is VAR_LOCKED or VAR_FIXED.  If so give an error and return
10660b4c66c6SBram Moolenaar  * TRUE.
10670b4c66c6SBram Moolenaar  */
10680b4c66c6SBram Moolenaar     static int
error_if_locked(int lock,char * error)10690b4c66c6SBram Moolenaar error_if_locked(int lock, char *error)
10700b4c66c6SBram Moolenaar {
10710b4c66c6SBram Moolenaar     if (lock & (VAR_LOCKED | VAR_FIXED))
10720b4c66c6SBram Moolenaar     {
10730b4c66c6SBram Moolenaar 	emsg(_(error));
10740b4c66c6SBram Moolenaar 	return TRUE;
10750b4c66c6SBram Moolenaar     }
10760b4c66c6SBram Moolenaar     return FALSE;
10770b4c66c6SBram Moolenaar }
10780b4c66c6SBram Moolenaar 
10790b4c66c6SBram Moolenaar /*
10805b5ae29bSBram Moolenaar  * Give an error if "tv" is not a number and return FAIL.
10815b5ae29bSBram Moolenaar  */
10825b5ae29bSBram Moolenaar     static int
check_for_number(typval_T * tv)10835b5ae29bSBram Moolenaar check_for_number(typval_T *tv)
10845b5ae29bSBram Moolenaar {
10855b5ae29bSBram Moolenaar     if (tv->v_type != VAR_NUMBER)
10865b5ae29bSBram Moolenaar     {
10875b5ae29bSBram Moolenaar 	semsg(_(e_expected_str_but_got_str),
10885b5ae29bSBram Moolenaar 		vartype_name(VAR_NUMBER), vartype_name(tv->v_type));
10895b5ae29bSBram Moolenaar 	return FAIL;
10905b5ae29bSBram Moolenaar     }
10915b5ae29bSBram Moolenaar     return OK;
10925b5ae29bSBram Moolenaar }
10935b5ae29bSBram Moolenaar 
10945b5ae29bSBram Moolenaar /*
10950bbf722aSBram Moolenaar  * Store "tv" in variable "name".
10960bbf722aSBram Moolenaar  * This is for s: and g: variables.
10970bbf722aSBram Moolenaar  */
10980bbf722aSBram Moolenaar     static void
store_var(char_u * name,typval_T * tv)10990bbf722aSBram Moolenaar store_var(char_u *name, typval_T *tv)
11000bbf722aSBram Moolenaar {
11010bbf722aSBram Moolenaar     funccal_entry_T entry;
1102d877a570SBram Moolenaar     int		    flags = ASSIGN_DECL;
11030bbf722aSBram Moolenaar 
1104d877a570SBram Moolenaar     if (tv->v_lock)
1105d877a570SBram Moolenaar 	flags |= ASSIGN_CONST;
11060bbf722aSBram Moolenaar     save_funccal(&entry);
1107d877a570SBram Moolenaar     set_var_const(name, NULL, tv, FALSE, flags, 0);
11080bbf722aSBram Moolenaar     restore_funccal();
11090bbf722aSBram Moolenaar }
11100bbf722aSBram Moolenaar 
11113beaf9cdSBram Moolenaar /*
11124f5e3977SBram Moolenaar  * Convert "tv" to a string.
11134f5e3977SBram Moolenaar  * Return FAIL if not allowed.
11144f5e3977SBram Moolenaar  */
11154f5e3977SBram Moolenaar     static int
do_2string(typval_T * tv,int is_2string_any,int tolerant)11165fa9b244SBram Moolenaar do_2string(typval_T *tv, int is_2string_any, int tolerant)
11174f5e3977SBram Moolenaar {
11184f5e3977SBram Moolenaar     if (tv->v_type != VAR_STRING)
11194f5e3977SBram Moolenaar     {
11204f5e3977SBram Moolenaar 	char_u *str;
11214f5e3977SBram Moolenaar 
11224f5e3977SBram Moolenaar 	if (is_2string_any)
11234f5e3977SBram Moolenaar 	{
11244f5e3977SBram Moolenaar 	    switch (tv->v_type)
11254f5e3977SBram Moolenaar 	    {
11264f5e3977SBram Moolenaar 		case VAR_SPECIAL:
11274f5e3977SBram Moolenaar 		case VAR_BOOL:
11284f5e3977SBram Moolenaar 		case VAR_NUMBER:
11294f5e3977SBram Moolenaar 		case VAR_FLOAT:
11304f5e3977SBram Moolenaar 		case VAR_BLOB:	break;
11315fa9b244SBram Moolenaar 
11325fa9b244SBram Moolenaar 		case VAR_LIST:
11335fa9b244SBram Moolenaar 				if (tolerant)
11345fa9b244SBram Moolenaar 				{
1135b288ba9fSBram Moolenaar 				    char_u	*s, *e, *p;
1136b288ba9fSBram Moolenaar 				    garray_T	ga;
11375fa9b244SBram Moolenaar 
1138b288ba9fSBram Moolenaar 				    ga_init2(&ga, sizeof(char_u *), 1);
1139b288ba9fSBram Moolenaar 
1140b288ba9fSBram Moolenaar 				    // Convert to NL separated items, then
1141b288ba9fSBram Moolenaar 				    // escape the items and replace the NL with
1142b288ba9fSBram Moolenaar 				    // a space.
11435fa9b244SBram Moolenaar 				    str = typval2string(tv, TRUE);
1144b288ba9fSBram Moolenaar 				    if (str == NULL)
1145b288ba9fSBram Moolenaar 					return FAIL;
1146b288ba9fSBram Moolenaar 				    s = str;
1147b288ba9fSBram Moolenaar 				    while ((e = vim_strchr(s, '\n')) != NULL)
1148b288ba9fSBram Moolenaar 				    {
1149b288ba9fSBram Moolenaar 					*e = NUL;
1150*21c1a0c2SBram Moolenaar 					p = vim_strsave_fnameescape(s,
1151*21c1a0c2SBram Moolenaar 								     VSE_NONE);
1152b288ba9fSBram Moolenaar 					if (p != NULL)
1153b288ba9fSBram Moolenaar 					{
1154b288ba9fSBram Moolenaar 					    ga_concat(&ga, p);
1155b288ba9fSBram Moolenaar 					    ga_concat(&ga, (char_u *)" ");
1156b288ba9fSBram Moolenaar 					    vim_free(p);
1157b288ba9fSBram Moolenaar 					}
1158b288ba9fSBram Moolenaar 					s = e + 1;
1159b288ba9fSBram Moolenaar 				    }
1160b288ba9fSBram Moolenaar 				    vim_free(str);
11615fa9b244SBram Moolenaar 				    clear_tv(tv);
11625fa9b244SBram Moolenaar 				    tv->v_type = VAR_STRING;
1163b288ba9fSBram Moolenaar 				    tv->vval.v_string = ga.ga_data;
11645fa9b244SBram Moolenaar 				    return OK;
11655fa9b244SBram Moolenaar 				}
11665fa9b244SBram Moolenaar 				// FALLTHROUGH
11674f5e3977SBram Moolenaar 		default:	to_string_error(tv->v_type);
11684f5e3977SBram Moolenaar 				return FAIL;
11694f5e3977SBram Moolenaar 	    }
11704f5e3977SBram Moolenaar 	}
117134453208SBram Moolenaar 	str = typval_tostring(tv, TRUE);
11724f5e3977SBram Moolenaar 	clear_tv(tv);
11734f5e3977SBram Moolenaar 	tv->v_type = VAR_STRING;
11744f5e3977SBram Moolenaar 	tv->vval.v_string = str;
11754f5e3977SBram Moolenaar     }
11764f5e3977SBram Moolenaar     return OK;
11774f5e3977SBram Moolenaar }
11784f5e3977SBram Moolenaar 
11794f5e3977SBram Moolenaar /*
11803beaf9cdSBram Moolenaar  * When the value of "sv" is a null list of dict, allocate it.
11813beaf9cdSBram Moolenaar  */
11823beaf9cdSBram Moolenaar     static void
allocate_if_null(typval_T * tv)11833beaf9cdSBram Moolenaar allocate_if_null(typval_T *tv)
11843beaf9cdSBram Moolenaar {
11853beaf9cdSBram Moolenaar     switch (tv->v_type)
11863beaf9cdSBram Moolenaar     {
11873beaf9cdSBram Moolenaar 	case VAR_LIST:
11883beaf9cdSBram Moolenaar 	    if (tv->vval.v_list == NULL)
1189fef8064bSBram Moolenaar 		(void)rettv_list_alloc(tv);
11903beaf9cdSBram Moolenaar 	    break;
11913beaf9cdSBram Moolenaar 	case VAR_DICT:
11923beaf9cdSBram Moolenaar 	    if (tv->vval.v_dict == NULL)
1193fef8064bSBram Moolenaar 		(void)rettv_dict_alloc(tv);
11943beaf9cdSBram Moolenaar 	    break;
1195b7c21afeSBram Moolenaar 	case VAR_BLOB:
1196b7c21afeSBram Moolenaar 	    if (tv->vval.v_blob == NULL)
1197b7c21afeSBram Moolenaar 		(void)rettv_blob_alloc(tv);
1198b7c21afeSBram Moolenaar 	    break;
11993beaf9cdSBram Moolenaar 	default:
12003beaf9cdSBram Moolenaar 	    break;
12013beaf9cdSBram Moolenaar     }
12023beaf9cdSBram Moolenaar }
1203d3aac291SBram Moolenaar 
1204e7525c55SBram Moolenaar /*
12050289a093SBram Moolenaar  * Return the character "str[index]" where "index" is the character index,
12060289a093SBram Moolenaar  * including composing characters.
12070289a093SBram Moolenaar  * If "index" is out of range NULL is returned.
1208e7525c55SBram Moolenaar  */
1209e7525c55SBram Moolenaar     char_u *
char_from_string(char_u * str,varnumber_T index)1210e7525c55SBram Moolenaar char_from_string(char_u *str, varnumber_T index)
1211e7525c55SBram Moolenaar {
1212e7525c55SBram Moolenaar     size_t	    nbyte = 0;
1213e7525c55SBram Moolenaar     varnumber_T	    nchar = index;
1214e7525c55SBram Moolenaar     size_t	    slen;
1215e7525c55SBram Moolenaar 
1216e7525c55SBram Moolenaar     if (str == NULL)
1217e7525c55SBram Moolenaar 	return NULL;
1218e7525c55SBram Moolenaar     slen = STRLEN(str);
1219e7525c55SBram Moolenaar 
1220ff871400SBram Moolenaar     // Do the same as for a list: a negative index counts from the end.
1221ff871400SBram Moolenaar     // Optimization to check the first byte to be below 0x80 (and no composing
1222ff871400SBram Moolenaar     // character follows) makes this a lot faster.
1223e7525c55SBram Moolenaar     if (index < 0)
1224e7525c55SBram Moolenaar     {
1225e7525c55SBram Moolenaar 	int	clen = 0;
1226e7525c55SBram Moolenaar 
1227e7525c55SBram Moolenaar 	for (nbyte = 0; nbyte < slen; ++clen)
1228ff871400SBram Moolenaar 	{
1229ff871400SBram Moolenaar 	    if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
1230ff871400SBram Moolenaar 		++nbyte;
1231ff871400SBram Moolenaar 	    else if (enc_utf8)
1232ff871400SBram Moolenaar 		nbyte += utfc_ptr2len(str + nbyte);
1233ff871400SBram Moolenaar 	    else
12340289a093SBram Moolenaar 		nbyte += mb_ptr2len(str + nbyte);
1235ff871400SBram Moolenaar 	}
1236e7525c55SBram Moolenaar 	nchar = clen + index;
1237e7525c55SBram Moolenaar 	if (nchar < 0)
1238e7525c55SBram Moolenaar 	    // unlike list: index out of range results in empty string
1239e7525c55SBram Moolenaar 	    return NULL;
1240e7525c55SBram Moolenaar     }
1241e7525c55SBram Moolenaar 
1242e7525c55SBram Moolenaar     for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar)
1243ff871400SBram Moolenaar     {
1244ff871400SBram Moolenaar 	if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
1245ff871400SBram Moolenaar 	    ++nbyte;
1246ff871400SBram Moolenaar 	else if (enc_utf8)
1247ff871400SBram Moolenaar 	    nbyte += utfc_ptr2len(str + nbyte);
1248ff871400SBram Moolenaar 	else
12490289a093SBram Moolenaar 	    nbyte += mb_ptr2len(str + nbyte);
1250ff871400SBram Moolenaar     }
1251e7525c55SBram Moolenaar     if (nbyte >= slen)
1252e7525c55SBram Moolenaar 	return NULL;
12530289a093SBram Moolenaar     return vim_strnsave(str + nbyte, mb_ptr2len(str + nbyte));
1254e7525c55SBram Moolenaar }
1255e7525c55SBram Moolenaar 
1256e7525c55SBram Moolenaar /*
1257e7525c55SBram Moolenaar  * Get the byte index for character index "idx" in string "str" with length
12580289a093SBram Moolenaar  * "str_len".  Composing characters are included.
1259e7525c55SBram Moolenaar  * If going over the end return "str_len".
1260e7525c55SBram Moolenaar  * If "idx" is negative count from the end, -1 is the last character.
1261e7525c55SBram Moolenaar  * When going over the start return -1.
1262e7525c55SBram Moolenaar  */
1263e7525c55SBram Moolenaar     static long
char_idx2byte(char_u * str,size_t str_len,varnumber_T idx)1264e7525c55SBram Moolenaar char_idx2byte(char_u *str, size_t str_len, varnumber_T idx)
1265e7525c55SBram Moolenaar {
1266e7525c55SBram Moolenaar     varnumber_T nchar = idx;
1267e7525c55SBram Moolenaar     size_t	nbyte = 0;
1268e7525c55SBram Moolenaar 
1269e7525c55SBram Moolenaar     if (nchar >= 0)
1270e7525c55SBram Moolenaar     {
1271e7525c55SBram Moolenaar 	while (nchar > 0 && nbyte < str_len)
1272e7525c55SBram Moolenaar 	{
12730289a093SBram Moolenaar 	    nbyte += mb_ptr2len(str + nbyte);
1274e7525c55SBram Moolenaar 	    --nchar;
1275e7525c55SBram Moolenaar 	}
1276e7525c55SBram Moolenaar     }
1277e7525c55SBram Moolenaar     else
1278e7525c55SBram Moolenaar     {
1279e7525c55SBram Moolenaar 	nbyte = str_len;
1280e7525c55SBram Moolenaar 	while (nchar < 0 && nbyte > 0)
1281e7525c55SBram Moolenaar 	{
1282e7525c55SBram Moolenaar 	    --nbyte;
1283e7525c55SBram Moolenaar 	    nbyte -= mb_head_off(str, str + nbyte);
1284e7525c55SBram Moolenaar 	    ++nchar;
1285e7525c55SBram Moolenaar 	}
1286e7525c55SBram Moolenaar 	if (nchar < 0)
1287e7525c55SBram Moolenaar 	    return -1;
1288e7525c55SBram Moolenaar     }
1289e7525c55SBram Moolenaar     return (long)nbyte;
1290e7525c55SBram Moolenaar }
1291e7525c55SBram Moolenaar 
1292e7525c55SBram Moolenaar /*
12930289a093SBram Moolenaar  * Return the slice "str[first : last]" using character indexes.  Composing
12940289a093SBram Moolenaar  * characters are included.
12956601b629SBram Moolenaar  * "exclusive" is TRUE for slice().
1296e7525c55SBram Moolenaar  * Return NULL when the result is empty.
1297e7525c55SBram Moolenaar  */
1298e7525c55SBram Moolenaar     char_u *
string_slice(char_u * str,varnumber_T first,varnumber_T last,int exclusive)12996601b629SBram Moolenaar string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive)
1300e7525c55SBram Moolenaar {
1301e7525c55SBram Moolenaar     long	start_byte, end_byte;
1302e7525c55SBram Moolenaar     size_t	slen;
1303e7525c55SBram Moolenaar 
1304e7525c55SBram Moolenaar     if (str == NULL)
1305e7525c55SBram Moolenaar 	return NULL;
1306e7525c55SBram Moolenaar     slen = STRLEN(str);
1307e7525c55SBram Moolenaar     start_byte = char_idx2byte(str, slen, first);
1308e7525c55SBram Moolenaar     if (start_byte < 0)
1309e7525c55SBram Moolenaar 	start_byte = 0; // first index very negative: use zero
13106601b629SBram Moolenaar     if ((last == -1 && !exclusive) || last == VARNUM_MAX)
1311e7525c55SBram Moolenaar 	end_byte = (long)slen;
1312e7525c55SBram Moolenaar     else
1313e7525c55SBram Moolenaar     {
1314e7525c55SBram Moolenaar 	end_byte = char_idx2byte(str, slen, last);
13156601b629SBram Moolenaar 	if (!exclusive && end_byte >= 0 && end_byte < (long)slen)
1316e7525c55SBram Moolenaar 	    // end index is inclusive
13170289a093SBram Moolenaar 	    end_byte += mb_ptr2len(str + end_byte);
1318e7525c55SBram Moolenaar     }
1319e7525c55SBram Moolenaar 
1320e7525c55SBram Moolenaar     if (start_byte >= (long)slen || end_byte <= start_byte)
1321e7525c55SBram Moolenaar 	return NULL;
1322e7525c55SBram Moolenaar     return vim_strnsave(str + start_byte, end_byte - start_byte);
1323e7525c55SBram Moolenaar }
1324e7525c55SBram Moolenaar 
13256db660beSBram Moolenaar /*
13266db660beSBram Moolenaar  * Get a script variable for ISN_STORESCRIPT and ISN_LOADSCRIPT.
13276db660beSBram Moolenaar  * When "dfunc_idx" is negative don't give an error.
13286db660beSBram Moolenaar  * Returns NULL for an error.
13296db660beSBram Moolenaar  */
133007a65d26SBram Moolenaar     static svar_T *
get_script_svar(scriptref_T * sref,int dfunc_idx)13316db660beSBram Moolenaar get_script_svar(scriptref_T *sref, int dfunc_idx)
133207a65d26SBram Moolenaar {
133307a65d26SBram Moolenaar     scriptitem_T    *si = SCRIPT_ITEM(sref->sref_sid);
13346db660beSBram Moolenaar     dfunc_T	    *dfunc = dfunc_idx < 0 ? NULL
13356db660beSBram Moolenaar 			      : ((dfunc_T *)def_functions.ga_data) + dfunc_idx;
133607a65d26SBram Moolenaar     svar_T	    *sv;
133707a65d26SBram Moolenaar 
133807a65d26SBram Moolenaar     if (sref->sref_seq != si->sn_script_seq)
133907a65d26SBram Moolenaar     {
13406db660beSBram Moolenaar 	// The script was reloaded after the function was compiled, the
13416db660beSBram Moolenaar 	// script_idx may not be valid.
13426db660beSBram Moolenaar 	if (dfunc != NULL)
134307a65d26SBram Moolenaar 	    semsg(_(e_script_variable_invalid_after_reload_in_function_str),
13446db660beSBram Moolenaar 					 printable_func_name(dfunc->df_ufunc));
134507a65d26SBram Moolenaar 	return NULL;
134607a65d26SBram Moolenaar     }
134707a65d26SBram Moolenaar     sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx;
134860dc8274SBram Moolenaar     if (!equal_type(sv->sv_type, sref->sref_type, 0))
134907a65d26SBram Moolenaar     {
13506db660beSBram Moolenaar 	if (dfunc != NULL)
135107a65d26SBram Moolenaar 	    emsg(_(e_script_variable_type_changed));
135207a65d26SBram Moolenaar 	return NULL;
135307a65d26SBram Moolenaar     }
135407a65d26SBram Moolenaar     return sv;
135507a65d26SBram Moolenaar }
135607a65d26SBram Moolenaar 
13570bbf722aSBram Moolenaar /*
13582067733bSBram Moolenaar  * Function passed to do_cmdline() for splitting a script joined by NL
13592067733bSBram Moolenaar  * characters.
13602067733bSBram Moolenaar  */
13612067733bSBram Moolenaar     static char_u *
get_split_sourceline(int c UNUSED,void * cookie,int indent UNUSED,getline_opt_T options UNUSED)13622067733bSBram Moolenaar get_split_sourceline(
13632067733bSBram Moolenaar 	int c UNUSED,
13642067733bSBram Moolenaar 	void *cookie,
13652067733bSBram Moolenaar 	int indent UNUSED,
13662067733bSBram Moolenaar 	getline_opt_T options UNUSED)
13672067733bSBram Moolenaar {
13682067733bSBram Moolenaar     source_cookie_T	*sp = (source_cookie_T *)cookie;
13692067733bSBram Moolenaar     char_u		*p;
13702067733bSBram Moolenaar     char_u		*line;
13712067733bSBram Moolenaar 
13722067733bSBram Moolenaar     if (*sp->nextline == NUL)
13732067733bSBram Moolenaar 	return NULL;
13742067733bSBram Moolenaar     p = vim_strchr(sp->nextline, '\n');
13752067733bSBram Moolenaar     if (p == NULL)
13762067733bSBram Moolenaar     {
13772067733bSBram Moolenaar 	line = vim_strsave(sp->nextline);
13782067733bSBram Moolenaar 	sp->nextline += STRLEN(sp->nextline);
13792067733bSBram Moolenaar     }
13802067733bSBram Moolenaar     else
13812067733bSBram Moolenaar     {
13822067733bSBram Moolenaar 	line = vim_strnsave(sp->nextline, p - sp->nextline);
13832067733bSBram Moolenaar 	sp->nextline = p + 1;
13842067733bSBram Moolenaar     }
13852067733bSBram Moolenaar     return line;
13862067733bSBram Moolenaar }
13872067733bSBram Moolenaar 
13882067733bSBram Moolenaar /*
13898a7d6542SBram Moolenaar  * Execute a function by "name".
13908a7d6542SBram Moolenaar  * This can be a builtin function, user function or a funcref.
13917eeefd4aSBram Moolenaar  * "iptr" can be used to replace the instruction with a more efficient one.
13928a7d6542SBram Moolenaar  */
13938a7d6542SBram Moolenaar     static int
call_eval_func(char_u * name,int argcount,ectx_T * ectx,isn_T * iptr)13942fecb531SBram Moolenaar call_eval_func(
13952fecb531SBram Moolenaar 	char_u	    *name,
13962fecb531SBram Moolenaar 	int	    argcount,
13972fecb531SBram Moolenaar 	ectx_T	    *ectx,
13982fecb531SBram Moolenaar 	isn_T	    *iptr)
13998a7d6542SBram Moolenaar {
14008a7d6542SBram Moolenaar     int	    called_emsg_before = called_emsg;
1401ed677f55SBram Moolenaar     int	    res;
14028a7d6542SBram Moolenaar 
1403b1b6f4deSBram Moolenaar     res = call_by_name(name, argcount, ectx, iptr, NULL);
1404ed677f55SBram Moolenaar     if (res == FAIL && called_emsg == called_emsg_before)
14058a7d6542SBram Moolenaar     {
14061df8b3fbSBram Moolenaar 	dictitem_T	*v;
14071df8b3fbSBram Moolenaar 
14081df8b3fbSBram Moolenaar 	v = find_var(name, NULL, FALSE);
14091df8b3fbSBram Moolenaar 	if (v == NULL)
14101df8b3fbSBram Moolenaar 	{
14111df8b3fbSBram Moolenaar 	    semsg(_(e_unknownfunc), name);
14128a7d6542SBram Moolenaar 	    return FAIL;
14138a7d6542SBram Moolenaar 	}
14141df8b3fbSBram Moolenaar 	if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC)
14151df8b3fbSBram Moolenaar 	{
14161df8b3fbSBram Moolenaar 	    semsg(_(e_unknownfunc), name);
14171df8b3fbSBram Moolenaar 	    return FAIL;
14181df8b3fbSBram Moolenaar 	}
14194c137214SBram Moolenaar 	return call_partial(&v->di_tv, argcount, ectx);
14201df8b3fbSBram Moolenaar     }
1421ed677f55SBram Moolenaar     return res;
14228a7d6542SBram Moolenaar }
14238a7d6542SBram Moolenaar 
14248a7d6542SBram Moolenaar /*
1425f112f30aSBram Moolenaar  * When a function reference is used, fill a partial with the information
1426f112f30aSBram Moolenaar  * needed, especially when it is used as a closure.
1427f112f30aSBram Moolenaar  */
1428cd45ed03SBram Moolenaar     int
fill_partial_and_closure(partial_T * pt,ufunc_T * ufunc,ectx_T * ectx)1429f112f30aSBram Moolenaar fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
1430f112f30aSBram Moolenaar {
1431f112f30aSBram Moolenaar     pt->pt_func = ufunc;
1432f112f30aSBram Moolenaar     pt->pt_refcount = 1;
1433f112f30aSBram Moolenaar 
14340d3de8cbSBram Moolenaar     if (ufunc->uf_flags & FC_CLOSURE)
1435f112f30aSBram Moolenaar     {
1436f112f30aSBram Moolenaar 	dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
1437f112f30aSBram Moolenaar 							  + ectx->ec_dfunc_idx;
1438f112f30aSBram Moolenaar 
1439c04f2a4cSBram Moolenaar 	// The closure may need to find arguments and local variables in the
1440c04f2a4cSBram Moolenaar 	// current stack.
14410186e586SBram Moolenaar 	pt->pt_outer.out_stack = &ectx->ec_stack;
14420186e586SBram Moolenaar 	pt->pt_outer.out_frame_idx = ectx->ec_frame_idx;
1443c04f2a4cSBram Moolenaar 	if (ectx->ec_outer_ref != NULL)
1444c04f2a4cSBram Moolenaar 	{
1445c04f2a4cSBram Moolenaar 	    // The current context already has a context, link to that one.
1446c04f2a4cSBram Moolenaar 	    pt->pt_outer.out_up = ectx->ec_outer_ref->or_outer;
1447c04f2a4cSBram Moolenaar 	    if (ectx->ec_outer_ref->or_partial != NULL)
1448c04f2a4cSBram Moolenaar 	    {
1449c04f2a4cSBram Moolenaar 		pt->pt_outer.out_up_partial = ectx->ec_outer_ref->or_partial;
1450c04f2a4cSBram Moolenaar 		++pt->pt_outer.out_up_partial->pt_refcount;
1451c04f2a4cSBram Moolenaar 	    }
1452c04f2a4cSBram Moolenaar 	}
1453f112f30aSBram Moolenaar 
1454c04f2a4cSBram Moolenaar 	// If this function returns and the closure is still being used, we
1455c04f2a4cSBram Moolenaar 	// need to make a copy of the context (arguments and local variables).
1456c04f2a4cSBram Moolenaar 	// Store a reference to the partial so we can handle that.
145735578168SBram Moolenaar 	if (GA_GROW_FAILS(&ectx->ec_funcrefs, 1))
1458f112f30aSBram Moolenaar 	{
1459f112f30aSBram Moolenaar 	    vim_free(pt);
1460f112f30aSBram Moolenaar 	    return FAIL;
1461f112f30aSBram Moolenaar 	}
1462c04f2a4cSBram Moolenaar 	// Extra variable keeps the count of closures created in the current
1463c04f2a4cSBram Moolenaar 	// function call.
1464f112f30aSBram Moolenaar 	++(((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx
1465f112f30aSBram Moolenaar 		       + STACK_FRAME_SIZE + dfunc->df_varcount)->vval.v_number;
1466f112f30aSBram Moolenaar 
1467f112f30aSBram Moolenaar 	((partial_T **)ectx->ec_funcrefs.ga_data)
1468f112f30aSBram Moolenaar 			       [ectx->ec_funcrefs.ga_len] = pt;
1469f112f30aSBram Moolenaar 	++pt->pt_refcount;
1470f112f30aSBram Moolenaar 	++ectx->ec_funcrefs.ga_len;
1471f112f30aSBram Moolenaar     }
14720d3de8cbSBram Moolenaar     ++ufunc->uf_refcount;
1473f112f30aSBram Moolenaar     return OK;
1474f112f30aSBram Moolenaar }
1475f112f30aSBram Moolenaar 
1476aacc966cSBram Moolenaar /*
1477aacc966cSBram Moolenaar  * Execute iptr->isn_arg.string as an Ex command.
1478aacc966cSBram Moolenaar  */
1479aacc966cSBram Moolenaar     static int
exec_command(isn_T * iptr)1480aacc966cSBram Moolenaar exec_command(isn_T *iptr)
1481aacc966cSBram Moolenaar {
1482aacc966cSBram Moolenaar     source_cookie_T cookie;
1483aacc966cSBram Moolenaar 
1484aacc966cSBram Moolenaar     SOURCING_LNUM = iptr->isn_lnum;
1485aacc966cSBram Moolenaar     // Pass getsourceline to get an error for a missing ":end"
1486aacc966cSBram Moolenaar     // command.
1487aacc966cSBram Moolenaar     CLEAR_FIELD(cookie);
1488aacc966cSBram Moolenaar     cookie.sourcing_lnum = iptr->isn_lnum - 1;
1489aacc966cSBram Moolenaar     if (do_cmdline(iptr->isn_arg.string,
1490aacc966cSBram Moolenaar 		getsourceline, &cookie,
1491aacc966cSBram Moolenaar 			     DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED) == FAIL
1492aacc966cSBram Moolenaar 		|| did_emsg)
1493aacc966cSBram Moolenaar 	return FAIL;
1494aacc966cSBram Moolenaar     return OK;
1495aacc966cSBram Moolenaar }
1496aacc966cSBram Moolenaar 
1497f18332fbSBram Moolenaar // used for v_instr of typval of VAR_INSTR
1498f18332fbSBram Moolenaar struct instr_S {
1499f18332fbSBram Moolenaar     ectx_T	*instr_ectx;
1500f18332fbSBram Moolenaar     isn_T	*instr_instr;
1501f18332fbSBram Moolenaar };
1502f18332fbSBram Moolenaar 
15034c137214SBram Moolenaar // used for substitute_instr
15044c137214SBram Moolenaar typedef struct subs_expr_S {
15054c137214SBram Moolenaar     ectx_T	*subs_ectx;
15064c137214SBram Moolenaar     isn_T	*subs_instr;
15074c137214SBram Moolenaar     int		subs_status;
15084c137214SBram Moolenaar } subs_expr_T;
15098a7d6542SBram Moolenaar 
15108a7d6542SBram Moolenaar // Get pointer to item in the stack.
15114c137214SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
15128a7d6542SBram Moolenaar 
15138a7d6542SBram Moolenaar // Get pointer to item at the bottom of the stack, -1 is the bottom.
15148a7d6542SBram Moolenaar #undef STACK_TV_BOT
15154c137214SBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx)
15168a7d6542SBram Moolenaar 
15171378fbc4SBram Moolenaar // Get pointer to a local variable on the stack.  Negative for arguments.
15184c137214SBram Moolenaar #define STACK_TV_VAR(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx + STACK_FRAME_SIZE + idx)
15198a7d6542SBram Moolenaar 
1520b69c6fb7SBram Moolenaar // Set when calling do_debug().
1521b69c6fb7SBram Moolenaar static ectx_T	*debug_context = NULL;
15226bc30b05SBram Moolenaar static int	debug_var_count;
1523b69c6fb7SBram Moolenaar 
1524b69c6fb7SBram Moolenaar /*
1525b69c6fb7SBram Moolenaar  * When debugging lookup "name" and return the typeval.
1526b69c6fb7SBram Moolenaar  * When not found return NULL.
1527b69c6fb7SBram Moolenaar  */
1528b69c6fb7SBram Moolenaar     typval_T *
lookup_debug_var(char_u * name)1529b69c6fb7SBram Moolenaar lookup_debug_var(char_u *name)
1530b69c6fb7SBram Moolenaar {
1531b69c6fb7SBram Moolenaar     int		    idx;
1532b69c6fb7SBram Moolenaar     dfunc_T	    *dfunc;
15336bc30b05SBram Moolenaar     ufunc_T	    *ufunc;
1534b69c6fb7SBram Moolenaar     ectx_T	    *ectx = debug_context;
15356bc30b05SBram Moolenaar     int		    varargs_off;
1536b69c6fb7SBram Moolenaar 
1537b69c6fb7SBram Moolenaar     if (ectx == NULL)
1538b69c6fb7SBram Moolenaar 	return NULL;
1539b69c6fb7SBram Moolenaar     dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
1540b69c6fb7SBram Moolenaar 
1541b69c6fb7SBram Moolenaar     // Go through the local variable names, from last to first.
15426bc30b05SBram Moolenaar     for (idx = debug_var_count - 1; idx >= 0; --idx)
1543b69c6fb7SBram Moolenaar     {
15446bc30b05SBram Moolenaar 	if (STRCMP(((char_u **)dfunc->df_var_names.ga_data)[idx], name) == 0)
1545b69c6fb7SBram Moolenaar 	    return STACK_TV_VAR(idx);
1546b69c6fb7SBram Moolenaar     }
1547b69c6fb7SBram Moolenaar 
15486bc30b05SBram Moolenaar     // Go through argument names.
15496bc30b05SBram Moolenaar     ufunc = dfunc->df_ufunc;
15506bc30b05SBram Moolenaar     varargs_off = ufunc->uf_va_name == NULL ? 0 : 1;
15516bc30b05SBram Moolenaar     for (idx = 0; idx < ufunc->uf_args.ga_len; ++idx)
15526bc30b05SBram Moolenaar 	if (STRCMP(((char_u **)(ufunc->uf_args.ga_data))[idx], name) == 0)
15536bc30b05SBram Moolenaar 	    return STACK_TV(ectx->ec_frame_idx - ufunc->uf_args.ga_len
15546bc30b05SBram Moolenaar 							  - varargs_off + idx);
15556bc30b05SBram Moolenaar     if (ufunc->uf_va_name != NULL && STRCMP(ufunc->uf_va_name, name) == 0)
15566bc30b05SBram Moolenaar 	return STACK_TV(ectx->ec_frame_idx - 1);
15576bc30b05SBram Moolenaar 
1558b69c6fb7SBram Moolenaar     return NULL;
1559b69c6fb7SBram Moolenaar }
1560b69c6fb7SBram Moolenaar 
156126a4484dSBram Moolenaar /*
156226a4484dSBram Moolenaar  * Return TRUE if there might be a breakpoint in "ufunc", which is when a
156326a4484dSBram Moolenaar  * breakpoint was set in that function or when there is any expression.
156426a4484dSBram Moolenaar  */
156526a4484dSBram Moolenaar     int
may_break_in_function(ufunc_T * ufunc)156626a4484dSBram Moolenaar may_break_in_function(ufunc_T *ufunc)
156726a4484dSBram Moolenaar {
156826a4484dSBram Moolenaar     return ufunc->uf_has_breakpoint || debug_has_expr_breakpoint();
156926a4484dSBram Moolenaar }
157026a4484dSBram Moolenaar 
15714cea536bSBram Moolenaar     static void
handle_debug(isn_T * iptr,ectx_T * ectx)15724cea536bSBram Moolenaar handle_debug(isn_T *iptr, ectx_T *ectx)
15734cea536bSBram Moolenaar {
15744cea536bSBram Moolenaar     char_u	*line;
15754cea536bSBram Moolenaar     ufunc_T	*ufunc = (((dfunc_T *)def_functions.ga_data)
15764cea536bSBram Moolenaar 					       + ectx->ec_dfunc_idx)->df_ufunc;
15774cea536bSBram Moolenaar     isn_T	*ni;
15784cea536bSBram Moolenaar     int		end_lnum = iptr->isn_lnum;
15794cea536bSBram Moolenaar     garray_T	ga;
15804cea536bSBram Moolenaar     int		lnum;
15814cea536bSBram Moolenaar 
15824f8f5428SBram Moolenaar     if (ex_nesting_level > debug_break_level)
15834f8f5428SBram Moolenaar     {
15844f8f5428SBram Moolenaar 	linenr_T breakpoint;
15854f8f5428SBram Moolenaar 
158626a4484dSBram Moolenaar 	if (!may_break_in_function(ufunc))
15874f8f5428SBram Moolenaar 	    return;
15884f8f5428SBram Moolenaar 
15894f8f5428SBram Moolenaar 	// check for the next breakpoint if needed
15904f8f5428SBram Moolenaar 	breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name,
15918cec9273SBram Moolenaar 					   iptr->isn_arg.debug.dbg_break_lnum);
15924f8f5428SBram Moolenaar 	if (breakpoint <= 0 || breakpoint > iptr->isn_lnum)
15934f8f5428SBram Moolenaar 	    return;
15944f8f5428SBram Moolenaar     }
15954f8f5428SBram Moolenaar 
15964cea536bSBram Moolenaar     SOURCING_LNUM = iptr->isn_lnum;
15974cea536bSBram Moolenaar     debug_context = ectx;
15988cec9273SBram Moolenaar     debug_var_count = iptr->isn_arg.debug.dbg_var_names_len;
15994cea536bSBram Moolenaar 
16004cea536bSBram Moolenaar     for (ni = iptr + 1; ni->isn_type != ISN_FINISH; ++ni)
16014cea536bSBram Moolenaar 	if (ni->isn_type == ISN_DEBUG
16024cea536bSBram Moolenaar 		  || ni->isn_type == ISN_RETURN
16034cea536bSBram Moolenaar 		  || ni->isn_type == ISN_RETURN_VOID)
16044cea536bSBram Moolenaar 	{
16054cea536bSBram Moolenaar 	    end_lnum = ni->isn_lnum;
16064cea536bSBram Moolenaar 	    break;
16074cea536bSBram Moolenaar 	}
16084cea536bSBram Moolenaar 
16094cea536bSBram Moolenaar     if (end_lnum > iptr->isn_lnum)
16104cea536bSBram Moolenaar     {
16114cea536bSBram Moolenaar 	ga_init2(&ga, sizeof(char_u *), 10);
16124cea536bSBram Moolenaar 	for (lnum = iptr->isn_lnum; lnum < end_lnum; ++lnum)
161359b50c3bSBram Moolenaar 	{
1614303215d6SBram Moolenaar 	    char_u *p = ((char_u **)ufunc->uf_lines.ga_data)[lnum - 1];
161559b50c3bSBram Moolenaar 
1616303215d6SBram Moolenaar 	    if (p == NULL)
1617303215d6SBram Moolenaar 		continue;  // left over from continuation line
1618303215d6SBram Moolenaar 	    p = skipwhite(p);
161959b50c3bSBram Moolenaar 	    if (*p == '#')
162059b50c3bSBram Moolenaar 		break;
162135578168SBram Moolenaar 	    if (GA_GROW_OK(&ga, 1))
162259b50c3bSBram Moolenaar 		((char_u **)(ga.ga_data))[ga.ga_len++] = p;
162359b50c3bSBram Moolenaar 	    if (STRNCMP(p, "def ", 4) == 0)
162459b50c3bSBram Moolenaar 		break;
162559b50c3bSBram Moolenaar 	}
16264cea536bSBram Moolenaar 	line = ga_concat_strings(&ga, "  ");
16274cea536bSBram Moolenaar 	vim_free(ga.ga_data);
16284cea536bSBram Moolenaar     }
16294cea536bSBram Moolenaar     else
16304cea536bSBram Moolenaar 	line = ((char_u **)ufunc->uf_lines.ga_data)[iptr->isn_lnum - 1];
16314cea536bSBram Moolenaar 
16326e969552SDominique Pelle     do_debug(line == NULL ? (char_u *)"[empty]" : line);
16334cea536bSBram Moolenaar     debug_context = NULL;
16344cea536bSBram Moolenaar 
16354cea536bSBram Moolenaar     if (end_lnum > iptr->isn_lnum)
16364cea536bSBram Moolenaar 	vim_free(line);
16374cea536bSBram Moolenaar }
16384cea536bSBram Moolenaar 
16394c137214SBram Moolenaar /*
16404c137214SBram Moolenaar  * Execute instructions in execution context "ectx".
16414c137214SBram Moolenaar  * Return OK or FAIL;
16424c137214SBram Moolenaar  */
16434c137214SBram Moolenaar     static int
exec_instructions(ectx_T * ectx)16444c137214SBram Moolenaar exec_instructions(ectx_T *ectx)
164525e0f586SBram Moolenaar {
1646cbe178e3SBram Moolenaar     int		ret = FAIL;
1647cbe178e3SBram Moolenaar     int		save_trylevel_at_start = ectx->ec_trylevel_at_start;
1648b1b6f4deSBram Moolenaar     int		dict_stack_len_at_start = dict_stack.ga_len;
1649f785aa13SBram Moolenaar 
165038a3bfa9SBram Moolenaar     // Start execution at the first instruction.
16514c137214SBram Moolenaar     ectx->ec_iidx = 0;
1652170fcfcfSBram Moolenaar 
1653ff65288aSBram Moolenaar     // Only catch exceptions in this instruction list.
1654ff65288aSBram Moolenaar     ectx->ec_trylevel_at_start = trylevel;
1655ff65288aSBram Moolenaar 
16568a7d6542SBram Moolenaar     for (;;)
16578a7d6542SBram Moolenaar     {
1658a7490192SBram Moolenaar 	static int  breakcheck_count = 0;  // using "static" makes it faster
16598a7d6542SBram Moolenaar 	isn_T	    *iptr;
1660a7490192SBram Moolenaar 	typval_T    *tv;
166120431c9dSBram Moolenaar 
16625a9e5845SDominique Pelle 	if (unlikely(++breakcheck_count >= 100))
1663270d0388SBram Moolenaar 	{
1664270d0388SBram Moolenaar 	    line_breakcheck();
1665270d0388SBram Moolenaar 	    breakcheck_count = 0;
1666270d0388SBram Moolenaar 	}
16675a9e5845SDominique Pelle 	if (unlikely(got_int))
166820431c9dSBram Moolenaar 	{
166920431c9dSBram Moolenaar 	    // Turn CTRL-C into an exception.
167020431c9dSBram Moolenaar 	    got_int = FALSE;
167197acfc78SBram Moolenaar 	    if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
1672cbe178e3SBram Moolenaar 		goto theend;
167320431c9dSBram Moolenaar 	    did_throw = TRUE;
167420431c9dSBram Moolenaar 	}
16758a7d6542SBram Moolenaar 
16765a9e5845SDominique Pelle 	if (unlikely(did_emsg && msg_list != NULL && *msg_list != NULL))
1677a26b9700SBram Moolenaar 	{
1678a26b9700SBram Moolenaar 	    // Turn an error message into an exception.
1679a26b9700SBram Moolenaar 	    did_emsg = FALSE;
1680a26b9700SBram Moolenaar 	    if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL)
1681cbe178e3SBram Moolenaar 		goto theend;
1682a26b9700SBram Moolenaar 	    did_throw = TRUE;
1683a26b9700SBram Moolenaar 	    *msg_list = NULL;
1684a26b9700SBram Moolenaar 	}
1685a26b9700SBram Moolenaar 
16865a9e5845SDominique Pelle 	if (unlikely(did_throw))
16878a7d6542SBram Moolenaar 	{
16884c137214SBram Moolenaar 	    garray_T	*trystack = &ectx->ec_trystack;
168920431c9dSBram Moolenaar 	    trycmd_T    *trycmd = NULL;
1690d3d8feebSBram Moolenaar 	    int		index = trystack->ga_len;
16918a7d6542SBram Moolenaar 
16928a7d6542SBram Moolenaar 	    // An exception jumps to the first catch, finally, or returns from
16938a7d6542SBram Moolenaar 	    // the current function.
1694d3d8feebSBram Moolenaar 	    while (index > 0)
1695d3d8feebSBram Moolenaar 	    {
1696d3d8feebSBram Moolenaar 		trycmd = ((trycmd_T *)trystack->ga_data) + index - 1;
1697834193afSBram Moolenaar 		if (!trycmd->tcd_in_catch || trycmd->tcd_finally_idx != 0)
1698d3d8feebSBram Moolenaar 		    break;
1699d3d8feebSBram Moolenaar 		// In the catch and finally block of this try we have to go up
1700d3d8feebSBram Moolenaar 		// one level.
1701d3d8feebSBram Moolenaar 		--index;
1702d3d8feebSBram Moolenaar 		trycmd = NULL;
1703d3d8feebSBram Moolenaar 	    }
17044c137214SBram Moolenaar 	    if (trycmd != NULL && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
17058a7d6542SBram Moolenaar 	    {
1706834193afSBram Moolenaar 		if (trycmd->tcd_in_catch)
1707834193afSBram Moolenaar 		{
1708834193afSBram Moolenaar 		    // exception inside ":catch", jump to ":finally" once
1709834193afSBram Moolenaar 		    ectx->ec_iidx = trycmd->tcd_finally_idx;
1710834193afSBram Moolenaar 		    trycmd->tcd_finally_idx = 0;
1711834193afSBram Moolenaar 		}
1712834193afSBram Moolenaar 		else
1713834193afSBram Moolenaar 		    // jump to first ":catch"
17144c137214SBram Moolenaar 		    ectx->ec_iidx = trycmd->tcd_catch_idx;
1715834193afSBram Moolenaar 		trycmd->tcd_in_catch = TRUE;
1716d3d8feebSBram Moolenaar 		did_throw = FALSE;  // don't come back here until :endtry
1717d3d8feebSBram Moolenaar 		trycmd->tcd_did_throw = TRUE;
17188a7d6542SBram Moolenaar 	    }
17198a7d6542SBram Moolenaar 	    else
17208a7d6542SBram Moolenaar 	    {
1721cdd70f09SBram Moolenaar 		// Not inside try or need to return from current functions.
1722cdd70f09SBram Moolenaar 		// Push a dummy return value.
172335578168SBram Moolenaar 		if (GA_GROW_FAILS(&ectx->ec_stack, 1))
1724cbe178e3SBram Moolenaar 		    goto theend;
17258a7d6542SBram Moolenaar 		tv = STACK_TV_BOT(0);
17268a7d6542SBram Moolenaar 		tv->v_type = VAR_NUMBER;
17278a7d6542SBram Moolenaar 		tv->vval.v_number = 0;
17284c137214SBram Moolenaar 		++ectx->ec_stack.ga_len;
17294c137214SBram Moolenaar 		if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
1730cdd70f09SBram Moolenaar 		{
1731cdd70f09SBram Moolenaar 		    // At the toplevel we are done.
1732257cc5eeSBram Moolenaar 		    need_rethrow = TRUE;
17334c137214SBram Moolenaar 		    if (handle_closure_in_use(ectx, FALSE) == FAIL)
1734cbe178e3SBram Moolenaar 			goto theend;
17358a7d6542SBram Moolenaar 		    goto done;
17368a7d6542SBram Moolenaar 		}
17378a7d6542SBram Moolenaar 
17384c137214SBram Moolenaar 		if (func_return(ectx) == FAIL)
1739cbe178e3SBram Moolenaar 		    goto theend;
17408a7d6542SBram Moolenaar 	    }
17418a7d6542SBram Moolenaar 	    continue;
17428a7d6542SBram Moolenaar 	}
17438a7d6542SBram Moolenaar 
17444c137214SBram Moolenaar 	iptr = &ectx->ec_instr[ectx->ec_iidx++];
17458a7d6542SBram Moolenaar 	switch (iptr->isn_type)
17468a7d6542SBram Moolenaar 	{
17478a7d6542SBram Moolenaar 	    // execute Ex command line
17488a7d6542SBram Moolenaar 	    case ISN_EXEC:
1749aacc966cSBram Moolenaar 		if (exec_command(iptr) == FAIL)
1750eeece9e4SBram Moolenaar 		    goto on_error;
17518a7d6542SBram Moolenaar 		break;
17528a7d6542SBram Moolenaar 
17532067733bSBram Moolenaar 	    // execute Ex command line split at NL characters.
17542067733bSBram Moolenaar 	    case ISN_EXEC_SPLIT:
17552067733bSBram Moolenaar 		{
17562067733bSBram Moolenaar 		    source_cookie_T cookie;
1757518df27eSBram Moolenaar 		    char_u	    *line;
17582067733bSBram Moolenaar 
17592067733bSBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
17602067733bSBram Moolenaar 		    CLEAR_FIELD(cookie);
17612067733bSBram Moolenaar 		    cookie.sourcing_lnum = iptr->isn_lnum - 1;
17622067733bSBram Moolenaar 		    cookie.nextline = iptr->isn_arg.string;
1763518df27eSBram Moolenaar 		    line = get_split_sourceline(0, &cookie, 0, 0);
1764518df27eSBram Moolenaar 		    if (do_cmdline(line,
17652067733bSBram Moolenaar 				get_split_sourceline, &cookie,
17662067733bSBram Moolenaar 				   DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED)
17672067733bSBram Moolenaar 									== FAIL
17682067733bSBram Moolenaar 				|| did_emsg)
1769518df27eSBram Moolenaar 		    {
1770518df27eSBram Moolenaar 			vim_free(line);
17712067733bSBram Moolenaar 			goto on_error;
17722067733bSBram Moolenaar 		    }
1773518df27eSBram Moolenaar 		    vim_free(line);
1774518df27eSBram Moolenaar 		}
17752067733bSBram Moolenaar 		break;
17762067733bSBram Moolenaar 
17773b1373b1SBram Moolenaar 	    // Evaluate an expression with legacy syntax, push it onto the
17783b1373b1SBram Moolenaar 	    // stack.
17793b1373b1SBram Moolenaar 	    case ISN_LEGACY_EVAL:
17803b1373b1SBram Moolenaar 		{
17813b1373b1SBram Moolenaar 		    char_u  *arg = iptr->isn_arg.string;
17823b1373b1SBram Moolenaar 		    int	    res;
17833b1373b1SBram Moolenaar 		    int	    save_flags = cmdmod.cmod_flags;
17843b1373b1SBram Moolenaar 
178535578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
1786cbe178e3SBram Moolenaar 			goto theend;
17873b1373b1SBram Moolenaar 		    tv = STACK_TV_BOT(0);
17883b1373b1SBram Moolenaar 		    init_tv(tv);
17893b1373b1SBram Moolenaar 		    cmdmod.cmod_flags |= CMOD_LEGACY;
17903b1373b1SBram Moolenaar 		    res = eval0(arg, tv, NULL, &EVALARG_EVALUATE);
17913b1373b1SBram Moolenaar 		    cmdmod.cmod_flags = save_flags;
17923b1373b1SBram Moolenaar 		    if (res == FAIL)
17933b1373b1SBram Moolenaar 			goto on_error;
17943b1373b1SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
17953b1373b1SBram Moolenaar 		}
17963b1373b1SBram Moolenaar 		break;
17973b1373b1SBram Moolenaar 
1798f18332fbSBram Moolenaar 	    // push typeval VAR_INSTR with instructions to be executed
1799f18332fbSBram Moolenaar 	    case ISN_INSTR:
1800f18332fbSBram Moolenaar 		{
180135578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
1802cbe178e3SBram Moolenaar 			goto theend;
1803f18332fbSBram Moolenaar 		    tv = STACK_TV_BOT(0);
1804f18332fbSBram Moolenaar 		    tv->vval.v_instr = ALLOC_ONE(instr_T);
1805f18332fbSBram Moolenaar 		    if (tv->vval.v_instr == NULL)
1806f18332fbSBram Moolenaar 			goto on_error;
1807f18332fbSBram Moolenaar 		    ++ectx->ec_stack.ga_len;
1808f18332fbSBram Moolenaar 
1809f18332fbSBram Moolenaar 		    tv->v_type = VAR_INSTR;
1810f18332fbSBram Moolenaar 		    tv->vval.v_instr->instr_ectx = ectx;
1811f18332fbSBram Moolenaar 		    tv->vval.v_instr->instr_instr = iptr->isn_arg.instr;
1812f18332fbSBram Moolenaar 		}
1813f18332fbSBram Moolenaar 		break;
1814f18332fbSBram Moolenaar 
18154c137214SBram Moolenaar 	    // execute :substitute with an expression
18164c137214SBram Moolenaar 	    case ISN_SUBSTITUTE:
18174c137214SBram Moolenaar 		{
18184c137214SBram Moolenaar 		    subs_T		*subs = &iptr->isn_arg.subs;
18194c137214SBram Moolenaar 		    source_cookie_T	cookie;
18204c137214SBram Moolenaar 		    struct subs_expr_S	*save_instr = substitute_instr;
18214c137214SBram Moolenaar 		    struct subs_expr_S	subs_instr;
18224c137214SBram Moolenaar 		    int			res;
18234c137214SBram Moolenaar 
18244c137214SBram Moolenaar 		    subs_instr.subs_ectx = ectx;
18254c137214SBram Moolenaar 		    subs_instr.subs_instr = subs->subs_instr;
18264c137214SBram Moolenaar 		    subs_instr.subs_status = OK;
18274c137214SBram Moolenaar 		    substitute_instr = &subs_instr;
18284c137214SBram Moolenaar 
18294c137214SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
18304c137214SBram Moolenaar 		    // This is very much like ISN_EXEC
18314c137214SBram Moolenaar 		    CLEAR_FIELD(cookie);
18324c137214SBram Moolenaar 		    cookie.sourcing_lnum = iptr->isn_lnum - 1;
18334c137214SBram Moolenaar 		    res = do_cmdline(subs->subs_cmd,
18344c137214SBram Moolenaar 				getsourceline, &cookie,
18354c137214SBram Moolenaar 				   DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
18364c137214SBram Moolenaar 		    substitute_instr = save_instr;
18374c137214SBram Moolenaar 
18384c137214SBram Moolenaar 		    if (res == FAIL || did_emsg
18394c137214SBram Moolenaar 					     || subs_instr.subs_status == FAIL)
18404c137214SBram Moolenaar 			goto on_error;
18414c137214SBram Moolenaar 		}
18424c137214SBram Moolenaar 		break;
18434c137214SBram Moolenaar 
18444c137214SBram Moolenaar 	    case ISN_FINISH:
18454c137214SBram Moolenaar 		goto done;
18464c137214SBram Moolenaar 
18472d1c57edSBram Moolenaar 	    case ISN_REDIRSTART:
18482d1c57edSBram Moolenaar 		// create a dummy entry for var_redir_str()
18492d1c57edSBram Moolenaar 		if (alloc_redir_lval() == FAIL)
18502d1c57edSBram Moolenaar 		    goto on_error;
18512d1c57edSBram Moolenaar 
18522d1c57edSBram Moolenaar 		// The output is stored in growarray "redir_ga" until
18532d1c57edSBram Moolenaar 		// redirection ends.
18542d1c57edSBram Moolenaar 		init_redir_ga();
18552d1c57edSBram Moolenaar 		redir_vname = 1;
18562d1c57edSBram Moolenaar 		break;
18572d1c57edSBram Moolenaar 
18582d1c57edSBram Moolenaar 	    case ISN_REDIREND:
18592d1c57edSBram Moolenaar 		{
18602d1c57edSBram Moolenaar 		    char_u *res = get_clear_redir_ga();
18612d1c57edSBram Moolenaar 
18622d1c57edSBram Moolenaar 		    // End redirection, put redirected text on the stack.
18632d1c57edSBram Moolenaar 		    clear_redir_lval();
18642d1c57edSBram Moolenaar 		    redir_vname = 0;
18652d1c57edSBram Moolenaar 
186635578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
18672d1c57edSBram Moolenaar 		    {
18682d1c57edSBram Moolenaar 			vim_free(res);
1869cbe178e3SBram Moolenaar 			goto theend;
18702d1c57edSBram Moolenaar 		    }
18712d1c57edSBram Moolenaar 		    tv = STACK_TV_BOT(0);
18722d1c57edSBram Moolenaar 		    tv->v_type = VAR_STRING;
18732d1c57edSBram Moolenaar 		    tv->vval.v_string = res;
18742d1c57edSBram Moolenaar 		    ++ectx->ec_stack.ga_len;
18752d1c57edSBram Moolenaar 		}
18762d1c57edSBram Moolenaar 		break;
18772d1c57edSBram Moolenaar 
18785f7d4c04SBram Moolenaar 	    case ISN_CEXPR_AUCMD:
1879b7c97815SBram Moolenaar #ifdef FEAT_QUICKFIX
18805f7d4c04SBram Moolenaar 		if (trigger_cexpr_autocmd(iptr->isn_arg.number) == FAIL)
18815f7d4c04SBram Moolenaar 		    goto on_error;
1882b7c97815SBram Moolenaar #endif
18835f7d4c04SBram Moolenaar 		break;
18845f7d4c04SBram Moolenaar 
18855f7d4c04SBram Moolenaar 	    case ISN_CEXPR_CORE:
1886b7c97815SBram Moolenaar #ifdef FEAT_QUICKFIX
18875f7d4c04SBram Moolenaar 		{
18885f7d4c04SBram Moolenaar 		    exarg_T ea;
18895f7d4c04SBram Moolenaar 		    int	    res;
18905f7d4c04SBram Moolenaar 
18915f7d4c04SBram Moolenaar 		    CLEAR_FIELD(ea);
18925f7d4c04SBram Moolenaar 		    ea.cmdidx = iptr->isn_arg.cexpr.cexpr_ref->cer_cmdidx;
18935f7d4c04SBram Moolenaar 		    ea.forceit = iptr->isn_arg.cexpr.cexpr_ref->cer_forceit;
18945f7d4c04SBram Moolenaar 		    ea.cmdlinep = &iptr->isn_arg.cexpr.cexpr_ref->cer_cmdline;
18955f7d4c04SBram Moolenaar 		    --ectx->ec_stack.ga_len;
18965f7d4c04SBram Moolenaar 		    tv = STACK_TV_BOT(0);
18975f7d4c04SBram Moolenaar 		    res = cexpr_core(&ea, tv);
18985f7d4c04SBram Moolenaar 		    clear_tv(tv);
18995f7d4c04SBram Moolenaar 		    if (res == FAIL)
19005f7d4c04SBram Moolenaar 			goto on_error;
19015f7d4c04SBram Moolenaar 		}
1902b7c97815SBram Moolenaar #endif
19035f7d4c04SBram Moolenaar 		break;
19045f7d4c04SBram Moolenaar 
1905cfe435d7SBram Moolenaar 	    // execute Ex command from pieces on the stack
1906cfe435d7SBram Moolenaar 	    case ISN_EXECCONCAT:
1907cfe435d7SBram Moolenaar 		{
1908cfe435d7SBram Moolenaar 		    int	    count = iptr->isn_arg.number;
19097f6f56f4SBram Moolenaar 		    size_t  len = 0;
1910cfe435d7SBram Moolenaar 		    int	    pass;
1911cfe435d7SBram Moolenaar 		    int	    i;
1912cfe435d7SBram Moolenaar 		    char_u  *cmd = NULL;
1913cfe435d7SBram Moolenaar 		    char_u  *str;
1914cfe435d7SBram Moolenaar 
1915cfe435d7SBram Moolenaar 		    for (pass = 1; pass <= 2; ++pass)
1916cfe435d7SBram Moolenaar 		    {
1917cfe435d7SBram Moolenaar 			for (i = 0; i < count; ++i)
1918cfe435d7SBram Moolenaar 			{
1919cfe435d7SBram Moolenaar 			    tv = STACK_TV_BOT(i - count);
1920cfe435d7SBram Moolenaar 			    str = tv->vval.v_string;
1921cfe435d7SBram Moolenaar 			    if (str != NULL && *str != NUL)
1922cfe435d7SBram Moolenaar 			    {
1923cfe435d7SBram Moolenaar 				if (pass == 2)
1924cfe435d7SBram Moolenaar 				    STRCPY(cmd + len, str);
1925cfe435d7SBram Moolenaar 				len += STRLEN(str);
1926cfe435d7SBram Moolenaar 			    }
1927cfe435d7SBram Moolenaar 			    if (pass == 2)
1928cfe435d7SBram Moolenaar 				clear_tv(tv);
1929cfe435d7SBram Moolenaar 			}
1930cfe435d7SBram Moolenaar 			if (pass == 1)
1931cfe435d7SBram Moolenaar 			{
1932cfe435d7SBram Moolenaar 			    cmd = alloc(len + 1);
19335a9e5845SDominique Pelle 			    if (unlikely(cmd == NULL))
1934cbe178e3SBram Moolenaar 				goto theend;
1935cfe435d7SBram Moolenaar 			    len = 0;
1936cfe435d7SBram Moolenaar 			}
1937cfe435d7SBram Moolenaar 		    }
1938cfe435d7SBram Moolenaar 
19396378c4feSBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
1940cfe435d7SBram Moolenaar 		    do_cmdline_cmd(cmd);
1941cfe435d7SBram Moolenaar 		    vim_free(cmd);
1942cfe435d7SBram Moolenaar 		}
1943cfe435d7SBram Moolenaar 		break;
1944cfe435d7SBram Moolenaar 
19458a7d6542SBram Moolenaar 	    // execute :echo {string} ...
19468a7d6542SBram Moolenaar 	    case ISN_ECHO:
19478a7d6542SBram Moolenaar 		{
19488a7d6542SBram Moolenaar 		    int count = iptr->isn_arg.echo.echo_count;
19498a7d6542SBram Moolenaar 		    int	atstart = TRUE;
19508a7d6542SBram Moolenaar 		    int needclr = TRUE;
19514c137214SBram Moolenaar 		    int	idx;
19528a7d6542SBram Moolenaar 
19538a7d6542SBram Moolenaar 		    for (idx = 0; idx < count; ++idx)
19548a7d6542SBram Moolenaar 		    {
19558a7d6542SBram Moolenaar 			tv = STACK_TV_BOT(idx - count);
19568a7d6542SBram Moolenaar 			echo_one(tv, iptr->isn_arg.echo.echo_with_white,
19578a7d6542SBram Moolenaar 							   &atstart, &needclr);
19588a7d6542SBram Moolenaar 			clear_tv(tv);
19598a7d6542SBram Moolenaar 		    }
1960e0807ea4SBram Moolenaar 		    if (needclr)
1961e0807ea4SBram Moolenaar 			msg_clr_eos();
19624c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= count;
19638a7d6542SBram Moolenaar 		}
19648a7d6542SBram Moolenaar 		break;
19658a7d6542SBram Moolenaar 
1966f93c7feaSBram Moolenaar 	    // :execute {string} ...
1967f93c7feaSBram Moolenaar 	    // :echomsg {string} ...
19687de62623SBram Moolenaar 	    // :echoconsole {string} ...
1969f93c7feaSBram Moolenaar 	    // :echoerr {string} ...
1970ad39c094SBram Moolenaar 	    case ISN_EXECUTE:
1971f93c7feaSBram Moolenaar 	    case ISN_ECHOMSG:
19727de62623SBram Moolenaar 	    case ISN_ECHOCONSOLE:
1973f93c7feaSBram Moolenaar 	    case ISN_ECHOERR:
1974ad39c094SBram Moolenaar 		{
1975ad39c094SBram Moolenaar 		    int		count = iptr->isn_arg.number;
1976ad39c094SBram Moolenaar 		    garray_T	ga;
1977ad39c094SBram Moolenaar 		    char_u	buf[NUMBUFLEN];
1978ad39c094SBram Moolenaar 		    char_u	*p;
1979ad39c094SBram Moolenaar 		    int		len;
1980ad39c094SBram Moolenaar 		    int		failed = FALSE;
19814c137214SBram Moolenaar 		    int		idx;
1982ad39c094SBram Moolenaar 
1983ad39c094SBram Moolenaar 		    ga_init2(&ga, 1, 80);
1984ad39c094SBram Moolenaar 		    for (idx = 0; idx < count; ++idx)
1985ad39c094SBram Moolenaar 		    {
1986ad39c094SBram Moolenaar 			tv = STACK_TV_BOT(idx - count);
1987e5abf7afSBram Moolenaar 			if (iptr->isn_type == ISN_EXECUTE)
1988e5abf7afSBram Moolenaar 			{
1989e5abf7afSBram Moolenaar 			    if (tv->v_type == VAR_CHANNEL
1990e5abf7afSBram Moolenaar 						      || tv->v_type == VAR_JOB)
1991ad39c094SBram Moolenaar 			    {
19927517ffdbSBram Moolenaar 				SOURCING_LNUM = iptr->isn_lnum;
199368db996bSBram Moolenaar 				semsg(_(e_using_invalid_value_as_string_str),
199468db996bSBram Moolenaar 						    vartype_name(tv->v_type));
1995ad39c094SBram Moolenaar 				break;
1996ad39c094SBram Moolenaar 			    }
1997ad39c094SBram Moolenaar 			    else
1998ad39c094SBram Moolenaar 				p = tv_get_string_buf(tv, buf);
1999e5abf7afSBram Moolenaar 			}
2000e5abf7afSBram Moolenaar 			else
2001e5abf7afSBram Moolenaar 			    p = tv_stringify(tv, buf);
2002ad39c094SBram Moolenaar 
2003ad39c094SBram Moolenaar 			len = (int)STRLEN(p);
200435578168SBram Moolenaar 			if (GA_GROW_FAILS(&ga, len + 2))
2005ad39c094SBram Moolenaar 			    failed = TRUE;
2006ad39c094SBram Moolenaar 			else
2007ad39c094SBram Moolenaar 			{
2008ad39c094SBram Moolenaar 			    if (ga.ga_len > 0)
2009ad39c094SBram Moolenaar 				((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
2010ad39c094SBram Moolenaar 			    STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
2011ad39c094SBram Moolenaar 			    ga.ga_len += len;
2012ad39c094SBram Moolenaar 			}
2013ad39c094SBram Moolenaar 			clear_tv(tv);
2014ad39c094SBram Moolenaar 		    }
20154c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= count;
2016e5abf7afSBram Moolenaar 		    if (failed)
2017c71ee829SBram Moolenaar 		    {
2018c71ee829SBram Moolenaar 			ga_clear(&ga);
2019e5abf7afSBram Moolenaar 			goto on_error;
2020c71ee829SBram Moolenaar 		    }
2021ad39c094SBram Moolenaar 
2022e5abf7afSBram Moolenaar 		    if (ga.ga_data != NULL)
2023f93c7feaSBram Moolenaar 		    {
2024f93c7feaSBram Moolenaar 			if (iptr->isn_type == ISN_EXECUTE)
2025430deb19SBram Moolenaar 			{
2026430deb19SBram Moolenaar 			    SOURCING_LNUM = iptr->isn_lnum;
2027ad39c094SBram Moolenaar 			    do_cmdline_cmd((char_u *)ga.ga_data);
2028eeece9e4SBram Moolenaar 			    if (did_emsg)
2029c71ee829SBram Moolenaar 			    {
2030c71ee829SBram Moolenaar 				ga_clear(&ga);
2031eeece9e4SBram Moolenaar 				goto on_error;
2032430deb19SBram Moolenaar 			    }
2033c71ee829SBram Moolenaar 			}
2034f93c7feaSBram Moolenaar 			else
2035f93c7feaSBram Moolenaar 			{
2036f93c7feaSBram Moolenaar 			    msg_sb_eol();
2037f93c7feaSBram Moolenaar 			    if (iptr->isn_type == ISN_ECHOMSG)
2038f93c7feaSBram Moolenaar 			    {
2039f93c7feaSBram Moolenaar 				msg_attr(ga.ga_data, echo_attr);
2040f93c7feaSBram Moolenaar 				out_flush();
2041f93c7feaSBram Moolenaar 			    }
20427de62623SBram Moolenaar 			    else if (iptr->isn_type == ISN_ECHOCONSOLE)
20437de62623SBram Moolenaar 			    {
20447de62623SBram Moolenaar 				ui_write(ga.ga_data, (int)STRLEN(ga.ga_data),
20457de62623SBram Moolenaar 									 TRUE);
20467de62623SBram Moolenaar 				ui_write((char_u *)"\r\n", 2, TRUE);
20477de62623SBram Moolenaar 			    }
2048f93c7feaSBram Moolenaar 			    else
2049f93c7feaSBram Moolenaar 			    {
2050f93c7feaSBram Moolenaar 				SOURCING_LNUM = iptr->isn_lnum;
2051f93c7feaSBram Moolenaar 				emsg(ga.ga_data);
2052f93c7feaSBram Moolenaar 			    }
2053f93c7feaSBram Moolenaar 			}
2054f93c7feaSBram Moolenaar 		    }
2055ad39c094SBram Moolenaar 		    ga_clear(&ga);
2056ad39c094SBram Moolenaar 		}
2057ad39c094SBram Moolenaar 		break;
2058ad39c094SBram Moolenaar 
20598a7d6542SBram Moolenaar 	    // load local variable or argument
20608a7d6542SBram Moolenaar 	    case ISN_LOAD:
206135578168SBram Moolenaar 		if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2062cbe178e3SBram Moolenaar 		    goto theend;
20638a7d6542SBram Moolenaar 		copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
20644c137214SBram Moolenaar 		++ectx->ec_stack.ga_len;
20658a7d6542SBram Moolenaar 		break;
20668a7d6542SBram Moolenaar 
20678a7d6542SBram Moolenaar 	    // load v: variable
20688a7d6542SBram Moolenaar 	    case ISN_LOADV:
206935578168SBram Moolenaar 		if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2070cbe178e3SBram Moolenaar 		    goto theend;
20718a7d6542SBram Moolenaar 		copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
20724c137214SBram Moolenaar 		++ectx->ec_stack.ga_len;
20738a7d6542SBram Moolenaar 		break;
20748a7d6542SBram Moolenaar 
2075b283a8a6SBram Moolenaar 	    // load s: variable in Vim9 script
20768a7d6542SBram Moolenaar 	    case ISN_LOADSCRIPT:
20778a7d6542SBram Moolenaar 		{
20784aab88d9SBram Moolenaar 		    scriptref_T	*sref = iptr->isn_arg.script.scriptref;
20798a7d6542SBram Moolenaar 		    svar_T	 *sv;
20808a7d6542SBram Moolenaar 
20816db660beSBram Moolenaar 		    sv = get_script_svar(sref, ectx->ec_dfunc_idx);
208207a65d26SBram Moolenaar 		    if (sv == NULL)
2083cbe178e3SBram Moolenaar 			goto theend;
20843beaf9cdSBram Moolenaar 		    allocate_if_null(sv->sv_tv);
208535578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2086cbe178e3SBram Moolenaar 			goto theend;
20878a7d6542SBram Moolenaar 		    copy_tv(sv->sv_tv, STACK_TV_BOT(0));
20884c137214SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
20898a7d6542SBram Moolenaar 		}
20908a7d6542SBram Moolenaar 		break;
20918a7d6542SBram Moolenaar 
20928a7d6542SBram Moolenaar 	    // load s: variable in old script
20938a7d6542SBram Moolenaar 	    case ISN_LOADS:
20948a7d6542SBram Moolenaar 		{
2095b283a8a6SBram Moolenaar 		    hashtab_T	*ht = &SCRIPT_VARS(
2096b283a8a6SBram Moolenaar 					       iptr->isn_arg.loadstore.ls_sid);
2097b283a8a6SBram Moolenaar 		    char_u	*name = iptr->isn_arg.loadstore.ls_name;
20988a7d6542SBram Moolenaar 		    dictitem_T	*di = find_var_in_ht(ht, 0, name, TRUE);
20990bbf722aSBram Moolenaar 
21008a7d6542SBram Moolenaar 		    if (di == NULL)
21018a7d6542SBram Moolenaar 		    {
21027517ffdbSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
2103451c2e35SBram Moolenaar 			semsg(_(e_undefined_variable_str), name);
2104f0b9f43cSBram Moolenaar 			goto on_error;
21058a7d6542SBram Moolenaar 		    }
21068a7d6542SBram Moolenaar 		    else
21078a7d6542SBram Moolenaar 		    {
210835578168SBram Moolenaar 			if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2109cbe178e3SBram Moolenaar 			    goto theend;
21108a7d6542SBram Moolenaar 			copy_tv(&di->di_tv, STACK_TV_BOT(0));
21114c137214SBram Moolenaar 			++ectx->ec_stack.ga_len;
21128a7d6542SBram Moolenaar 		    }
21138a7d6542SBram Moolenaar 		}
21148a7d6542SBram Moolenaar 		break;
21158a7d6542SBram Moolenaar 
2116d3aac291SBram Moolenaar 	    // load g:/b:/w:/t: variable
21178a7d6542SBram Moolenaar 	    case ISN_LOADG:
2118d3aac291SBram Moolenaar 	    case ISN_LOADB:
2119d3aac291SBram Moolenaar 	    case ISN_LOADW:
2120d3aac291SBram Moolenaar 	    case ISN_LOADT:
21218a7d6542SBram Moolenaar 		{
2122d3aac291SBram Moolenaar 		    dictitem_T *di = NULL;
2123d3aac291SBram Moolenaar 		    hashtab_T *ht = NULL;
2124d3aac291SBram Moolenaar 		    char namespace;
21252f8ce0aeSBram Moolenaar 
2126d3aac291SBram Moolenaar 		    switch (iptr->isn_type)
2127d3aac291SBram Moolenaar 		    {
2128d3aac291SBram Moolenaar 			case ISN_LOADG:
2129d3aac291SBram Moolenaar 			    ht = get_globvar_ht();
2130d3aac291SBram Moolenaar 			    namespace = 'g';
2131d3aac291SBram Moolenaar 			    break;
2132d3aac291SBram Moolenaar 			case ISN_LOADB:
2133d3aac291SBram Moolenaar 			    ht = &curbuf->b_vars->dv_hashtab;
2134d3aac291SBram Moolenaar 			    namespace = 'b';
2135d3aac291SBram Moolenaar 			    break;
2136d3aac291SBram Moolenaar 			case ISN_LOADW:
2137d3aac291SBram Moolenaar 			    ht = &curwin->w_vars->dv_hashtab;
2138d3aac291SBram Moolenaar 			    namespace = 'w';
2139d3aac291SBram Moolenaar 			    break;
2140d3aac291SBram Moolenaar 			case ISN_LOADT:
2141d3aac291SBram Moolenaar 			    ht = &curtab->tp_vars->dv_hashtab;
2142d3aac291SBram Moolenaar 			    namespace = 't';
2143d3aac291SBram Moolenaar 			    break;
2144d3aac291SBram Moolenaar 			default:  // Cannot reach here
2145cbe178e3SBram Moolenaar 			    goto theend;
2146d3aac291SBram Moolenaar 		    }
2147d3aac291SBram Moolenaar 		    di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
21480bbf722aSBram Moolenaar 
21498a7d6542SBram Moolenaar 		    if (di == NULL)
21508a7d6542SBram Moolenaar 		    {
21517517ffdbSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
2152451c2e35SBram Moolenaar 			semsg(_(e_undefined_variable_char_str),
2153d3aac291SBram Moolenaar 					     namespace, iptr->isn_arg.string);
2154f0b9f43cSBram Moolenaar 			goto on_error;
21558a7d6542SBram Moolenaar 		    }
21568a7d6542SBram Moolenaar 		    else
21578a7d6542SBram Moolenaar 		    {
215835578168SBram Moolenaar 			if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2159cbe178e3SBram Moolenaar 			    goto theend;
21608a7d6542SBram Moolenaar 			copy_tv(&di->di_tv, STACK_TV_BOT(0));
21614c137214SBram Moolenaar 			++ectx->ec_stack.ga_len;
21628a7d6542SBram Moolenaar 		    }
21638a7d6542SBram Moolenaar 		}
21648a7d6542SBram Moolenaar 		break;
21658a7d6542SBram Moolenaar 
216603290b84SBram Moolenaar 	    // load autoload variable
216703290b84SBram Moolenaar 	    case ISN_LOADAUTO:
216803290b84SBram Moolenaar 		{
216903290b84SBram Moolenaar 		    char_u *name = iptr->isn_arg.string;
217003290b84SBram Moolenaar 
217135578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2172cbe178e3SBram Moolenaar 			goto theend;
217303290b84SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
217438a434f7SBram Moolenaar 		    if (eval_variable(name, (int)STRLEN(name),
2175cb4e80faSBram Moolenaar 			      STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL)
217603290b84SBram Moolenaar 			goto on_error;
21774c137214SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
217803290b84SBram Moolenaar 		}
217903290b84SBram Moolenaar 		break;
218003290b84SBram Moolenaar 
21812f8ce0aeSBram Moolenaar 	    // load g:/b:/w:/t: namespace
21822f8ce0aeSBram Moolenaar 	    case ISN_LOADGDICT:
21832f8ce0aeSBram Moolenaar 	    case ISN_LOADBDICT:
21842f8ce0aeSBram Moolenaar 	    case ISN_LOADWDICT:
21852f8ce0aeSBram Moolenaar 	    case ISN_LOADTDICT:
21862f8ce0aeSBram Moolenaar 		{
21872f8ce0aeSBram Moolenaar 		    dict_T *d = NULL;
21882f8ce0aeSBram Moolenaar 
21892f8ce0aeSBram Moolenaar 		    switch (iptr->isn_type)
21902f8ce0aeSBram Moolenaar 		    {
2191682d0a15SBram Moolenaar 			case ISN_LOADGDICT: d = get_globvar_dict(); break;
2192682d0a15SBram Moolenaar 			case ISN_LOADBDICT: d = curbuf->b_vars; break;
2193682d0a15SBram Moolenaar 			case ISN_LOADWDICT: d = curwin->w_vars; break;
2194682d0a15SBram Moolenaar 			case ISN_LOADTDICT: d = curtab->tp_vars; break;
21952f8ce0aeSBram Moolenaar 			default:  // Cannot reach here
2196cbe178e3SBram Moolenaar 			    goto theend;
21972f8ce0aeSBram Moolenaar 		    }
219835578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2199cbe178e3SBram Moolenaar 			goto theend;
22002f8ce0aeSBram Moolenaar 		    tv = STACK_TV_BOT(0);
22012f8ce0aeSBram Moolenaar 		    tv->v_type = VAR_DICT;
22022f8ce0aeSBram Moolenaar 		    tv->v_lock = 0;
22032f8ce0aeSBram Moolenaar 		    tv->vval.v_dict = d;
22041bd3cb20SBram Moolenaar 		    ++d->dv_refcount;
22054c137214SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
22062f8ce0aeSBram Moolenaar 		}
22072f8ce0aeSBram Moolenaar 		break;
22082f8ce0aeSBram Moolenaar 
22098a7d6542SBram Moolenaar 	    // load &option
22108a7d6542SBram Moolenaar 	    case ISN_LOADOPT:
22118a7d6542SBram Moolenaar 		{
22128a7d6542SBram Moolenaar 		    typval_T	optval;
22138a7d6542SBram Moolenaar 		    char_u	*name = iptr->isn_arg.string;
22148a7d6542SBram Moolenaar 
2215a8c17704SBram Moolenaar 		    // This is not expected to fail, name is checked during
2216a8c17704SBram Moolenaar 		    // compilation: don't set SOURCING_LNUM.
221735578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2218cbe178e3SBram Moolenaar 			goto theend;
22199a78e6dfSBram Moolenaar 		    if (eval_option(&name, &optval, TRUE) == FAIL)
2220cbe178e3SBram Moolenaar 			goto theend;
22218a7d6542SBram Moolenaar 		    *STACK_TV_BOT(0) = optval;
22224c137214SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
22238a7d6542SBram Moolenaar 		}
22248a7d6542SBram Moolenaar 		break;
22258a7d6542SBram Moolenaar 
22268a7d6542SBram Moolenaar 	    // load $ENV
22278a7d6542SBram Moolenaar 	    case ISN_LOADENV:
22288a7d6542SBram Moolenaar 		{
22298a7d6542SBram Moolenaar 		    typval_T	optval;
22308a7d6542SBram Moolenaar 		    char_u	*name = iptr->isn_arg.string;
22318a7d6542SBram Moolenaar 
223235578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2233cbe178e3SBram Moolenaar 			goto theend;
22340bbf722aSBram Moolenaar 		    // name is always valid, checked when compiling
22359a78e6dfSBram Moolenaar 		    (void)eval_env_var(&name, &optval, TRUE);
22368a7d6542SBram Moolenaar 		    *STACK_TV_BOT(0) = optval;
22374c137214SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
22388a7d6542SBram Moolenaar 		}
22398a7d6542SBram Moolenaar 		break;
22408a7d6542SBram Moolenaar 
22418a7d6542SBram Moolenaar 	    // load @register
22428a7d6542SBram Moolenaar 	    case ISN_LOADREG:
224335578168SBram Moolenaar 		if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2244cbe178e3SBram Moolenaar 		    goto theend;
22458a7d6542SBram Moolenaar 		tv = STACK_TV_BOT(0);
22468a7d6542SBram Moolenaar 		tv->v_type = VAR_STRING;
22472f8ce0aeSBram Moolenaar 		tv->v_lock = 0;
22481e021e63SBram Moolenaar 		// This may result in NULL, which should be equivalent to an
22491e021e63SBram Moolenaar 		// empty string.
22508a7d6542SBram Moolenaar 		tv->vval.v_string = get_reg_contents(
22518a7d6542SBram Moolenaar 					  iptr->isn_arg.number, GREG_EXPR_SRC);
22524c137214SBram Moolenaar 		++ectx->ec_stack.ga_len;
22538a7d6542SBram Moolenaar 		break;
22548a7d6542SBram Moolenaar 
22558a7d6542SBram Moolenaar 	    // store local variable
22568a7d6542SBram Moolenaar 	    case ISN_STORE:
22574c137214SBram Moolenaar 		--ectx->ec_stack.ga_len;
22588a7d6542SBram Moolenaar 		tv = STACK_TV_VAR(iptr->isn_arg.number);
22598a7d6542SBram Moolenaar 		clear_tv(tv);
22608a7d6542SBram Moolenaar 		*tv = *STACK_TV_BOT(0);
22618a7d6542SBram Moolenaar 		break;
22628a7d6542SBram Moolenaar 
2263b283a8a6SBram Moolenaar 	    // store s: variable in old script
2264b283a8a6SBram Moolenaar 	    case ISN_STORES:
2265b283a8a6SBram Moolenaar 		{
2266b283a8a6SBram Moolenaar 		    hashtab_T	*ht = &SCRIPT_VARS(
2267b283a8a6SBram Moolenaar 					       iptr->isn_arg.loadstore.ls_sid);
2268b283a8a6SBram Moolenaar 		    char_u	*name = iptr->isn_arg.loadstore.ls_name;
22690bbf722aSBram Moolenaar 		    dictitem_T	*di = find_var_in_ht(ht, 0, name + 2, TRUE);
2270b283a8a6SBram Moolenaar 
22714c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
22720bbf722aSBram Moolenaar 		    if (di == NULL)
22735deeb3f1SBram Moolenaar 			store_var(name, STACK_TV_BOT(0));
22740bbf722aSBram Moolenaar 		    else
22750bbf722aSBram Moolenaar 		    {
2276dcf29ac8SBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
2277dcf29ac8SBram Moolenaar 			if (var_check_permission(di, name) == FAIL)
22786e50ec2fSBram Moolenaar 			{
22796e50ec2fSBram Moolenaar 			    clear_tv(STACK_TV_BOT(0));
2280dcf29ac8SBram Moolenaar 			    goto on_error;
22816e50ec2fSBram Moolenaar 			}
2282b283a8a6SBram Moolenaar 			clear_tv(&di->di_tv);
2283b283a8a6SBram Moolenaar 			di->di_tv = *STACK_TV_BOT(0);
2284b283a8a6SBram Moolenaar 		    }
22850bbf722aSBram Moolenaar 		}
2286b283a8a6SBram Moolenaar 		break;
2287b283a8a6SBram Moolenaar 
2288b283a8a6SBram Moolenaar 	    // store script-local variable in Vim9 script
22898a7d6542SBram Moolenaar 	    case ISN_STORESCRIPT:
22908a7d6542SBram Moolenaar 		{
22914aab88d9SBram Moolenaar 		    scriptref_T	    *sref = iptr->isn_arg.script.scriptref;
22924aab88d9SBram Moolenaar 		    svar_T	    *sv;
22938a7d6542SBram Moolenaar 
22946db660beSBram Moolenaar 		    sv = get_script_svar(sref, ectx->ec_dfunc_idx);
229507a65d26SBram Moolenaar 		    if (sv == NULL)
2296cbe178e3SBram Moolenaar 			goto theend;
22974c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
2298f5906aa7SBram Moolenaar 
2299f5906aa7SBram Moolenaar 		    // "const" and "final" are checked at compile time, locking
2300f5906aa7SBram Moolenaar 		    // the value needs to be checked here.
2301f5906aa7SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
2302f5906aa7SBram Moolenaar 		    if (value_check_lock(sv->sv_tv->v_lock, sv->sv_name, FALSE))
23036e50ec2fSBram Moolenaar 		    {
23046e50ec2fSBram Moolenaar 			clear_tv(STACK_TV_BOT(0));
2305f5906aa7SBram Moolenaar 			goto on_error;
23066e50ec2fSBram Moolenaar 		    }
2307f5906aa7SBram Moolenaar 
23088a7d6542SBram Moolenaar 		    clear_tv(sv->sv_tv);
23098a7d6542SBram Moolenaar 		    *sv->sv_tv = *STACK_TV_BOT(0);
23108a7d6542SBram Moolenaar 		}
23118a7d6542SBram Moolenaar 		break;
23128a7d6542SBram Moolenaar 
23138a7d6542SBram Moolenaar 	    // store option
23148a7d6542SBram Moolenaar 	    case ISN_STOREOPT:
23158a7d6542SBram Moolenaar 		{
23168a7d6542SBram Moolenaar 		    long	n = 0;
23178a7d6542SBram Moolenaar 		    char_u	*s = NULL;
23188a7d6542SBram Moolenaar 		    char	*msg;
23198a7d6542SBram Moolenaar 
23204c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
23218a7d6542SBram Moolenaar 		    tv = STACK_TV_BOT(0);
23228a7d6542SBram Moolenaar 		    if (tv->v_type == VAR_STRING)
232397a2af39SBram Moolenaar 		    {
23248a7d6542SBram Moolenaar 			s = tv->vval.v_string;
232597a2af39SBram Moolenaar 			if (s == NULL)
232697a2af39SBram Moolenaar 			    s = (char_u *)"";
232797a2af39SBram Moolenaar 		    }
23288a7d6542SBram Moolenaar 		    else
2329a6e67e4fSBram Moolenaar 			// must be VAR_NUMBER, CHECKTYPE makes sure
2330a6e67e4fSBram Moolenaar 			n = tv->vval.v_number;
23318a7d6542SBram Moolenaar 		    msg = set_option_value(iptr->isn_arg.storeopt.so_name,
23328a7d6542SBram Moolenaar 					n, s, iptr->isn_arg.storeopt.so_flags);
2333e75ba268SBram Moolenaar 		    clear_tv(tv);
23348a7d6542SBram Moolenaar 		    if (msg != NULL)
23358a7d6542SBram Moolenaar 		    {
23367517ffdbSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
23378a7d6542SBram Moolenaar 			emsg(_(msg));
2338e859312eSBram Moolenaar 			goto on_error;
23398a7d6542SBram Moolenaar 		    }
23408a7d6542SBram Moolenaar 		}
23418a7d6542SBram Moolenaar 		break;
23428a7d6542SBram Moolenaar 
2343b283a8a6SBram Moolenaar 	    // store $ENV
2344b283a8a6SBram Moolenaar 	    case ISN_STOREENV:
23454c137214SBram Moolenaar 		--ectx->ec_stack.ga_len;
234620431c9dSBram Moolenaar 		tv = STACK_TV_BOT(0);
234720431c9dSBram Moolenaar 		vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
234820431c9dSBram Moolenaar 		clear_tv(tv);
2349b283a8a6SBram Moolenaar 		break;
2350b283a8a6SBram Moolenaar 
2351b283a8a6SBram Moolenaar 	    // store @r
2352b283a8a6SBram Moolenaar 	    case ISN_STOREREG:
2353b283a8a6SBram Moolenaar 		{
2354b283a8a6SBram Moolenaar 		    int	reg = iptr->isn_arg.number;
2355b283a8a6SBram Moolenaar 
23564c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
2357401d9ffbSBram Moolenaar 		    tv = STACK_TV_BOT(0);
235874f4a965SBram Moolenaar 		    write_reg_contents(reg, tv_get_string(tv), -1, FALSE);
2359401d9ffbSBram Moolenaar 		    clear_tv(tv);
2360b283a8a6SBram Moolenaar 		}
2361b283a8a6SBram Moolenaar 		break;
2362b283a8a6SBram Moolenaar 
2363b283a8a6SBram Moolenaar 	    // store v: variable
2364b283a8a6SBram Moolenaar 	    case ISN_STOREV:
23654c137214SBram Moolenaar 		--ectx->ec_stack.ga_len;
2366b283a8a6SBram Moolenaar 		if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
2367b283a8a6SBram Moolenaar 								       == FAIL)
2368e859312eSBram Moolenaar 		    // should not happen, type is checked when compiling
2369e859312eSBram Moolenaar 		    goto on_error;
2370b283a8a6SBram Moolenaar 		break;
2371b283a8a6SBram Moolenaar 
2372d3aac291SBram Moolenaar 	    // store g:/b:/w:/t: variable
23738a7d6542SBram Moolenaar 	    case ISN_STOREG:
2374d3aac291SBram Moolenaar 	    case ISN_STOREB:
2375d3aac291SBram Moolenaar 	    case ISN_STOREW:
2376d3aac291SBram Moolenaar 	    case ISN_STORET:
23778a7d6542SBram Moolenaar 		{
23788a7d6542SBram Moolenaar 		    dictitem_T	*di;
2379d3aac291SBram Moolenaar 		    hashtab_T	*ht;
23803bdc90b7SBram Moolenaar 		    char_u	*name = iptr->isn_arg.string + 2;
23813bdc90b7SBram Moolenaar 
2382d3aac291SBram Moolenaar 		    switch (iptr->isn_type)
2383d3aac291SBram Moolenaar 		    {
2384d3aac291SBram Moolenaar 			case ISN_STOREG:
2385d3aac291SBram Moolenaar 			    ht = get_globvar_ht();
2386d3aac291SBram Moolenaar 			    break;
2387d3aac291SBram Moolenaar 			case ISN_STOREB:
2388d3aac291SBram Moolenaar 			    ht = &curbuf->b_vars->dv_hashtab;
2389d3aac291SBram Moolenaar 			    break;
2390d3aac291SBram Moolenaar 			case ISN_STOREW:
2391d3aac291SBram Moolenaar 			    ht = &curwin->w_vars->dv_hashtab;
2392d3aac291SBram Moolenaar 			    break;
2393d3aac291SBram Moolenaar 			case ISN_STORET:
2394d3aac291SBram Moolenaar 			    ht = &curtab->tp_vars->dv_hashtab;
2395d3aac291SBram Moolenaar 			    break;
2396d3aac291SBram Moolenaar 			default:  // Cannot reach here
2397cbe178e3SBram Moolenaar 			    goto theend;
2398d3aac291SBram Moolenaar 		    }
23998a7d6542SBram Moolenaar 
24004c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
24013bdc90b7SBram Moolenaar 		    di = find_var_in_ht(ht, 0, name, TRUE);
24028a7d6542SBram Moolenaar 		    if (di == NULL)
24030bbf722aSBram Moolenaar 			store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
24048a7d6542SBram Moolenaar 		    else
24058a7d6542SBram Moolenaar 		    {
24063bdc90b7SBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
24073bdc90b7SBram Moolenaar 			if (var_check_permission(di, name) == FAIL)
24083bdc90b7SBram Moolenaar 			    goto on_error;
24098a7d6542SBram Moolenaar 			clear_tv(&di->di_tv);
24108a7d6542SBram Moolenaar 			di->di_tv = *STACK_TV_BOT(0);
24118a7d6542SBram Moolenaar 		    }
24128a7d6542SBram Moolenaar 		}
24138a7d6542SBram Moolenaar 		break;
24148a7d6542SBram Moolenaar 
241503290b84SBram Moolenaar 	    // store an autoload variable
241603290b84SBram Moolenaar 	    case ISN_STOREAUTO:
241703290b84SBram Moolenaar 		SOURCING_LNUM = iptr->isn_lnum;
241803290b84SBram Moolenaar 		set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE);
241903290b84SBram Moolenaar 		clear_tv(STACK_TV_BOT(-1));
24204c137214SBram Moolenaar 		--ectx->ec_stack.ga_len;
242103290b84SBram Moolenaar 		break;
242203290b84SBram Moolenaar 
24238a7d6542SBram Moolenaar 	    // store number in local variable
24248a7d6542SBram Moolenaar 	    case ISN_STORENR:
2425a471eeaeSBram Moolenaar 		tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
24268a7d6542SBram Moolenaar 		clear_tv(tv);
24278a7d6542SBram Moolenaar 		tv->v_type = VAR_NUMBER;
2428a471eeaeSBram Moolenaar 		tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
24298a7d6542SBram Moolenaar 		break;
24308a7d6542SBram Moolenaar 
24314f5e3977SBram Moolenaar 	    // store value in list or dict variable
24324f5e3977SBram Moolenaar 	    case ISN_STOREINDEX:
24331cc2a94fSBram Moolenaar 		{
24344f5e3977SBram Moolenaar 		    vartype_T	dest_type = iptr->isn_arg.vartype;
24351cc2a94fSBram Moolenaar 		    typval_T	*tv_idx = STACK_TV_BOT(-2);
24364f5e3977SBram Moolenaar 		    typval_T	*tv_dest = STACK_TV_BOT(-1);
24374f5e3977SBram Moolenaar 		    int		status = OK;
24381cc2a94fSBram Moolenaar 
2439752fc692SBram Moolenaar 		    // Stack contains:
2440752fc692SBram Moolenaar 		    // -3 value to be stored
2441752fc692SBram Moolenaar 		    // -2 index
2442752fc692SBram Moolenaar 		    // -1 dict or list
24434f5e3977SBram Moolenaar 		    tv = STACK_TV_BOT(-3);
24440b4c66c6SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
24454f5e3977SBram Moolenaar 		    if (dest_type == VAR_ANY)
24464f5e3977SBram Moolenaar 		    {
24474f5e3977SBram Moolenaar 			dest_type = tv_dest->v_type;
24484f5e3977SBram Moolenaar 			if (dest_type == VAR_DICT)
24495fa9b244SBram Moolenaar 			    status = do_2string(tv_idx, TRUE, FALSE);
24504f5e3977SBram Moolenaar 			else if (dest_type == VAR_LIST
24514f5e3977SBram Moolenaar 					       && tv_idx->v_type != VAR_NUMBER)
24524f5e3977SBram Moolenaar 			{
2453e29a27f6SBram Moolenaar 			    emsg(_(e_number_expected));
24544f5e3977SBram Moolenaar 			    status = FAIL;
24554f5e3977SBram Moolenaar 			}
24564f5e3977SBram Moolenaar 		    }
24574f5e3977SBram Moolenaar 		    else if (dest_type != tv_dest->v_type)
24584f5e3977SBram Moolenaar 		    {
24594f5e3977SBram Moolenaar 			// just in case, should be OK
24604f5e3977SBram Moolenaar 			semsg(_(e_expected_str_but_got_str),
24614f5e3977SBram Moolenaar 				    vartype_name(dest_type),
24624f5e3977SBram Moolenaar 				    vartype_name(tv_dest->v_type));
24634f5e3977SBram Moolenaar 			status = FAIL;
24644f5e3977SBram Moolenaar 		    }
24654f5e3977SBram Moolenaar 
24664f5e3977SBram Moolenaar 		    if (status == OK && dest_type == VAR_LIST)
24674f5e3977SBram Moolenaar 		    {
2468239f8d93SBram Moolenaar 			long	    lidx = (long)tv_idx->vval.v_number;
24694f5e3977SBram Moolenaar 			list_T	    *list = tv_dest->vval.v_list;
24704f5e3977SBram Moolenaar 
24714f5e3977SBram Moolenaar 			if (list == NULL)
24724f5e3977SBram Moolenaar 			{
24734f5e3977SBram Moolenaar 			    emsg(_(e_list_not_set));
24744f5e3977SBram Moolenaar 			    goto on_error;
24754f5e3977SBram Moolenaar 			}
24761cc2a94fSBram Moolenaar 			if (lidx < 0 && list->lv_len + lidx >= 0)
24771cc2a94fSBram Moolenaar 			    // negative index is relative to the end
24781cc2a94fSBram Moolenaar 			    lidx = list->lv_len + lidx;
24791cc2a94fSBram Moolenaar 			if (lidx < 0 || lidx > list->lv_len)
24801cc2a94fSBram Moolenaar 			{
24811cc2a94fSBram Moolenaar 			    semsg(_(e_listidx), lidx);
2482e859312eSBram Moolenaar 			    goto on_error;
24831cc2a94fSBram Moolenaar 			}
24841cc2a94fSBram Moolenaar 			if (lidx < list->lv_len)
24851cc2a94fSBram Moolenaar 			{
24861cc2a94fSBram Moolenaar 			    listitem_T *li = list_find(list, lidx);
24871cc2a94fSBram Moolenaar 
24880b4c66c6SBram Moolenaar 			    if (error_if_locked(li->li_tv.v_lock,
24890b4c66c6SBram Moolenaar 						    e_cannot_change_list_item))
24904f5e3977SBram Moolenaar 				goto on_error;
24911cc2a94fSBram Moolenaar 			    // overwrite existing list item
24921cc2a94fSBram Moolenaar 			    clear_tv(&li->li_tv);
24931cc2a94fSBram Moolenaar 			    li->li_tv = *tv;
24941cc2a94fSBram Moolenaar 			}
24951cc2a94fSBram Moolenaar 			else
24961cc2a94fSBram Moolenaar 			{
24970b4c66c6SBram Moolenaar 			    if (error_if_locked(list->lv_lock,
24980b4c66c6SBram Moolenaar 							 e_cannot_change_list))
24994f5e3977SBram Moolenaar 				goto on_error;
2500e859312eSBram Moolenaar 			    // append to list, only fails when out of memory
25011cc2a94fSBram Moolenaar 			    if (list_append_tv(list, tv) == FAIL)
2502cbe178e3SBram Moolenaar 				goto theend;
25031cc2a94fSBram Moolenaar 			    clear_tv(tv);
25041cc2a94fSBram Moolenaar 			}
25051cc2a94fSBram Moolenaar 		    }
25064f5e3977SBram Moolenaar 		    else if (status == OK && dest_type == VAR_DICT)
25071cc2a94fSBram Moolenaar 		    {
25084f5e3977SBram Moolenaar 			char_u		*key = tv_idx->vval.v_string;
25094f5e3977SBram Moolenaar 			dict_T		*dict = tv_dest->vval.v_dict;
25101cc2a94fSBram Moolenaar 			dictitem_T	*di;
25111cc2a94fSBram Moolenaar 
25120b4c66c6SBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
25138e4c8c85SBram Moolenaar 			if (dict == NULL)
25148e4c8c85SBram Moolenaar 			{
2515bc4c5051SBram Moolenaar 			    emsg(_(e_dictionary_not_set));
25168e4c8c85SBram Moolenaar 			    goto on_error;
25178e4c8c85SBram Moolenaar 			}
251858626872SBram Moolenaar 			if (key == NULL)
251958626872SBram Moolenaar 			    key = (char_u *)"";
25201cc2a94fSBram Moolenaar 			di = dict_find(dict, key, -1);
25211cc2a94fSBram Moolenaar 			if (di != NULL)
25221cc2a94fSBram Moolenaar 			{
25230b4c66c6SBram Moolenaar 			    if (error_if_locked(di->di_tv.v_lock,
25240b4c66c6SBram Moolenaar 						    e_cannot_change_dict_item))
25254f5e3977SBram Moolenaar 				goto on_error;
2526e859312eSBram Moolenaar 			    // overwrite existing value
25271cc2a94fSBram Moolenaar 			    clear_tv(&di->di_tv);
25281cc2a94fSBram Moolenaar 			    di->di_tv = *tv;
25291cc2a94fSBram Moolenaar 			}
25301cc2a94fSBram Moolenaar 			else
25311cc2a94fSBram Moolenaar 			{
25320b4c66c6SBram Moolenaar 			    if (error_if_locked(dict->dv_lock,
25330b4c66c6SBram Moolenaar 							 e_cannot_change_dict))
25344f5e3977SBram Moolenaar 				goto on_error;
2535e859312eSBram Moolenaar 			    // add to dict, only fails when out of memory
25361cc2a94fSBram Moolenaar 			    if (dict_add_tv(dict, (char *)key, tv) == FAIL)
2537cbe178e3SBram Moolenaar 				goto theend;
25381cc2a94fSBram Moolenaar 			    clear_tv(tv);
25391cc2a94fSBram Moolenaar 			}
25404f5e3977SBram Moolenaar 		    }
254168452177SBram Moolenaar 		    else if (status == OK && dest_type == VAR_BLOB)
254268452177SBram Moolenaar 		    {
254351e93326SBram Moolenaar 			long	    lidx = (long)tv_idx->vval.v_number;
254451e93326SBram Moolenaar 			blob_T	    *blob = tv_dest->vval.v_blob;
254551e93326SBram Moolenaar 			varnumber_T nr;
254651e93326SBram Moolenaar 			int	    error = FALSE;
254751e93326SBram Moolenaar 			int	    len;
254851e93326SBram Moolenaar 
254951e93326SBram Moolenaar 			if (blob == NULL)
255051e93326SBram Moolenaar 			{
255151e93326SBram Moolenaar 			    emsg(_(e_blob_not_set));
255251e93326SBram Moolenaar 			    goto on_error;
255351e93326SBram Moolenaar 			}
255451e93326SBram Moolenaar 			len = blob_len(blob);
255551e93326SBram Moolenaar 			if (lidx < 0 && len + lidx >= 0)
255651e93326SBram Moolenaar 			    // negative index is relative to the end
255751e93326SBram Moolenaar 			    lidx = len + lidx;
255851e93326SBram Moolenaar 
255951e93326SBram Moolenaar 			// Can add one byte at the end.
256051e93326SBram Moolenaar 			if (lidx < 0 || lidx > len)
256151e93326SBram Moolenaar 			{
256251e93326SBram Moolenaar 			    semsg(_(e_blobidx), lidx);
256351e93326SBram Moolenaar 			    goto on_error;
256451e93326SBram Moolenaar 			}
256551e93326SBram Moolenaar 			if (value_check_lock(blob->bv_lock,
256651e93326SBram Moolenaar 						      (char_u *)"blob", FALSE))
256751e93326SBram Moolenaar 			    goto on_error;
256851e93326SBram Moolenaar 			nr = tv_get_number_chk(tv, &error);
256951e93326SBram Moolenaar 			if (error)
257051e93326SBram Moolenaar 			    goto on_error;
257151e93326SBram Moolenaar 			blob_set_append(blob, lidx, nr);
257268452177SBram Moolenaar 		    }
25734f5e3977SBram Moolenaar 		    else
25744f5e3977SBram Moolenaar 		    {
25754f5e3977SBram Moolenaar 			status = FAIL;
25764f5e3977SBram Moolenaar 			semsg(_(e_cannot_index_str), vartype_name(dest_type));
25774f5e3977SBram Moolenaar 		    }
25784f5e3977SBram Moolenaar 
25794f5e3977SBram Moolenaar 		    clear_tv(tv_idx);
25804f5e3977SBram Moolenaar 		    clear_tv(tv_dest);
25814c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= 3;
25824f5e3977SBram Moolenaar 		    if (status == FAIL)
25834f5e3977SBram Moolenaar 		    {
25844f5e3977SBram Moolenaar 			clear_tv(tv);
25854f5e3977SBram Moolenaar 			goto on_error;
25864f5e3977SBram Moolenaar 		    }
25871cc2a94fSBram Moolenaar 		}
25881cc2a94fSBram Moolenaar 		break;
25891cc2a94fSBram Moolenaar 
259068452177SBram Moolenaar 	    // store value in blob range
259168452177SBram Moolenaar 	    case ISN_STORERANGE:
259268452177SBram Moolenaar 		{
259368452177SBram Moolenaar 		    typval_T	*tv_idx1 = STACK_TV_BOT(-3);
259468452177SBram Moolenaar 		    typval_T	*tv_idx2 = STACK_TV_BOT(-2);
259568452177SBram Moolenaar 		    typval_T	*tv_dest = STACK_TV_BOT(-1);
259668452177SBram Moolenaar 		    int		status = OK;
259768452177SBram Moolenaar 
259868452177SBram Moolenaar 		    // Stack contains:
259968452177SBram Moolenaar 		    // -4 value to be stored
260068452177SBram Moolenaar 		    // -3 first index or "none"
260168452177SBram Moolenaar 		    // -2 second index or "none"
26024f0884d6SBram Moolenaar 		    // -1 destination list or blob
260368452177SBram Moolenaar 		    tv = STACK_TV_BOT(-4);
26044f0884d6SBram Moolenaar 		    if (tv_dest->v_type == VAR_LIST)
260568452177SBram Moolenaar 		    {
26064f0884d6SBram Moolenaar 			long	n1;
26074f0884d6SBram Moolenaar 			long	n2;
26084f0884d6SBram Moolenaar 			int	error = FALSE;
26094f0884d6SBram Moolenaar 
26104f0884d6SBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
26114f0884d6SBram Moolenaar 			n1 = (long)tv_get_number_chk(tv_idx1, &error);
26124f0884d6SBram Moolenaar 			if (error)
261368452177SBram Moolenaar 			    status = FAIL;
261468452177SBram Moolenaar 			else
261568452177SBram Moolenaar 			{
26164f0884d6SBram Moolenaar 			    if (tv_idx2->v_type == VAR_SPECIAL
26174f0884d6SBram Moolenaar 					&& tv_idx2->vval.v_number == VVAL_NONE)
26184f0884d6SBram Moolenaar 				n2 = list_len(tv_dest->vval.v_list) - 1;
26194f0884d6SBram Moolenaar 			    else
26204f0884d6SBram Moolenaar 				n2 = (long)tv_get_number_chk(tv_idx2, &error);
26214f0884d6SBram Moolenaar 			    if (error)
26224f0884d6SBram Moolenaar 				status = FAIL;
26234f0884d6SBram Moolenaar 			    else
26244f0884d6SBram Moolenaar 			    {
26254f0884d6SBram Moolenaar 				listitem_T *li1 = check_range_index_one(
26264f0884d6SBram Moolenaar 					tv_dest->vval.v_list, &n1, FALSE);
26274f0884d6SBram Moolenaar 
26284f0884d6SBram Moolenaar 				if (li1 == NULL)
26294f0884d6SBram Moolenaar 				    status = FAIL;
26304f0884d6SBram Moolenaar 				else
26314f0884d6SBram Moolenaar 				{
26324f0884d6SBram Moolenaar 				    status = check_range_index_two(
26334f0884d6SBram Moolenaar 					    tv_dest->vval.v_list,
26344f0884d6SBram Moolenaar 					    &n1, li1, &n2, FALSE);
26354f0884d6SBram Moolenaar 				    if (status != FAIL)
26364f0884d6SBram Moolenaar 					status = list_assign_range(
26374f0884d6SBram Moolenaar 						tv_dest->vval.v_list,
26384f0884d6SBram Moolenaar 						tv->vval.v_list,
26394f0884d6SBram Moolenaar 						n1,
26404f0884d6SBram Moolenaar 						n2,
26414f0884d6SBram Moolenaar 						tv_idx2->v_type == VAR_SPECIAL,
26424f0884d6SBram Moolenaar 						(char_u *)"=",
26434f0884d6SBram Moolenaar 						(char_u *)"[unknown]");
26444f0884d6SBram Moolenaar 				}
26454f0884d6SBram Moolenaar 			    }
26464f0884d6SBram Moolenaar 			}
26474f0884d6SBram Moolenaar 		    }
26484f0884d6SBram Moolenaar 		    else if (tv_dest->v_type == VAR_BLOB)
26494f0884d6SBram Moolenaar 		    {
265068452177SBram Moolenaar 			varnumber_T n1;
265168452177SBram Moolenaar 			varnumber_T n2;
265268452177SBram Moolenaar 			int	    error = FALSE;
265368452177SBram Moolenaar 
265468452177SBram Moolenaar 			n1 = tv_get_number_chk(tv_idx1, &error);
265568452177SBram Moolenaar 			if (error)
265668452177SBram Moolenaar 			    status = FAIL;
265768452177SBram Moolenaar 			else
265868452177SBram Moolenaar 			{
265968452177SBram Moolenaar 			    if (tv_idx2->v_type == VAR_SPECIAL
266068452177SBram Moolenaar 					&& tv_idx2->vval.v_number == VVAL_NONE)
266168452177SBram Moolenaar 				n2 = blob_len(tv_dest->vval.v_blob) - 1;
266268452177SBram Moolenaar 			    else
266368452177SBram Moolenaar 				n2 = tv_get_number_chk(tv_idx2, &error);
266468452177SBram Moolenaar 			    if (error)
266568452177SBram Moolenaar 				status = FAIL;
266668452177SBram Moolenaar 			    else
26670e3ff191SBram Moolenaar 			    {
26680e3ff191SBram Moolenaar 				long  bloblen = blob_len(tv_dest->vval.v_blob);
26690e3ff191SBram Moolenaar 
26700e3ff191SBram Moolenaar 				if (check_blob_index(bloblen,
2671bd6406f1SBram Moolenaar 							     n1, FALSE) == FAIL
26720e3ff191SBram Moolenaar 					|| check_blob_range(bloblen,
26730e3ff191SBram Moolenaar 							n1, n2, FALSE) == FAIL)
26740e3ff191SBram Moolenaar 				    status = FAIL;
26750e3ff191SBram Moolenaar 				else
26760e3ff191SBram Moolenaar 				    status = blob_set_range(
26770e3ff191SBram Moolenaar 					     tv_dest->vval.v_blob, n1, n2, tv);
26780e3ff191SBram Moolenaar 			    }
267968452177SBram Moolenaar 			}
268068452177SBram Moolenaar 		    }
26814f0884d6SBram Moolenaar 		    else
26824f0884d6SBram Moolenaar 		    {
26834f0884d6SBram Moolenaar 			status = FAIL;
26844f0884d6SBram Moolenaar 			emsg(_(e_blob_required));
26854f0884d6SBram Moolenaar 		    }
268668452177SBram Moolenaar 
268768452177SBram Moolenaar 		    clear_tv(tv_idx1);
268868452177SBram Moolenaar 		    clear_tv(tv_idx2);
268968452177SBram Moolenaar 		    clear_tv(tv_dest);
26904c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= 4;
269168452177SBram Moolenaar 		    clear_tv(tv);
269268452177SBram Moolenaar 
269368452177SBram Moolenaar 		    if (status == FAIL)
269468452177SBram Moolenaar 			goto on_error;
269568452177SBram Moolenaar 		}
269668452177SBram Moolenaar 		break;
269768452177SBram Moolenaar 
26980186e586SBram Moolenaar 	    // load or store variable or argument from outer scope
26990186e586SBram Moolenaar 	    case ISN_LOADOUTER:
27000186e586SBram Moolenaar 	    case ISN_STOREOUTER:
27010186e586SBram Moolenaar 		{
27020186e586SBram Moolenaar 		    int		depth = iptr->isn_arg.outer.outer_depth;
2703c04f2a4cSBram Moolenaar 		    outer_T	*outer = ectx->ec_outer_ref == NULL ? NULL
2704c04f2a4cSBram Moolenaar 						: ectx->ec_outer_ref->or_outer;
27050186e586SBram Moolenaar 
27060186e586SBram Moolenaar 		    while (depth > 1 && outer != NULL)
27070186e586SBram Moolenaar 		    {
27080186e586SBram Moolenaar 			outer = outer->out_up;
27090186e586SBram Moolenaar 			--depth;
27100186e586SBram Moolenaar 		    }
27110186e586SBram Moolenaar 		    if (outer == NULL)
27120186e586SBram Moolenaar 		    {
27130186e586SBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
27140186e586SBram Moolenaar 			iemsg("LOADOUTER depth more than scope levels");
2715cbe178e3SBram Moolenaar 			goto theend;
27160186e586SBram Moolenaar 		    }
27170186e586SBram Moolenaar 		    tv = ((typval_T *)outer->out_stack->ga_data)
27180186e586SBram Moolenaar 				    + outer->out_frame_idx + STACK_FRAME_SIZE
27190186e586SBram Moolenaar 				    + iptr->isn_arg.outer.outer_idx;
27200186e586SBram Moolenaar 		    if (iptr->isn_type == ISN_LOADOUTER)
27210186e586SBram Moolenaar 		    {
272235578168SBram Moolenaar 			if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2723cbe178e3SBram Moolenaar 			    goto theend;
27240186e586SBram Moolenaar 			copy_tv(tv, STACK_TV_BOT(0));
27254c137214SBram Moolenaar 			++ectx->ec_stack.ga_len;
27260186e586SBram Moolenaar 		    }
27270186e586SBram Moolenaar 		    else
27280186e586SBram Moolenaar 		    {
27294c137214SBram Moolenaar 			--ectx->ec_stack.ga_len;
27300186e586SBram Moolenaar 			clear_tv(tv);
27310186e586SBram Moolenaar 			*tv = *STACK_TV_BOT(0);
27320186e586SBram Moolenaar 		    }
27330186e586SBram Moolenaar 		}
27340186e586SBram Moolenaar 		break;
27350186e586SBram Moolenaar 
2736752fc692SBram Moolenaar 	    // unlet item in list or dict variable
2737752fc692SBram Moolenaar 	    case ISN_UNLETINDEX:
2738752fc692SBram Moolenaar 		{
2739752fc692SBram Moolenaar 		    typval_T	*tv_idx = STACK_TV_BOT(-2);
2740752fc692SBram Moolenaar 		    typval_T	*tv_dest = STACK_TV_BOT(-1);
2741752fc692SBram Moolenaar 		    int		status = OK;
2742752fc692SBram Moolenaar 
2743752fc692SBram Moolenaar 		    // Stack contains:
2744752fc692SBram Moolenaar 		    // -2 index
2745752fc692SBram Moolenaar 		    // -1 dict or list
2746752fc692SBram Moolenaar 		    if (tv_dest->v_type == VAR_DICT)
2747752fc692SBram Moolenaar 		    {
2748752fc692SBram Moolenaar 			// unlet a dict item, index must be a string
2749752fc692SBram Moolenaar 			if (tv_idx->v_type != VAR_STRING)
2750752fc692SBram Moolenaar 			{
27510acbf5aeSBram Moolenaar 			    SOURCING_LNUM = iptr->isn_lnum;
2752752fc692SBram Moolenaar 			    semsg(_(e_expected_str_but_got_str),
2753752fc692SBram Moolenaar 					vartype_name(VAR_STRING),
2754752fc692SBram Moolenaar 					vartype_name(tv_idx->v_type));
2755752fc692SBram Moolenaar 			    status = FAIL;
2756752fc692SBram Moolenaar 			}
2757752fc692SBram Moolenaar 			else
2758752fc692SBram Moolenaar 			{
2759752fc692SBram Moolenaar 			    dict_T	*d = tv_dest->vval.v_dict;
2760752fc692SBram Moolenaar 			    char_u	*key = tv_idx->vval.v_string;
2761752fc692SBram Moolenaar 			    dictitem_T  *di = NULL;
2762752fc692SBram Moolenaar 
2763752fc692SBram Moolenaar 			    if (key == NULL)
2764752fc692SBram Moolenaar 				key = (char_u *)"";
2765752fc692SBram Moolenaar 			    if (d != NULL)
2766752fc692SBram Moolenaar 				di = dict_find(d, key, (int)STRLEN(key));
2767752fc692SBram Moolenaar 			    if (di == NULL)
2768752fc692SBram Moolenaar 			    {
2769752fc692SBram Moolenaar 				// NULL dict is equivalent to empty dict
27700acbf5aeSBram Moolenaar 				SOURCING_LNUM = iptr->isn_lnum;
2771752fc692SBram Moolenaar 				semsg(_(e_dictkey), key);
2772752fc692SBram Moolenaar 				status = FAIL;
2773752fc692SBram Moolenaar 			    }
2774752fc692SBram Moolenaar 			    else
2775752fc692SBram Moolenaar 			    {
2776752fc692SBram Moolenaar 				// TODO: check for dict or item locked
2777752fc692SBram Moolenaar 				dictitem_remove(d, di);
2778752fc692SBram Moolenaar 			    }
2779752fc692SBram Moolenaar 			}
2780752fc692SBram Moolenaar 		    }
2781752fc692SBram Moolenaar 		    else if (tv_dest->v_type == VAR_LIST)
2782752fc692SBram Moolenaar 		    {
2783752fc692SBram Moolenaar 			// unlet a List item, index must be a number
27840acbf5aeSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
27855b5ae29bSBram Moolenaar 			if (check_for_number(tv_idx) == FAIL)
27865b5ae29bSBram Moolenaar 			{
2787752fc692SBram Moolenaar 			    status = FAIL;
2788752fc692SBram Moolenaar 			}
2789752fc692SBram Moolenaar 			else
2790752fc692SBram Moolenaar 			{
2791752fc692SBram Moolenaar 			    list_T	*l = tv_dest->vval.v_list;
2792239f8d93SBram Moolenaar 			    long	n = (long)tv_idx->vval.v_number;
2793752fc692SBram Moolenaar 			    listitem_T	*li = NULL;
2794752fc692SBram Moolenaar 
2795752fc692SBram Moolenaar 			    li = list_find(l, n);
2796752fc692SBram Moolenaar 			    if (li == NULL)
2797752fc692SBram Moolenaar 			    {
27980acbf5aeSBram Moolenaar 				SOURCING_LNUM = iptr->isn_lnum;
2799752fc692SBram Moolenaar 				semsg(_(e_listidx), n);
2800752fc692SBram Moolenaar 				status = FAIL;
2801752fc692SBram Moolenaar 			    }
2802752fc692SBram Moolenaar 			    else
2803752fc692SBram Moolenaar 				// TODO: check for list or item locked
2804752fc692SBram Moolenaar 				listitem_remove(l, li);
2805752fc692SBram Moolenaar 			}
2806752fc692SBram Moolenaar 		    }
2807752fc692SBram Moolenaar 		    else
2808752fc692SBram Moolenaar 		    {
2809752fc692SBram Moolenaar 			status = FAIL;
2810752fc692SBram Moolenaar 			semsg(_(e_cannot_index_str),
2811752fc692SBram Moolenaar 						vartype_name(tv_dest->v_type));
2812752fc692SBram Moolenaar 		    }
2813752fc692SBram Moolenaar 
2814752fc692SBram Moolenaar 		    clear_tv(tv_idx);
2815752fc692SBram Moolenaar 		    clear_tv(tv_dest);
28164c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= 2;
2817752fc692SBram Moolenaar 		    if (status == FAIL)
2818752fc692SBram Moolenaar 			goto on_error;
2819752fc692SBram Moolenaar 		}
2820752fc692SBram Moolenaar 		break;
2821752fc692SBram Moolenaar 
28225b5ae29bSBram Moolenaar 	    // unlet range of items in list variable
28235b5ae29bSBram Moolenaar 	    case ISN_UNLETRANGE:
28245b5ae29bSBram Moolenaar 		{
28255b5ae29bSBram Moolenaar 		    // Stack contains:
28265b5ae29bSBram Moolenaar 		    // -3 index1
28275b5ae29bSBram Moolenaar 		    // -2 index2
28285b5ae29bSBram Moolenaar 		    // -1 dict or list
28295b5ae29bSBram Moolenaar 		    typval_T	*tv_idx1 = STACK_TV_BOT(-3);
28305b5ae29bSBram Moolenaar 		    typval_T	*tv_idx2 = STACK_TV_BOT(-2);
28315b5ae29bSBram Moolenaar 		    typval_T	*tv_dest = STACK_TV_BOT(-1);
28325b5ae29bSBram Moolenaar 		    int		status = OK;
28335b5ae29bSBram Moolenaar 
28345b5ae29bSBram Moolenaar 		    if (tv_dest->v_type == VAR_LIST)
28355b5ae29bSBram Moolenaar 		    {
28365b5ae29bSBram Moolenaar 			// indexes must be a number
28375b5ae29bSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
28385b5ae29bSBram Moolenaar 			if (check_for_number(tv_idx1) == FAIL
283963cb6567SBram Moolenaar 				|| (tv_idx2->v_type != VAR_SPECIAL
284063cb6567SBram Moolenaar 					 && check_for_number(tv_idx2) == FAIL))
28415b5ae29bSBram Moolenaar 			{
28425b5ae29bSBram Moolenaar 			    status = FAIL;
28435b5ae29bSBram Moolenaar 			}
28445b5ae29bSBram Moolenaar 			else
28455b5ae29bSBram Moolenaar 			{
28465b5ae29bSBram Moolenaar 			    list_T	*l = tv_dest->vval.v_list;
28475b5ae29bSBram Moolenaar 			    long	n1 = (long)tv_idx1->vval.v_number;
284863cb6567SBram Moolenaar 			    long	n2 = tv_idx2->v_type == VAR_SPECIAL
284963cb6567SBram Moolenaar 					    ? 0 : (long)tv_idx2->vval.v_number;
28505b5ae29bSBram Moolenaar 			    listitem_T	*li;
28515b5ae29bSBram Moolenaar 
28525b5ae29bSBram Moolenaar 			    li = list_find_index(l, &n1);
285363cb6567SBram Moolenaar 			    if (li == NULL)
28545b5ae29bSBram Moolenaar 				status = FAIL;
285563cb6567SBram Moolenaar 			    else
285663cb6567SBram Moolenaar 			    {
285763cb6567SBram Moolenaar 				if (n1 < 0)
285863cb6567SBram Moolenaar 				    n1 = list_idx_of_item(l, li);
285963cb6567SBram Moolenaar 				if (n2 < 0)
286063cb6567SBram Moolenaar 				{
286163cb6567SBram Moolenaar 				    listitem_T *li2 = list_find(l, n2);
286263cb6567SBram Moolenaar 
286363cb6567SBram Moolenaar 				    if (li2 == NULL)
286463cb6567SBram Moolenaar 					status = FAIL;
286563cb6567SBram Moolenaar 				    else
286663cb6567SBram Moolenaar 					n2 = list_idx_of_item(l, li2);
286763cb6567SBram Moolenaar 				}
286863cb6567SBram Moolenaar 				if (status != FAIL
28695dd839ceSBram Moolenaar 					&& tv_idx2->v_type != VAR_SPECIAL
28705dd839ceSBram Moolenaar 					&& n2 < n1)
28715dd839ceSBram Moolenaar 				{
28725dd839ceSBram Moolenaar 				    semsg(_(e_listidx), n2);
28735dd839ceSBram Moolenaar 				    status = FAIL;
28745dd839ceSBram Moolenaar 				}
28755dd839ceSBram Moolenaar 				if (status != FAIL
287663cb6567SBram Moolenaar 					&& list_unlet_range(l, li, NULL, n1,
287763cb6567SBram Moolenaar 					    tv_idx2->v_type != VAR_SPECIAL, n2)
287863cb6567SBram Moolenaar 								       == FAIL)
287963cb6567SBram Moolenaar 				    status = FAIL;
288063cb6567SBram Moolenaar 			    }
28815b5ae29bSBram Moolenaar 			}
28825b5ae29bSBram Moolenaar 		    }
28835b5ae29bSBram Moolenaar 		    else
28845b5ae29bSBram Moolenaar 		    {
28855b5ae29bSBram Moolenaar 			status = FAIL;
28865b5ae29bSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
28875b5ae29bSBram Moolenaar 			semsg(_(e_cannot_index_str),
28885b5ae29bSBram Moolenaar 						vartype_name(tv_dest->v_type));
28895b5ae29bSBram Moolenaar 		    }
28905b5ae29bSBram Moolenaar 
28915b5ae29bSBram Moolenaar 		    clear_tv(tv_idx1);
28925b5ae29bSBram Moolenaar 		    clear_tv(tv_idx2);
28935b5ae29bSBram Moolenaar 		    clear_tv(tv_dest);
28944c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= 3;
28955b5ae29bSBram Moolenaar 		    if (status == FAIL)
28965b5ae29bSBram Moolenaar 			goto on_error;
28975b5ae29bSBram Moolenaar 		}
28985b5ae29bSBram Moolenaar 		break;
28995b5ae29bSBram Moolenaar 
29008a7d6542SBram Moolenaar 	    // push constant
29018a7d6542SBram Moolenaar 	    case ISN_PUSHNR:
29028a7d6542SBram Moolenaar 	    case ISN_PUSHBOOL:
29038a7d6542SBram Moolenaar 	    case ISN_PUSHSPEC:
29048a7d6542SBram Moolenaar 	    case ISN_PUSHF:
29058a7d6542SBram Moolenaar 	    case ISN_PUSHS:
29068a7d6542SBram Moolenaar 	    case ISN_PUSHBLOB:
290742a480bfSBram Moolenaar 	    case ISN_PUSHFUNC:
290842a480bfSBram Moolenaar 	    case ISN_PUSHCHANNEL:
290942a480bfSBram Moolenaar 	    case ISN_PUSHJOB:
291035578168SBram Moolenaar 		if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2911cbe178e3SBram Moolenaar 		    goto theend;
29128a7d6542SBram Moolenaar 		tv = STACK_TV_BOT(0);
29132f8ce0aeSBram Moolenaar 		tv->v_lock = 0;
29144c137214SBram Moolenaar 		++ectx->ec_stack.ga_len;
29158a7d6542SBram Moolenaar 		switch (iptr->isn_type)
29168a7d6542SBram Moolenaar 		{
29178a7d6542SBram Moolenaar 		    case ISN_PUSHNR:
29188a7d6542SBram Moolenaar 			tv->v_type = VAR_NUMBER;
29198a7d6542SBram Moolenaar 			tv->vval.v_number = iptr->isn_arg.number;
29208a7d6542SBram Moolenaar 			break;
29218a7d6542SBram Moolenaar 		    case ISN_PUSHBOOL:
29228a7d6542SBram Moolenaar 			tv->v_type = VAR_BOOL;
29238a7d6542SBram Moolenaar 			tv->vval.v_number = iptr->isn_arg.number;
29248a7d6542SBram Moolenaar 			break;
29258a7d6542SBram Moolenaar 		    case ISN_PUSHSPEC:
29268a7d6542SBram Moolenaar 			tv->v_type = VAR_SPECIAL;
29278a7d6542SBram Moolenaar 			tv->vval.v_number = iptr->isn_arg.number;
29288a7d6542SBram Moolenaar 			break;
29298a7d6542SBram Moolenaar #ifdef FEAT_FLOAT
29308a7d6542SBram Moolenaar 		    case ISN_PUSHF:
29318a7d6542SBram Moolenaar 			tv->v_type = VAR_FLOAT;
29328a7d6542SBram Moolenaar 			tv->vval.v_float = iptr->isn_arg.fnumber;
29338a7d6542SBram Moolenaar 			break;
29348a7d6542SBram Moolenaar #endif
29358a7d6542SBram Moolenaar 		    case ISN_PUSHBLOB:
29368a7d6542SBram Moolenaar 			blob_copy(iptr->isn_arg.blob, tv);
29378a7d6542SBram Moolenaar 			break;
293842a480bfSBram Moolenaar 		    case ISN_PUSHFUNC:
293942a480bfSBram Moolenaar 			tv->v_type = VAR_FUNC;
2940087d2e15SBram Moolenaar 			if (iptr->isn_arg.string == NULL)
2941087d2e15SBram Moolenaar 			    tv->vval.v_string = NULL;
2942087d2e15SBram Moolenaar 			else
2943087d2e15SBram Moolenaar 			    tv->vval.v_string =
2944087d2e15SBram Moolenaar 					     vim_strsave(iptr->isn_arg.string);
294542a480bfSBram Moolenaar 			break;
294642a480bfSBram Moolenaar 		    case ISN_PUSHCHANNEL:
294742a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL
294842a480bfSBram Moolenaar 			tv->v_type = VAR_CHANNEL;
294942a480bfSBram Moolenaar 			tv->vval.v_channel = iptr->isn_arg.channel;
295042a480bfSBram Moolenaar 			if (tv->vval.v_channel != NULL)
295142a480bfSBram Moolenaar 			    ++tv->vval.v_channel->ch_refcount;
295242a480bfSBram Moolenaar #endif
295342a480bfSBram Moolenaar 			break;
295442a480bfSBram Moolenaar 		    case ISN_PUSHJOB:
295542a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL
295642a480bfSBram Moolenaar 			tv->v_type = VAR_JOB;
295742a480bfSBram Moolenaar 			tv->vval.v_job = iptr->isn_arg.job;
295842a480bfSBram Moolenaar 			if (tv->vval.v_job != NULL)
295942a480bfSBram Moolenaar 			    ++tv->vval.v_job->jv_refcount;
296042a480bfSBram Moolenaar #endif
296142a480bfSBram Moolenaar 			break;
29628a7d6542SBram Moolenaar 		    default:
29638a7d6542SBram Moolenaar 			tv->v_type = VAR_STRING;
2964e69f6d04SBram Moolenaar 			tv->vval.v_string = vim_strsave(
2965e69f6d04SBram Moolenaar 				iptr->isn_arg.string == NULL
2966e69f6d04SBram Moolenaar 					? (char_u *)"" : iptr->isn_arg.string);
29678a7d6542SBram Moolenaar 		}
29688a7d6542SBram Moolenaar 		break;
29698a7d6542SBram Moolenaar 
2970d72c1bf0SBram Moolenaar 	    case ISN_UNLET:
2971d72c1bf0SBram Moolenaar 		if (do_unlet(iptr->isn_arg.unlet.ul_name,
2972d72c1bf0SBram Moolenaar 				       iptr->isn_arg.unlet.ul_forceit) == FAIL)
2973e859312eSBram Moolenaar 		    goto on_error;
2974d72c1bf0SBram Moolenaar 		break;
29757bdaea6eSBram Moolenaar 	    case ISN_UNLETENV:
29767bdaea6eSBram Moolenaar 		vim_unsetenv(iptr->isn_arg.unlet.ul_name);
29777bdaea6eSBram Moolenaar 		break;
2978d72c1bf0SBram Moolenaar 
2979aacc966cSBram Moolenaar 	    case ISN_LOCKUNLOCK:
2980aacc966cSBram Moolenaar 		{
2981aacc966cSBram Moolenaar 		    typval_T	*lval_root_save = lval_root;
2982aacc966cSBram Moolenaar 		    int		res;
2983aacc966cSBram Moolenaar 
2984aacc966cSBram Moolenaar 		    // Stack has the local variable, argument the whole :lock
2985aacc966cSBram Moolenaar 		    // or :unlock command, like ISN_EXEC.
2986aacc966cSBram Moolenaar 		    --ectx->ec_stack.ga_len;
2987aacc966cSBram Moolenaar 		    lval_root = STACK_TV_BOT(0);
2988aacc966cSBram Moolenaar 		    res = exec_command(iptr);
2989aacc966cSBram Moolenaar 		    clear_tv(lval_root);
2990aacc966cSBram Moolenaar 		    lval_root = lval_root_save;
2991aacc966cSBram Moolenaar 		    if (res == FAIL)
2992aacc966cSBram Moolenaar 			goto on_error;
2993aacc966cSBram Moolenaar 		}
2994aacc966cSBram Moolenaar 		break;
2995aacc966cSBram Moolenaar 
29960b4c66c6SBram Moolenaar 	    case ISN_LOCKCONST:
29970b4c66c6SBram Moolenaar 		item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE);
29980b4c66c6SBram Moolenaar 		break;
29990b4c66c6SBram Moolenaar 
30008a7d6542SBram Moolenaar 	    // create a list from items on the stack; uses a single allocation
30018a7d6542SBram Moolenaar 	    // for the list header and the items
30028a7d6542SBram Moolenaar 	    case ISN_NEWLIST:
30034c137214SBram Moolenaar 		if (exe_newlist(iptr->isn_arg.number, ectx) == FAIL)
3004cbe178e3SBram Moolenaar 		    goto theend;
30058a7d6542SBram Moolenaar 		break;
30068a7d6542SBram Moolenaar 
30078a7d6542SBram Moolenaar 	    // create a dict from items on the stack
30088a7d6542SBram Moolenaar 	    case ISN_NEWDICT:
30098a7d6542SBram Moolenaar 		{
30108a7d6542SBram Moolenaar 		    int		count = iptr->isn_arg.number;
30118a7d6542SBram Moolenaar 		    dict_T	*dict = dict_alloc();
30128a7d6542SBram Moolenaar 		    dictitem_T	*item;
3013c7f7f6dbSBram Moolenaar 		    char_u	*key;
30144c137214SBram Moolenaar 		    int		idx;
30158a7d6542SBram Moolenaar 
30165a9e5845SDominique Pelle 		    if (unlikely(dict == NULL))
3017cbe178e3SBram Moolenaar 			goto theend;
30188a7d6542SBram Moolenaar 		    for (idx = 0; idx < count; ++idx)
30198a7d6542SBram Moolenaar 		    {
3020e859312eSBram Moolenaar 			// have already checked key type is VAR_STRING
30218a7d6542SBram Moolenaar 			tv = STACK_TV_BOT(2 * (idx - count));
3022e859312eSBram Moolenaar 			// check key is unique
3023c7f7f6dbSBram Moolenaar 			key = tv->vval.v_string == NULL
3024c7f7f6dbSBram Moolenaar 					    ? (char_u *)"" : tv->vval.v_string;
3025c7f7f6dbSBram Moolenaar 			item = dict_find(dict, key, -1);
3026e859312eSBram Moolenaar 			if (item != NULL)
3027e859312eSBram Moolenaar 			{
30287517ffdbSBram Moolenaar 			    SOURCING_LNUM = iptr->isn_lnum;
3029c7f7f6dbSBram Moolenaar 			    semsg(_(e_duplicate_key), key);
3030e859312eSBram Moolenaar 			    dict_unref(dict);
3031e859312eSBram Moolenaar 			    goto on_error;
3032e859312eSBram Moolenaar 			}
3033c7f7f6dbSBram Moolenaar 			item = dictitem_alloc(key);
30348a7d6542SBram Moolenaar 			clear_tv(tv);
30355a9e5845SDominique Pelle 			if (unlikely(item == NULL))
3036e859312eSBram Moolenaar 			{
3037e859312eSBram Moolenaar 			    dict_unref(dict);
3038cbe178e3SBram Moolenaar 			    goto theend;
3039e859312eSBram Moolenaar 			}
30408a7d6542SBram Moolenaar 			item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
30418a7d6542SBram Moolenaar 			item->di_tv.v_lock = 0;
30428a7d6542SBram Moolenaar 			if (dict_add(dict, item) == FAIL)
3043e859312eSBram Moolenaar 			{
3044d032f34aSBram Moolenaar 			    // can this ever happen?
3045e859312eSBram Moolenaar 			    dict_unref(dict);
3046cbe178e3SBram Moolenaar 			    goto theend;
30478a7d6542SBram Moolenaar 			}
3048e859312eSBram Moolenaar 		    }
30498a7d6542SBram Moolenaar 
30508a7d6542SBram Moolenaar 		    if (count > 0)
30514c137214SBram Moolenaar 			ectx->ec_stack.ga_len -= 2 * count - 1;
305235578168SBram Moolenaar 		    else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3053cbe178e3SBram Moolenaar 			goto theend;
30548a7d6542SBram Moolenaar 		    else
30554c137214SBram Moolenaar 			++ectx->ec_stack.ga_len;
30568a7d6542SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
30578a7d6542SBram Moolenaar 		    tv->v_type = VAR_DICT;
30582f8ce0aeSBram Moolenaar 		    tv->v_lock = 0;
30598a7d6542SBram Moolenaar 		    tv->vval.v_dict = dict;
30608a7d6542SBram Moolenaar 		    ++dict->dv_refcount;
30618a7d6542SBram Moolenaar 		}
30628a7d6542SBram Moolenaar 		break;
30638a7d6542SBram Moolenaar 
30648a7d6542SBram Moolenaar 	    // call a :def function
30658a7d6542SBram Moolenaar 	    case ISN_DCALL:
3066dfa3d552SBram Moolenaar 		SOURCING_LNUM = iptr->isn_lnum;
30672fecb531SBram Moolenaar 		if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
30682fecb531SBram Moolenaar 				NULL,
30698a7d6542SBram Moolenaar 				iptr->isn_arg.dfunc.cdf_argcount,
30704c137214SBram Moolenaar 				ectx) == FAIL)
3071e859312eSBram Moolenaar 		    goto on_error;
30728a7d6542SBram Moolenaar 		break;
30738a7d6542SBram Moolenaar 
30748a7d6542SBram Moolenaar 	    // call a builtin function
30758a7d6542SBram Moolenaar 	    case ISN_BCALL:
30768a7d6542SBram Moolenaar 		SOURCING_LNUM = iptr->isn_lnum;
30778a7d6542SBram Moolenaar 		if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
30788a7d6542SBram Moolenaar 			      iptr->isn_arg.bfunc.cbf_argcount,
30794c137214SBram Moolenaar 			      ectx) == FAIL)
3080d032f34aSBram Moolenaar 		    goto on_error;
30818a7d6542SBram Moolenaar 		break;
30828a7d6542SBram Moolenaar 
30838a7d6542SBram Moolenaar 	    // call a funcref or partial
30848a7d6542SBram Moolenaar 	    case ISN_PCALL:
30858a7d6542SBram Moolenaar 		{
30868a7d6542SBram Moolenaar 		    cpfunc_T	*pfunc = &iptr->isn_arg.pfunc;
30878a7d6542SBram Moolenaar 		    int		r;
30886f5b6dfbSBram Moolenaar 		    typval_T	partial_tv;
30898a7d6542SBram Moolenaar 
30908a7d6542SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
30918a7d6542SBram Moolenaar 		    if (pfunc->cpf_top)
30928a7d6542SBram Moolenaar 		    {
30938a7d6542SBram Moolenaar 			// funcref is above the arguments
30948a7d6542SBram Moolenaar 			tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
30958a7d6542SBram Moolenaar 		    }
30968a7d6542SBram Moolenaar 		    else
30978a7d6542SBram Moolenaar 		    {
30988a7d6542SBram Moolenaar 			// Get the funcref from the stack.
30994c137214SBram Moolenaar 			--ectx->ec_stack.ga_len;
31006f5b6dfbSBram Moolenaar 			partial_tv = *STACK_TV_BOT(0);
31016f5b6dfbSBram Moolenaar 			tv = &partial_tv;
31028a7d6542SBram Moolenaar 		    }
31034c137214SBram Moolenaar 		    r = call_partial(tv, pfunc->cpf_argcount, ectx);
31046f5b6dfbSBram Moolenaar 		    if (tv == &partial_tv)
31056f5b6dfbSBram Moolenaar 			clear_tv(&partial_tv);
31068a7d6542SBram Moolenaar 		    if (r == FAIL)
3107d032f34aSBram Moolenaar 			goto on_error;
3108bd5da371SBram Moolenaar 		}
3109bd5da371SBram Moolenaar 		break;
31108a7d6542SBram Moolenaar 
3111bd5da371SBram Moolenaar 	    case ISN_PCALL_END:
3112bd5da371SBram Moolenaar 		// PCALL finished, arguments have been consumed and replaced by
3113bd5da371SBram Moolenaar 		// the return value.  Now clear the funcref from the stack,
3114bd5da371SBram Moolenaar 		// and move the return value in its place.
31154c137214SBram Moolenaar 		--ectx->ec_stack.ga_len;
3116bd5da371SBram Moolenaar 		clear_tv(STACK_TV_BOT(-1));
31178a7d6542SBram Moolenaar 		*STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
31188a7d6542SBram Moolenaar 		break;
31198a7d6542SBram Moolenaar 
31208a7d6542SBram Moolenaar 	    // call a user defined function or funcref/partial
31218a7d6542SBram Moolenaar 	    case ISN_UCALL:
31228a7d6542SBram Moolenaar 		{
31238a7d6542SBram Moolenaar 		    cufunc_T	*cufunc = &iptr->isn_arg.ufunc;
31248a7d6542SBram Moolenaar 
31258a7d6542SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
31262fecb531SBram Moolenaar 		    if (call_eval_func(cufunc->cuf_name, cufunc->cuf_argcount,
31274c137214SBram Moolenaar 							   ectx, iptr) == FAIL)
3128d032f34aSBram Moolenaar 			goto on_error;
31298a7d6542SBram Moolenaar 		}
31308a7d6542SBram Moolenaar 		break;
31318a7d6542SBram Moolenaar 
3132f57b43c2SBram Moolenaar 	    // return from a :def function call without a value
3133f57b43c2SBram Moolenaar 	    case ISN_RETURN_VOID:
313435578168SBram Moolenaar 		if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3135cbe178e3SBram Moolenaar 		    goto theend;
3136299f3036SBram Moolenaar 		tv = STACK_TV_BOT(0);
31374c137214SBram Moolenaar 		++ectx->ec_stack.ga_len;
3138f57b43c2SBram Moolenaar 		tv->v_type = VAR_VOID;
3139299f3036SBram Moolenaar 		tv->vval.v_number = 0;
3140299f3036SBram Moolenaar 		tv->v_lock = 0;
3141299f3036SBram Moolenaar 		// FALLTHROUGH
3142299f3036SBram Moolenaar 
3143f57b43c2SBram Moolenaar 	    // return from a :def function call with what is on the stack
31448a7d6542SBram Moolenaar 	    case ISN_RETURN:
31458a7d6542SBram Moolenaar 		{
31464c137214SBram Moolenaar 		    garray_T	*trystack = &ectx->ec_trystack;
314720431c9dSBram Moolenaar 		    trycmd_T    *trycmd = NULL;
31488cbd6dfcSBram Moolenaar 
31498cbd6dfcSBram Moolenaar 		    if (trystack->ga_len > 0)
31508cbd6dfcSBram Moolenaar 			trycmd = ((trycmd_T *)trystack->ga_data)
31518cbd6dfcSBram Moolenaar 							+ trystack->ga_len - 1;
3152bf67ea1aSBram Moolenaar 		    if (trycmd != NULL
31534c137214SBram Moolenaar 				 && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
31548a7d6542SBram Moolenaar 		    {
31559cb577a6SBram Moolenaar 			// jump to ":finally" or ":endtry"
31569cb577a6SBram Moolenaar 			if (trycmd->tcd_finally_idx != 0)
31574c137214SBram Moolenaar 			    ectx->ec_iidx = trycmd->tcd_finally_idx;
31589cb577a6SBram Moolenaar 			else
31594c137214SBram Moolenaar 			    ectx->ec_iidx = trycmd->tcd_endtry_idx;
31608a7d6542SBram Moolenaar 			trycmd->tcd_return = TRUE;
31618a7d6542SBram Moolenaar 		    }
31628a7d6542SBram Moolenaar 		    else
3163d032f34aSBram Moolenaar 			goto func_return;
31648a7d6542SBram Moolenaar 		}
31658a7d6542SBram Moolenaar 		break;
31668a7d6542SBram Moolenaar 
3167c04f2a4cSBram Moolenaar 	    // push a partial, a reference to a compiled function
31688a7d6542SBram Moolenaar 	    case ISN_FUNCREF:
31698a7d6542SBram Moolenaar 		{
3170f112f30aSBram Moolenaar 		    partial_T   *pt = ALLOC_CLEAR_ONE(partial_T);
3171f112f30aSBram Moolenaar 		    dfunc_T	*pt_dfunc = ((dfunc_T *)def_functions.ga_data)
3172f112f30aSBram Moolenaar 					       + iptr->isn_arg.funcref.fr_func;
31738a7d6542SBram Moolenaar 
31748a7d6542SBram Moolenaar 		    if (pt == NULL)
3175cbe178e3SBram Moolenaar 			goto theend;
317635578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3177c8cd2b34SBram Moolenaar 		    {
3178bf67ea1aSBram Moolenaar 			vim_free(pt);
3179cbe178e3SBram Moolenaar 			goto theend;
3180bf67ea1aSBram Moolenaar 		    }
3181f112f30aSBram Moolenaar 		    if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc,
31824c137214SBram Moolenaar 								 ectx) == FAIL)
3183cbe178e3SBram Moolenaar 			goto theend;
31848a7d6542SBram Moolenaar 		    tv = STACK_TV_BOT(0);
31854c137214SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
31868a7d6542SBram Moolenaar 		    tv->vval.v_partial = pt;
31878a7d6542SBram Moolenaar 		    tv->v_type = VAR_PARTIAL;
31882f8ce0aeSBram Moolenaar 		    tv->v_lock = 0;
31898a7d6542SBram Moolenaar 		}
31908a7d6542SBram Moolenaar 		break;
31918a7d6542SBram Moolenaar 
319238ddf333SBram Moolenaar 	    // Create a global function from a lambda.
319338ddf333SBram Moolenaar 	    case ISN_NEWFUNC:
319438ddf333SBram Moolenaar 		{
319538ddf333SBram Moolenaar 		    newfunc_T	*newfunc = &iptr->isn_arg.newfunc;
319638ddf333SBram Moolenaar 
3197cd45ed03SBram Moolenaar 		    if (copy_func(newfunc->nf_lambda, newfunc->nf_global,
31984c137214SBram Moolenaar 								 ectx) == FAIL)
3199cbe178e3SBram Moolenaar 			goto theend;
320038ddf333SBram Moolenaar 		}
320138ddf333SBram Moolenaar 		break;
320238ddf333SBram Moolenaar 
32036abdcf82SBram Moolenaar 	    // List functions
32046abdcf82SBram Moolenaar 	    case ISN_DEF:
32056abdcf82SBram Moolenaar 		if (iptr->isn_arg.string == NULL)
32066abdcf82SBram Moolenaar 		    list_functions(NULL);
32076abdcf82SBram Moolenaar 		else
32086abdcf82SBram Moolenaar 		{
32096abdcf82SBram Moolenaar 		    exarg_T ea;
32106abdcf82SBram Moolenaar 
32116abdcf82SBram Moolenaar 		    CLEAR_FIELD(ea);
32126abdcf82SBram Moolenaar 		    ea.cmd = ea.arg = iptr->isn_arg.string;
32136abdcf82SBram Moolenaar 		    define_function(&ea, NULL);
32146abdcf82SBram Moolenaar 		}
32156abdcf82SBram Moolenaar 		break;
32166abdcf82SBram Moolenaar 
32178a7d6542SBram Moolenaar 	    // jump if a condition is met
32188a7d6542SBram Moolenaar 	    case ISN_JUMP:
32198a7d6542SBram Moolenaar 		{
32208a7d6542SBram Moolenaar 		    jumpwhen_T	when = iptr->isn_arg.jump.jump_when;
32212bb2658bSBram Moolenaar 		    int		error = FALSE;
32228a7d6542SBram Moolenaar 		    int		jump = TRUE;
32238a7d6542SBram Moolenaar 
32248a7d6542SBram Moolenaar 		    if (when != JUMP_ALWAYS)
32258a7d6542SBram Moolenaar 		    {
32268a7d6542SBram Moolenaar 			tv = STACK_TV_BOT(-1);
32272bb2658bSBram Moolenaar 			if (when == JUMP_IF_COND_FALSE
322813106605SBram Moolenaar 				|| when == JUMP_IF_FALSE
32292bb2658bSBram Moolenaar 				|| when == JUMP_IF_COND_TRUE)
32302bb2658bSBram Moolenaar 			{
32312bb2658bSBram Moolenaar 			    SOURCING_LNUM = iptr->isn_lnum;
32322bb2658bSBram Moolenaar 			    jump = tv_get_bool_chk(tv, &error);
32332bb2658bSBram Moolenaar 			    if (error)
32342bb2658bSBram Moolenaar 				goto on_error;
32352bb2658bSBram Moolenaar 			}
32362bb2658bSBram Moolenaar 			else
32378a7d6542SBram Moolenaar 			    jump = tv2bool(tv);
32388a7d6542SBram Moolenaar 			if (when == JUMP_IF_FALSE
32392bb2658bSBram Moolenaar 					     || when == JUMP_AND_KEEP_IF_FALSE
32402bb2658bSBram Moolenaar 					     || when == JUMP_IF_COND_FALSE)
32418a7d6542SBram Moolenaar 			    jump = !jump;
3242777770fbSBram Moolenaar 			if (when == JUMP_IF_FALSE || !jump)
32438a7d6542SBram Moolenaar 			{
32448a7d6542SBram Moolenaar 			    // drop the value from the stack
32458a7d6542SBram Moolenaar 			    clear_tv(tv);
32464c137214SBram Moolenaar 			    --ectx->ec_stack.ga_len;
32478a7d6542SBram Moolenaar 			}
32488a7d6542SBram Moolenaar 		    }
32498a7d6542SBram Moolenaar 		    if (jump)
32504c137214SBram Moolenaar 			ectx->ec_iidx = iptr->isn_arg.jump.jump_where;
32518a7d6542SBram Moolenaar 		}
32528a7d6542SBram Moolenaar 		break;
32538a7d6542SBram Moolenaar 
325438a3bfa9SBram Moolenaar 	    // Jump if an argument with a default value was already set and not
325538a3bfa9SBram Moolenaar 	    // v:none.
325638a3bfa9SBram Moolenaar 	    case ISN_JUMP_IF_ARG_SET:
325738a3bfa9SBram Moolenaar 		tv = STACK_TV_VAR(iptr->isn_arg.jumparg.jump_arg_off);
325838a3bfa9SBram Moolenaar 		if (tv->v_type != VAR_UNKNOWN
325938a3bfa9SBram Moolenaar 			&& !(tv->v_type == VAR_SPECIAL
326038a3bfa9SBram Moolenaar 					    && tv->vval.v_number == VVAL_NONE))
32614c137214SBram Moolenaar 		    ectx->ec_iidx = iptr->isn_arg.jumparg.jump_where;
326238a3bfa9SBram Moolenaar 		break;
326338a3bfa9SBram Moolenaar 
32648a7d6542SBram Moolenaar 	    // top of a for loop
32658a7d6542SBram Moolenaar 	    case ISN_FOR:
32668a7d6542SBram Moolenaar 		{
326774e54fcbSBram Moolenaar 		    typval_T	*ltv = STACK_TV_BOT(-1);
32688a7d6542SBram Moolenaar 		    typval_T	*idxtv =
32698a7d6542SBram Moolenaar 				   STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);
32708a7d6542SBram Moolenaar 
327135578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3272cbe178e3SBram Moolenaar 			goto theend;
327374e54fcbSBram Moolenaar 		    if (ltv->v_type == VAR_LIST)
327474e54fcbSBram Moolenaar 		    {
327574e54fcbSBram Moolenaar 			list_T *list = ltv->vval.v_list;
327674e54fcbSBram Moolenaar 
327774e54fcbSBram Moolenaar 			// push the next item from the list
327877e5dcc3SBram Moolenaar 			++idxtv->vval.v_number;
327974e54fcbSBram Moolenaar 			if (list == NULL
328074e54fcbSBram Moolenaar 				       || idxtv->vval.v_number >= list->lv_len)
3281a91a7132SBram Moolenaar 			{
32828a7d6542SBram Moolenaar 			    // past the end of the list, jump to "endfor"
32834c137214SBram Moolenaar 			    ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
32844c137214SBram Moolenaar 			    may_restore_cmdmod(&ectx->ec_funclocal);
3285a91a7132SBram Moolenaar 			}
32868a7d6542SBram Moolenaar 			else if (list->lv_first == &range_list_item)
32878a7d6542SBram Moolenaar 			{
32888a7d6542SBram Moolenaar 			    // non-materialized range() list
32898a7d6542SBram Moolenaar 			    tv = STACK_TV_BOT(0);
32908a7d6542SBram Moolenaar 			    tv->v_type = VAR_NUMBER;
32912f8ce0aeSBram Moolenaar 			    tv->v_lock = 0;
32928a7d6542SBram Moolenaar 			    tv->vval.v_number = list_find_nr(
32938a7d6542SBram Moolenaar 					     list, idxtv->vval.v_number, NULL);
32944c137214SBram Moolenaar 			    ++ectx->ec_stack.ga_len;
32958a7d6542SBram Moolenaar 			}
32968a7d6542SBram Moolenaar 			else
32978a7d6542SBram Moolenaar 			{
329874e54fcbSBram Moolenaar 			    listitem_T *li = list_find(list,
329974e54fcbSBram Moolenaar 							 idxtv->vval.v_number);
33008a7d6542SBram Moolenaar 
33018a7d6542SBram Moolenaar 			    copy_tv(&li->li_tv, STACK_TV_BOT(0));
33024c137214SBram Moolenaar 			    ++ectx->ec_stack.ga_len;
33038a7d6542SBram Moolenaar 			}
33048a7d6542SBram Moolenaar 		    }
330574e54fcbSBram Moolenaar 		    else if (ltv->v_type == VAR_STRING)
330674e54fcbSBram Moolenaar 		    {
330774e54fcbSBram Moolenaar 			char_u	*str = ltv->vval.v_string;
330874e54fcbSBram Moolenaar 
3309d551d6c2SBram Moolenaar 			// The index is for the last byte of the previous
3310d551d6c2SBram Moolenaar 			// character.
331174e54fcbSBram Moolenaar 			++idxtv->vval.v_number;
3312175a41c1SBram Moolenaar 			if (str == NULL || str[idxtv->vval.v_number] == NUL)
331374e54fcbSBram Moolenaar 			{
331474e54fcbSBram Moolenaar 			    // past the end of the string, jump to "endfor"
33154c137214SBram Moolenaar 			    ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
33164c137214SBram Moolenaar 			    may_restore_cmdmod(&ectx->ec_funclocal);
331774e54fcbSBram Moolenaar 			}
331874e54fcbSBram Moolenaar 			else
331974e54fcbSBram Moolenaar 			{
332074e54fcbSBram Moolenaar 			    int	clen = mb_ptr2len(str + idxtv->vval.v_number);
332174e54fcbSBram Moolenaar 
3322d551d6c2SBram Moolenaar 			    // Push the next character from the string.
332374e54fcbSBram Moolenaar 			    tv = STACK_TV_BOT(0);
332474e54fcbSBram Moolenaar 			    tv->v_type = VAR_STRING;
332574e54fcbSBram Moolenaar 			    tv->vval.v_string = vim_strnsave(
332674e54fcbSBram Moolenaar 					     str + idxtv->vval.v_number, clen);
33274c137214SBram Moolenaar 			    ++ectx->ec_stack.ga_len;
332874e54fcbSBram Moolenaar 			    idxtv->vval.v_number += clen - 1;
332974e54fcbSBram Moolenaar 			}
333074e54fcbSBram Moolenaar 		    }
3331d551d6c2SBram Moolenaar 		    else if (ltv->v_type == VAR_BLOB)
3332d551d6c2SBram Moolenaar 		    {
3333d551d6c2SBram Moolenaar 			blob_T	*blob = ltv->vval.v_blob;
3334d551d6c2SBram Moolenaar 
3335d551d6c2SBram Moolenaar 			// When we get here the first time make a copy of the
3336d551d6c2SBram Moolenaar 			// blob, so that the iteration still works when it is
3337d551d6c2SBram Moolenaar 			// changed.
3338d551d6c2SBram Moolenaar 			if (idxtv->vval.v_number == -1 && blob != NULL)
3339d551d6c2SBram Moolenaar 			{
3340d551d6c2SBram Moolenaar 			    blob_copy(blob, ltv);
3341d551d6c2SBram Moolenaar 			    blob_unref(blob);
3342d551d6c2SBram Moolenaar 			    blob = ltv->vval.v_blob;
3343d551d6c2SBram Moolenaar 			}
3344d551d6c2SBram Moolenaar 
3345d551d6c2SBram Moolenaar 			// The index is for the previous byte.
3346d551d6c2SBram Moolenaar 			++idxtv->vval.v_number;
3347d551d6c2SBram Moolenaar 			if (blob == NULL
3348d551d6c2SBram Moolenaar 				     || idxtv->vval.v_number >= blob_len(blob))
3349d551d6c2SBram Moolenaar 			{
3350d551d6c2SBram Moolenaar 			    // past the end of the blob, jump to "endfor"
33514c137214SBram Moolenaar 			    ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
33524c137214SBram Moolenaar 			    may_restore_cmdmod(&ectx->ec_funclocal);
3353d551d6c2SBram Moolenaar 			}
335474e54fcbSBram Moolenaar 			else
335574e54fcbSBram Moolenaar 			{
3356d551d6c2SBram Moolenaar 			    // Push the next byte from the blob.
3357d551d6c2SBram Moolenaar 			    tv = STACK_TV_BOT(0);
3358d551d6c2SBram Moolenaar 			    tv->v_type = VAR_NUMBER;
3359d551d6c2SBram Moolenaar 			    tv->vval.v_number = blob_get(blob,
3360d551d6c2SBram Moolenaar 							 idxtv->vval.v_number);
33614c137214SBram Moolenaar 			    ++ectx->ec_stack.ga_len;
3362d551d6c2SBram Moolenaar 			}
3363d551d6c2SBram Moolenaar 		    }
3364d551d6c2SBram Moolenaar 		    else
3365d551d6c2SBram Moolenaar 		    {
336674e54fcbSBram Moolenaar 			semsg(_(e_for_loop_on_str_not_supported),
336774e54fcbSBram Moolenaar 						    vartype_name(ltv->v_type));
3368cbe178e3SBram Moolenaar 			goto theend;
336974e54fcbSBram Moolenaar 		    }
337074e54fcbSBram Moolenaar 		}
33718a7d6542SBram Moolenaar 		break;
33728a7d6542SBram Moolenaar 
33738a7d6542SBram Moolenaar 	    // start of ":try" block
33748a7d6542SBram Moolenaar 	    case ISN_TRY:
33758a7d6542SBram Moolenaar 		{
337620431c9dSBram Moolenaar 		    trycmd_T    *trycmd = NULL;
337720431c9dSBram Moolenaar 
337835578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_trystack, 1))
3379cbe178e3SBram Moolenaar 			goto theend;
33804c137214SBram Moolenaar 		    trycmd = ((trycmd_T *)ectx->ec_trystack.ga_data)
33814c137214SBram Moolenaar 						     + ectx->ec_trystack.ga_len;
33824c137214SBram Moolenaar 		    ++ectx->ec_trystack.ga_len;
33838a7d6542SBram Moolenaar 		    ++trylevel;
33848d4be890SBram Moolenaar 		    CLEAR_POINTER(trycmd);
33854c137214SBram Moolenaar 		    trycmd->tcd_frame_idx = ectx->ec_frame_idx;
33864c137214SBram Moolenaar 		    trycmd->tcd_stack_len = ectx->ec_stack.ga_len;
3387a91a7132SBram Moolenaar 		    trycmd->tcd_catch_idx =
3388a91a7132SBram Moolenaar 					  iptr->isn_arg.try.try_ref->try_catch;
3389a91a7132SBram Moolenaar 		    trycmd->tcd_finally_idx =
3390a91a7132SBram Moolenaar 					iptr->isn_arg.try.try_ref->try_finally;
3391a91a7132SBram Moolenaar 		    trycmd->tcd_endtry_idx =
3392a91a7132SBram Moolenaar 					 iptr->isn_arg.try.try_ref->try_endtry;
33938a7d6542SBram Moolenaar 		}
33948a7d6542SBram Moolenaar 		break;
33958a7d6542SBram Moolenaar 
33968a7d6542SBram Moolenaar 	    case ISN_PUSHEXC:
33978a7d6542SBram Moolenaar 		if (current_exception == NULL)
33988a7d6542SBram Moolenaar 		{
33997517ffdbSBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
34008a7d6542SBram Moolenaar 		    iemsg("Evaluating catch while current_exception is NULL");
3401cbe178e3SBram Moolenaar 		    goto theend;
34028a7d6542SBram Moolenaar 		}
340335578168SBram Moolenaar 		if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3404cbe178e3SBram Moolenaar 		    goto theend;
34058a7d6542SBram Moolenaar 		tv = STACK_TV_BOT(0);
34064c137214SBram Moolenaar 		++ectx->ec_stack.ga_len;
34078a7d6542SBram Moolenaar 		tv->v_type = VAR_STRING;
34082f8ce0aeSBram Moolenaar 		tv->v_lock = 0;
34098a7d6542SBram Moolenaar 		tv->vval.v_string = vim_strsave(
34108a7d6542SBram Moolenaar 					   (char_u *)current_exception->value);
34118a7d6542SBram Moolenaar 		break;
34128a7d6542SBram Moolenaar 
34138a7d6542SBram Moolenaar 	    case ISN_CATCH:
34148a7d6542SBram Moolenaar 		{
34154c137214SBram Moolenaar 		    garray_T	*trystack = &ectx->ec_trystack;
34168a7d6542SBram Moolenaar 
34174c137214SBram Moolenaar 		    may_restore_cmdmod(&ectx->ec_funclocal);
34188a7d6542SBram Moolenaar 		    if (trystack->ga_len > 0)
34198a7d6542SBram Moolenaar 		    {
342020431c9dSBram Moolenaar 			trycmd_T    *trycmd = ((trycmd_T *)trystack->ga_data)
34218a7d6542SBram Moolenaar 							+ trystack->ga_len - 1;
34228a7d6542SBram Moolenaar 			trycmd->tcd_caught = TRUE;
3423d3d8feebSBram Moolenaar 			trycmd->tcd_did_throw = FALSE;
34248a7d6542SBram Moolenaar 		    }
34258a7d6542SBram Moolenaar 		    did_emsg = got_int = did_throw = FALSE;
34261430ceebSBram Moolenaar 		    force_abort = need_rethrow = FALSE;
34278a7d6542SBram Moolenaar 		    catch_exception(current_exception);
34288a7d6542SBram Moolenaar 		}
34298a7d6542SBram Moolenaar 		break;
34308a7d6542SBram Moolenaar 
3431c150c09eSBram Moolenaar 	    case ISN_TRYCONT:
3432c150c09eSBram Moolenaar 		{
34334c137214SBram Moolenaar 		    garray_T	*trystack = &ectx->ec_trystack;
3434c150c09eSBram Moolenaar 		    trycont_T	*trycont = &iptr->isn_arg.trycont;
3435c150c09eSBram Moolenaar 		    int		i;
3436c150c09eSBram Moolenaar 		    trycmd_T    *trycmd;
3437c150c09eSBram Moolenaar 		    int		iidx = trycont->tct_where;
3438c150c09eSBram Moolenaar 
3439c150c09eSBram Moolenaar 		    if (trystack->ga_len < trycont->tct_levels)
3440c150c09eSBram Moolenaar 		    {
3441c150c09eSBram Moolenaar 			siemsg("TRYCONT: expected %d levels, found %d",
3442c150c09eSBram Moolenaar 					trycont->tct_levels, trystack->ga_len);
3443cbe178e3SBram Moolenaar 			goto theend;
3444c150c09eSBram Moolenaar 		    }
3445c150c09eSBram Moolenaar 		    // Make :endtry jump to any outer try block and the last
3446c150c09eSBram Moolenaar 		    // :endtry inside the loop to the loop start.
3447c150c09eSBram Moolenaar 		    for (i = trycont->tct_levels; i > 0; --i)
3448c150c09eSBram Moolenaar 		    {
3449c150c09eSBram Moolenaar 			trycmd = ((trycmd_T *)trystack->ga_data)
3450c150c09eSBram Moolenaar 							+ trystack->ga_len - i;
34512e34c34bSBram Moolenaar 			// Add one to tcd_cont to be able to jump to
34522e34c34bSBram Moolenaar 			// instruction with index zero.
34532e34c34bSBram Moolenaar 			trycmd->tcd_cont = iidx + 1;
34547e82c5f3SBram Moolenaar 			iidx = trycmd->tcd_finally_idx == 0
34557e82c5f3SBram Moolenaar 			    ? trycmd->tcd_endtry_idx : trycmd->tcd_finally_idx;
3456c150c09eSBram Moolenaar 		    }
3457c150c09eSBram Moolenaar 		    // jump to :finally or :endtry of current try statement
34584c137214SBram Moolenaar 		    ectx->ec_iidx = iidx;
3459c150c09eSBram Moolenaar 		}
3460c150c09eSBram Moolenaar 		break;
3461c150c09eSBram Moolenaar 
34627e82c5f3SBram Moolenaar 	    case ISN_FINALLY:
34637e82c5f3SBram Moolenaar 		{
34644c137214SBram Moolenaar 		    garray_T	*trystack = &ectx->ec_trystack;
34657e82c5f3SBram Moolenaar 		    trycmd_T    *trycmd = ((trycmd_T *)trystack->ga_data)
34667e82c5f3SBram Moolenaar 							+ trystack->ga_len - 1;
34677e82c5f3SBram Moolenaar 
34687e82c5f3SBram Moolenaar 		    // Reset the index to avoid a return statement jumps here
34697e82c5f3SBram Moolenaar 		    // again.
34707e82c5f3SBram Moolenaar 		    trycmd->tcd_finally_idx = 0;
34717e82c5f3SBram Moolenaar 		    break;
34727e82c5f3SBram Moolenaar 		}
34737e82c5f3SBram Moolenaar 
34748a7d6542SBram Moolenaar 	    // end of ":try" block
34758a7d6542SBram Moolenaar 	    case ISN_ENDTRY:
34768a7d6542SBram Moolenaar 		{
34774c137214SBram Moolenaar 		    garray_T	*trystack = &ectx->ec_trystack;
34788a7d6542SBram Moolenaar 
34798a7d6542SBram Moolenaar 		    if (trystack->ga_len > 0)
34808a7d6542SBram Moolenaar 		    {
3481107e9cecSBram Moolenaar 			trycmd_T    *trycmd;
348220431c9dSBram Moolenaar 
34838a7d6542SBram Moolenaar 			--trystack->ga_len;
34848a7d6542SBram Moolenaar 			--trylevel;
34858a7d6542SBram Moolenaar 			trycmd = ((trycmd_T *)trystack->ga_data)
34868a7d6542SBram Moolenaar 							    + trystack->ga_len;
3487d3d8feebSBram Moolenaar 			if (trycmd->tcd_did_throw)
3488d3d8feebSBram Moolenaar 			    did_throw = TRUE;
3489f575adffSBram Moolenaar 			if (trycmd->tcd_caught && current_exception != NULL)
34908a7d6542SBram Moolenaar 			{
34918a7d6542SBram Moolenaar 			    // discard the exception
34928a7d6542SBram Moolenaar 			    if (caught_stack == current_exception)
34938a7d6542SBram Moolenaar 				caught_stack = caught_stack->caught;
34948a7d6542SBram Moolenaar 			    discard_current_exception();
34958a7d6542SBram Moolenaar 			}
34968a7d6542SBram Moolenaar 
34978a7d6542SBram Moolenaar 			if (trycmd->tcd_return)
3498d032f34aSBram Moolenaar 			    goto func_return;
3499d9d7789bSBram Moolenaar 
35004c137214SBram Moolenaar 			while (ectx->ec_stack.ga_len > trycmd->tcd_stack_len)
3501d9d7789bSBram Moolenaar 			{
35024c137214SBram Moolenaar 			    --ectx->ec_stack.ga_len;
3503d9d7789bSBram Moolenaar 			    clear_tv(STACK_TV_BOT(0));
3504d9d7789bSBram Moolenaar 			}
35058d4be890SBram Moolenaar 			if (trycmd->tcd_cont != 0)
3506c150c09eSBram Moolenaar 			    // handling :continue: jump to outer try block or
3507c150c09eSBram Moolenaar 			    // start of the loop
35084c137214SBram Moolenaar 			    ectx->ec_iidx = trycmd->tcd_cont - 1;
35098a7d6542SBram Moolenaar 		    }
35108a7d6542SBram Moolenaar 		}
35118a7d6542SBram Moolenaar 		break;
35128a7d6542SBram Moolenaar 
35138a7d6542SBram Moolenaar 	    case ISN_THROW:
35148f81b22eSBram Moolenaar 		{
35154c137214SBram Moolenaar 		    garray_T	*trystack = &ectx->ec_trystack;
3516107e9cecSBram Moolenaar 
3517107e9cecSBram Moolenaar 		    if (trystack->ga_len == 0 && trylevel == 0 && emsg_silent)
3518107e9cecSBram Moolenaar 		    {
3519107e9cecSBram Moolenaar 			// throwing an exception while using "silent!" causes
3520107e9cecSBram Moolenaar 			// the function to abort but not display an error.
35218f81b22eSBram Moolenaar 			tv = STACK_TV_BOT(-1);
35228f81b22eSBram Moolenaar 			clear_tv(tv);
35238f81b22eSBram Moolenaar 			tv->v_type = VAR_NUMBER;
35248f81b22eSBram Moolenaar 			tv->vval.v_number = 0;
35258f81b22eSBram Moolenaar 			goto done;
35268f81b22eSBram Moolenaar 		    }
35274c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
35288a7d6542SBram Moolenaar 		    tv = STACK_TV_BOT(0);
35291e021e63SBram Moolenaar 		    if (tv->vval.v_string == NULL
35301e021e63SBram Moolenaar 				       || *skipwhite(tv->vval.v_string) == NUL)
35311e021e63SBram Moolenaar 		    {
3532335e6713SBram Moolenaar 			vim_free(tv->vval.v_string);
35331dcae599SBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
35341e021e63SBram Moolenaar 			emsg(_(e_throw_with_empty_string));
3535cbe178e3SBram Moolenaar 			goto theend;
35361e021e63SBram Moolenaar 		    }
35371e021e63SBram Moolenaar 
3538107e9cecSBram Moolenaar 		    // Inside a "catch" we need to first discard the caught
3539107e9cecSBram Moolenaar 		    // exception.
3540107e9cecSBram Moolenaar 		    if (trystack->ga_len > 0)
3541107e9cecSBram Moolenaar 		    {
3542107e9cecSBram Moolenaar 			trycmd_T    *trycmd = ((trycmd_T *)trystack->ga_data)
3543107e9cecSBram Moolenaar 							+ trystack->ga_len - 1;
3544107e9cecSBram Moolenaar 			if (trycmd->tcd_caught && current_exception != NULL)
3545107e9cecSBram Moolenaar 			{
3546107e9cecSBram Moolenaar 			    // discard the exception
3547107e9cecSBram Moolenaar 			    if (caught_stack == current_exception)
3548107e9cecSBram Moolenaar 				caught_stack = caught_stack->caught;
3549107e9cecSBram Moolenaar 			    discard_current_exception();
3550107e9cecSBram Moolenaar 			    trycmd->tcd_caught = FALSE;
3551107e9cecSBram Moolenaar 			}
3552107e9cecSBram Moolenaar 		    }
3553107e9cecSBram Moolenaar 
3554107e9cecSBram Moolenaar 		    if (throw_exception(tv->vval.v_string, ET_USER, NULL)
3555107e9cecSBram Moolenaar 								       == FAIL)
35568a7d6542SBram Moolenaar 		    {
35578a7d6542SBram Moolenaar 			vim_free(tv->vval.v_string);
3558cbe178e3SBram Moolenaar 			goto theend;
35598a7d6542SBram Moolenaar 		    }
35608a7d6542SBram Moolenaar 		    did_throw = TRUE;
3561107e9cecSBram Moolenaar 		}
35628a7d6542SBram Moolenaar 		break;
35638a7d6542SBram Moolenaar 
35648a7d6542SBram Moolenaar 	    // compare with special values
35658a7d6542SBram Moolenaar 	    case ISN_COMPAREBOOL:
35668a7d6542SBram Moolenaar 	    case ISN_COMPARESPECIAL:
35678a7d6542SBram Moolenaar 		{
35688a7d6542SBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
35698a7d6542SBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
35708a7d6542SBram Moolenaar 		    varnumber_T arg1 = tv1->vval.v_number;
35718a7d6542SBram Moolenaar 		    varnumber_T arg2 = tv2->vval.v_number;
35728a7d6542SBram Moolenaar 		    int		res;
35738a7d6542SBram Moolenaar 
35748a7d6542SBram Moolenaar 		    switch (iptr->isn_arg.op.op_type)
35758a7d6542SBram Moolenaar 		    {
35768a7d6542SBram Moolenaar 			case EXPR_EQUAL: res = arg1 == arg2; break;
35778a7d6542SBram Moolenaar 			case EXPR_NEQUAL: res = arg1 != arg2; break;
35788a7d6542SBram Moolenaar 			default: res = 0; break;
35798a7d6542SBram Moolenaar 		    }
35808a7d6542SBram Moolenaar 
35814c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
35828a7d6542SBram Moolenaar 		    tv1->v_type = VAR_BOOL;
35838a7d6542SBram Moolenaar 		    tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
35848a7d6542SBram Moolenaar 		}
35858a7d6542SBram Moolenaar 		break;
35868a7d6542SBram Moolenaar 
35878a7d6542SBram Moolenaar 	    // Operation with two number arguments
35888a7d6542SBram Moolenaar 	    case ISN_OPNR:
35898a7d6542SBram Moolenaar 	    case ISN_COMPARENR:
35908a7d6542SBram Moolenaar 		{
35918a7d6542SBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
35928a7d6542SBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
35938a7d6542SBram Moolenaar 		    varnumber_T arg1 = tv1->vval.v_number;
35948a7d6542SBram Moolenaar 		    varnumber_T arg2 = tv2->vval.v_number;
3595fbeefb1bSBram Moolenaar 		    varnumber_T res = 0;
3596fbeefb1bSBram Moolenaar 		    int		div_zero = FALSE;
35978a7d6542SBram Moolenaar 
35988a7d6542SBram Moolenaar 		    switch (iptr->isn_arg.op.op_type)
35998a7d6542SBram Moolenaar 		    {
36008a7d6542SBram Moolenaar 			case EXPR_MULT: res = arg1 * arg2; break;
3601fbeefb1bSBram Moolenaar 			case EXPR_DIV:  if (arg2 == 0)
3602fbeefb1bSBram Moolenaar 					    div_zero = TRUE;
3603fbeefb1bSBram Moolenaar 					else
3604fbeefb1bSBram Moolenaar 					    res = arg1 / arg2;
3605fbeefb1bSBram Moolenaar 					break;
3606fbeefb1bSBram Moolenaar 			case EXPR_REM:  if (arg2 == 0)
3607fbeefb1bSBram Moolenaar 					    div_zero = TRUE;
3608fbeefb1bSBram Moolenaar 					else
3609fbeefb1bSBram Moolenaar 					    res = arg1 % arg2;
3610fbeefb1bSBram Moolenaar 					break;
36118a7d6542SBram Moolenaar 			case EXPR_SUB: res = arg1 - arg2; break;
36128a7d6542SBram Moolenaar 			case EXPR_ADD: res = arg1 + arg2; break;
36138a7d6542SBram Moolenaar 
36148a7d6542SBram Moolenaar 			case EXPR_EQUAL: res = arg1 == arg2; break;
36158a7d6542SBram Moolenaar 			case EXPR_NEQUAL: res = arg1 != arg2; break;
36168a7d6542SBram Moolenaar 			case EXPR_GREATER: res = arg1 > arg2; break;
36178a7d6542SBram Moolenaar 			case EXPR_GEQUAL: res = arg1 >= arg2; break;
36188a7d6542SBram Moolenaar 			case EXPR_SMALLER: res = arg1 < arg2; break;
36198a7d6542SBram Moolenaar 			case EXPR_SEQUAL: res = arg1 <= arg2; break;
3620fbeefb1bSBram Moolenaar 			default: break;
36218a7d6542SBram Moolenaar 		    }
36228a7d6542SBram Moolenaar 
36234c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
36248a7d6542SBram Moolenaar 		    if (iptr->isn_type == ISN_COMPARENR)
36258a7d6542SBram Moolenaar 		    {
36268a7d6542SBram Moolenaar 			tv1->v_type = VAR_BOOL;
36278a7d6542SBram Moolenaar 			tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
36288a7d6542SBram Moolenaar 		    }
36298a7d6542SBram Moolenaar 		    else
36308a7d6542SBram Moolenaar 			tv1->vval.v_number = res;
3631fbeefb1bSBram Moolenaar 		    if (div_zero)
3632fbeefb1bSBram Moolenaar 		    {
3633fbeefb1bSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
3634fbeefb1bSBram Moolenaar 			emsg(_(e_divide_by_zero));
3635fbeefb1bSBram Moolenaar 			goto on_error;
3636fbeefb1bSBram Moolenaar 		    }
36378a7d6542SBram Moolenaar 		}
36388a7d6542SBram Moolenaar 		break;
36398a7d6542SBram Moolenaar 
36408a7d6542SBram Moolenaar 	    // Computation with two float arguments
36418a7d6542SBram Moolenaar 	    case ISN_OPFLOAT:
36428a7d6542SBram Moolenaar 	    case ISN_COMPAREFLOAT:
3643a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT
36448a7d6542SBram Moolenaar 		{
36458a7d6542SBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
36468a7d6542SBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
36478a7d6542SBram Moolenaar 		    float_T	arg1 = tv1->vval.v_float;
36488a7d6542SBram Moolenaar 		    float_T	arg2 = tv2->vval.v_float;
36498a7d6542SBram Moolenaar 		    float_T	res = 0;
36508a7d6542SBram Moolenaar 		    int		cmp = FALSE;
36518a7d6542SBram Moolenaar 
36528a7d6542SBram Moolenaar 		    switch (iptr->isn_arg.op.op_type)
36538a7d6542SBram Moolenaar 		    {
36548a7d6542SBram Moolenaar 			case EXPR_MULT: res = arg1 * arg2; break;
36558a7d6542SBram Moolenaar 			case EXPR_DIV: res = arg1 / arg2; break;
36568a7d6542SBram Moolenaar 			case EXPR_SUB: res = arg1 - arg2; break;
36578a7d6542SBram Moolenaar 			case EXPR_ADD: res = arg1 + arg2; break;
36588a7d6542SBram Moolenaar 
36598a7d6542SBram Moolenaar 			case EXPR_EQUAL: cmp = arg1 == arg2; break;
36608a7d6542SBram Moolenaar 			case EXPR_NEQUAL: cmp = arg1 != arg2; break;
36618a7d6542SBram Moolenaar 			case EXPR_GREATER: cmp = arg1 > arg2; break;
36628a7d6542SBram Moolenaar 			case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
36638a7d6542SBram Moolenaar 			case EXPR_SMALLER: cmp = arg1 < arg2; break;
36648a7d6542SBram Moolenaar 			case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
36658a7d6542SBram Moolenaar 			default: cmp = 0; break;
36668a7d6542SBram Moolenaar 		    }
36674c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
36688a7d6542SBram Moolenaar 		    if (iptr->isn_type == ISN_COMPAREFLOAT)
36698a7d6542SBram Moolenaar 		    {
36708a7d6542SBram Moolenaar 			tv1->v_type = VAR_BOOL;
36718a7d6542SBram Moolenaar 			tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
36728a7d6542SBram Moolenaar 		    }
36738a7d6542SBram Moolenaar 		    else
36748a7d6542SBram Moolenaar 			tv1->vval.v_float = res;
36758a7d6542SBram Moolenaar 		}
3676a5d5953dSBram Moolenaar #endif
36778a7d6542SBram Moolenaar 		break;
36788a7d6542SBram Moolenaar 
36798a7d6542SBram Moolenaar 	    case ISN_COMPARELIST:
36808a7d6542SBram Moolenaar 		{
36818a7d6542SBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
36828a7d6542SBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
36838a7d6542SBram Moolenaar 		    list_T	*arg1 = tv1->vval.v_list;
36848a7d6542SBram Moolenaar 		    list_T	*arg2 = tv2->vval.v_list;
36858a7d6542SBram Moolenaar 		    int		cmp = FALSE;
36868a7d6542SBram Moolenaar 		    int		ic = iptr->isn_arg.op.op_ic;
36878a7d6542SBram Moolenaar 
36888a7d6542SBram Moolenaar 		    switch (iptr->isn_arg.op.op_type)
36898a7d6542SBram Moolenaar 		    {
36908a7d6542SBram Moolenaar 			case EXPR_EQUAL: cmp =
36918a7d6542SBram Moolenaar 				      list_equal(arg1, arg2, ic, FALSE); break;
36928a7d6542SBram Moolenaar 			case EXPR_NEQUAL: cmp =
36938a7d6542SBram Moolenaar 				     !list_equal(arg1, arg2, ic, FALSE); break;
36948a7d6542SBram Moolenaar 			case EXPR_IS: cmp = arg1 == arg2; break;
36958a7d6542SBram Moolenaar 			case EXPR_ISNOT: cmp = arg1 != arg2; break;
36968a7d6542SBram Moolenaar 			default: cmp = 0; break;
36978a7d6542SBram Moolenaar 		    }
36984c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
36998a7d6542SBram Moolenaar 		    clear_tv(tv1);
37008a7d6542SBram Moolenaar 		    clear_tv(tv2);
37018a7d6542SBram Moolenaar 		    tv1->v_type = VAR_BOOL;
37028a7d6542SBram Moolenaar 		    tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
37038a7d6542SBram Moolenaar 		}
37048a7d6542SBram Moolenaar 		break;
37058a7d6542SBram Moolenaar 
37068a7d6542SBram Moolenaar 	    case ISN_COMPAREBLOB:
37078a7d6542SBram Moolenaar 		{
37088a7d6542SBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
37098a7d6542SBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
37108a7d6542SBram Moolenaar 		    blob_T	*arg1 = tv1->vval.v_blob;
37118a7d6542SBram Moolenaar 		    blob_T	*arg2 = tv2->vval.v_blob;
37128a7d6542SBram Moolenaar 		    int		cmp = FALSE;
37138a7d6542SBram Moolenaar 
37148a7d6542SBram Moolenaar 		    switch (iptr->isn_arg.op.op_type)
37158a7d6542SBram Moolenaar 		    {
37168a7d6542SBram Moolenaar 			case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break;
37178a7d6542SBram Moolenaar 			case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break;
37188a7d6542SBram Moolenaar 			case EXPR_IS: cmp = arg1 == arg2; break;
37198a7d6542SBram Moolenaar 			case EXPR_ISNOT: cmp = arg1 != arg2; break;
37208a7d6542SBram Moolenaar 			default: cmp = 0; break;
37218a7d6542SBram Moolenaar 		    }
37224c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
37238a7d6542SBram Moolenaar 		    clear_tv(tv1);
37248a7d6542SBram Moolenaar 		    clear_tv(tv2);
37258a7d6542SBram Moolenaar 		    tv1->v_type = VAR_BOOL;
37268a7d6542SBram Moolenaar 		    tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
37278a7d6542SBram Moolenaar 		}
37288a7d6542SBram Moolenaar 		break;
37298a7d6542SBram Moolenaar 
37308a7d6542SBram Moolenaar 		// TODO: handle separately
37318a7d6542SBram Moolenaar 	    case ISN_COMPARESTRING:
37328a7d6542SBram Moolenaar 	    case ISN_COMPAREDICT:
37338a7d6542SBram Moolenaar 	    case ISN_COMPAREFUNC:
37348a7d6542SBram Moolenaar 	    case ISN_COMPAREANY:
37358a7d6542SBram Moolenaar 		{
37368a7d6542SBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
37378a7d6542SBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
3738657137caSBram Moolenaar 		    exprtype_T	exprtype = iptr->isn_arg.op.op_type;
37398a7d6542SBram Moolenaar 		    int		ic = iptr->isn_arg.op.op_ic;
37408a7d6542SBram Moolenaar 
3741eb26f433SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
3742657137caSBram Moolenaar 		    typval_compare(tv1, tv2, exprtype, ic);
37438a7d6542SBram Moolenaar 		    clear_tv(tv2);
37444c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
37458a7d6542SBram Moolenaar 		}
37468a7d6542SBram Moolenaar 		break;
37478a7d6542SBram Moolenaar 
37488a7d6542SBram Moolenaar 	    case ISN_ADDLIST:
37498a7d6542SBram Moolenaar 	    case ISN_ADDBLOB:
37508a7d6542SBram Moolenaar 		{
37518a7d6542SBram Moolenaar 		    typval_T *tv1 = STACK_TV_BOT(-2);
37528a7d6542SBram Moolenaar 		    typval_T *tv2 = STACK_TV_BOT(-1);
37538a7d6542SBram Moolenaar 
37541dcae599SBram Moolenaar 		    // add two lists or blobs
37558a7d6542SBram Moolenaar 		    if (iptr->isn_type == ISN_ADDLIST)
375607802044SBram Moolenaar 		    {
375707802044SBram Moolenaar 			if (iptr->isn_arg.op.op_type == EXPR_APPEND
375807802044SBram Moolenaar 						   && tv1->vval.v_list != NULL)
375907802044SBram Moolenaar 			    list_extend(tv1->vval.v_list, tv2->vval.v_list,
376007802044SBram Moolenaar 									 NULL);
376107802044SBram Moolenaar 			else
37628a7d6542SBram Moolenaar 			    eval_addlist(tv1, tv2);
376307802044SBram Moolenaar 		    }
37648a7d6542SBram Moolenaar 		    else
37658a7d6542SBram Moolenaar 			eval_addblob(tv1, tv2);
37668a7d6542SBram Moolenaar 		    clear_tv(tv2);
37674c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
37688a7d6542SBram Moolenaar 		}
37698a7d6542SBram Moolenaar 		break;
37708a7d6542SBram Moolenaar 
37711dcae599SBram Moolenaar 	    case ISN_LISTAPPEND:
37721dcae599SBram Moolenaar 		{
37731dcae599SBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
37741dcae599SBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
37751dcae599SBram Moolenaar 		    list_T	*l = tv1->vval.v_list;
37761dcae599SBram Moolenaar 
37771dcae599SBram Moolenaar 		    // add an item to a list
37781dcae599SBram Moolenaar 		    if (l == NULL)
37791dcae599SBram Moolenaar 		    {
37801dcae599SBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
37811dcae599SBram Moolenaar 			emsg(_(e_cannot_add_to_null_list));
37821dcae599SBram Moolenaar 			goto on_error;
37831dcae599SBram Moolenaar 		    }
37841dcae599SBram Moolenaar 		    if (list_append_tv(l, tv2) == FAIL)
3785cbe178e3SBram Moolenaar 			goto theend;
3786955347ccSBram Moolenaar 		    clear_tv(tv2);
37874c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
37881dcae599SBram Moolenaar 		}
37891dcae599SBram Moolenaar 		break;
37901dcae599SBram Moolenaar 
379180b0e5eaSBram Moolenaar 	    case ISN_BLOBAPPEND:
379280b0e5eaSBram Moolenaar 		{
379380b0e5eaSBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
379480b0e5eaSBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
379580b0e5eaSBram Moolenaar 		    blob_T	*b = tv1->vval.v_blob;
379680b0e5eaSBram Moolenaar 		    int		error = FALSE;
379780b0e5eaSBram Moolenaar 		    varnumber_T n;
379880b0e5eaSBram Moolenaar 
379980b0e5eaSBram Moolenaar 		    // add a number to a blob
380080b0e5eaSBram Moolenaar 		    if (b == NULL)
380180b0e5eaSBram Moolenaar 		    {
380280b0e5eaSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
380380b0e5eaSBram Moolenaar 			emsg(_(e_cannot_add_to_null_blob));
380480b0e5eaSBram Moolenaar 			goto on_error;
380580b0e5eaSBram Moolenaar 		    }
380680b0e5eaSBram Moolenaar 		    n = tv_get_number_chk(tv2, &error);
380780b0e5eaSBram Moolenaar 		    if (error)
380880b0e5eaSBram Moolenaar 			goto on_error;
380980b0e5eaSBram Moolenaar 		    ga_append(&b->bv_ga, (int)n);
38104c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
381180b0e5eaSBram Moolenaar 		}
381280b0e5eaSBram Moolenaar 		break;
381380b0e5eaSBram Moolenaar 
38148a7d6542SBram Moolenaar 	    // Computation with two arguments of unknown type
38158a7d6542SBram Moolenaar 	    case ISN_OPANY:
38168a7d6542SBram Moolenaar 		{
38178a7d6542SBram Moolenaar 		    typval_T	*tv1 = STACK_TV_BOT(-2);
38188a7d6542SBram Moolenaar 		    typval_T	*tv2 = STACK_TV_BOT(-1);
38198a7d6542SBram Moolenaar 		    varnumber_T	n1, n2;
38208a7d6542SBram Moolenaar #ifdef FEAT_FLOAT
38218a7d6542SBram Moolenaar 		    float_T	f1 = 0, f2 = 0;
38228a7d6542SBram Moolenaar #endif
38238a7d6542SBram Moolenaar 		    int		error = FALSE;
38248a7d6542SBram Moolenaar 
38258a7d6542SBram Moolenaar 		    if (iptr->isn_arg.op.op_type == EXPR_ADD)
38268a7d6542SBram Moolenaar 		    {
38278a7d6542SBram Moolenaar 			if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
38288a7d6542SBram Moolenaar 			{
38298a7d6542SBram Moolenaar 			    eval_addlist(tv1, tv2);
38308a7d6542SBram Moolenaar 			    clear_tv(tv2);
38314c137214SBram Moolenaar 			    --ectx->ec_stack.ga_len;
38328a7d6542SBram Moolenaar 			    break;
38338a7d6542SBram Moolenaar 			}
38348a7d6542SBram Moolenaar 			else if (tv1->v_type == VAR_BLOB
38358a7d6542SBram Moolenaar 						    && tv2->v_type == VAR_BLOB)
38368a7d6542SBram Moolenaar 			{
38378a7d6542SBram Moolenaar 			    eval_addblob(tv1, tv2);
38388a7d6542SBram Moolenaar 			    clear_tv(tv2);
38394c137214SBram Moolenaar 			    --ectx->ec_stack.ga_len;
38408a7d6542SBram Moolenaar 			    break;
38418a7d6542SBram Moolenaar 			}
38428a7d6542SBram Moolenaar 		    }
38438a7d6542SBram Moolenaar #ifdef FEAT_FLOAT
38448a7d6542SBram Moolenaar 		    if (tv1->v_type == VAR_FLOAT)
38458a7d6542SBram Moolenaar 		    {
38468a7d6542SBram Moolenaar 			f1 = tv1->vval.v_float;
38478a7d6542SBram Moolenaar 			n1 = 0;
38488a7d6542SBram Moolenaar 		    }
38498a7d6542SBram Moolenaar 		    else
38508a7d6542SBram Moolenaar #endif
38518a7d6542SBram Moolenaar 		    {
3852f665e97fSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
38538a7d6542SBram Moolenaar 			n1 = tv_get_number_chk(tv1, &error);
38548a7d6542SBram Moolenaar 			if (error)
3855d032f34aSBram Moolenaar 			    goto on_error;
38568a7d6542SBram Moolenaar #ifdef FEAT_FLOAT
38578a7d6542SBram Moolenaar 			if (tv2->v_type == VAR_FLOAT)
38588a7d6542SBram Moolenaar 			    f1 = n1;
38598a7d6542SBram Moolenaar #endif
38608a7d6542SBram Moolenaar 		    }
38618a7d6542SBram Moolenaar #ifdef FEAT_FLOAT
38628a7d6542SBram Moolenaar 		    if (tv2->v_type == VAR_FLOAT)
38638a7d6542SBram Moolenaar 		    {
38648a7d6542SBram Moolenaar 			f2 = tv2->vval.v_float;
38658a7d6542SBram Moolenaar 			n2 = 0;
38668a7d6542SBram Moolenaar 		    }
38678a7d6542SBram Moolenaar 		    else
38688a7d6542SBram Moolenaar #endif
38698a7d6542SBram Moolenaar 		    {
38708a7d6542SBram Moolenaar 			n2 = tv_get_number_chk(tv2, &error);
38718a7d6542SBram Moolenaar 			if (error)
3872d032f34aSBram Moolenaar 			    goto on_error;
38738a7d6542SBram Moolenaar #ifdef FEAT_FLOAT
38748a7d6542SBram Moolenaar 			if (tv1->v_type == VAR_FLOAT)
38758a7d6542SBram Moolenaar 			    f2 = n2;
38768a7d6542SBram Moolenaar #endif
38778a7d6542SBram Moolenaar 		    }
38788a7d6542SBram Moolenaar #ifdef FEAT_FLOAT
38798a7d6542SBram Moolenaar 		    // if there is a float on either side the result is a float
38808a7d6542SBram Moolenaar 		    if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
38818a7d6542SBram Moolenaar 		    {
38828a7d6542SBram Moolenaar 			switch (iptr->isn_arg.op.op_type)
38838a7d6542SBram Moolenaar 			{
38848a7d6542SBram Moolenaar 			    case EXPR_MULT: f1 = f1 * f2; break;
38858a7d6542SBram Moolenaar 			    case EXPR_DIV:  f1 = f1 / f2; break;
38868a7d6542SBram Moolenaar 			    case EXPR_SUB:  f1 = f1 - f2; break;
38878a7d6542SBram Moolenaar 			    case EXPR_ADD:  f1 = f1 + f2; break;
38887517ffdbSBram Moolenaar 			    default: SOURCING_LNUM = iptr->isn_lnum;
38897517ffdbSBram Moolenaar 				     emsg(_(e_modulus));
3890f0b9f43cSBram Moolenaar 				     goto on_error;
38918a7d6542SBram Moolenaar 			}
38928a7d6542SBram Moolenaar 			clear_tv(tv1);
38938a7d6542SBram Moolenaar 			clear_tv(tv2);
38948a7d6542SBram Moolenaar 			tv1->v_type = VAR_FLOAT;
38958a7d6542SBram Moolenaar 			tv1->vval.v_float = f1;
38964c137214SBram Moolenaar 			--ectx->ec_stack.ga_len;
38978a7d6542SBram Moolenaar 		    }
38988a7d6542SBram Moolenaar 		    else
38998a7d6542SBram Moolenaar #endif
39008a7d6542SBram Moolenaar 		    {
3901b1f28570SBram Moolenaar 			int failed = FALSE;
3902b1f28570SBram Moolenaar 
39038a7d6542SBram Moolenaar 			switch (iptr->isn_arg.op.op_type)
39048a7d6542SBram Moolenaar 			{
39058a7d6542SBram Moolenaar 			    case EXPR_MULT: n1 = n1 * n2; break;
3906b1f28570SBram Moolenaar 			    case EXPR_DIV:  n1 = num_divide(n1, n2, &failed);
3907b1f28570SBram Moolenaar 					    if (failed)
390899880f96SBram Moolenaar 						goto on_error;
390999880f96SBram Moolenaar 					    break;
39108a7d6542SBram Moolenaar 			    case EXPR_SUB:  n1 = n1 - n2; break;
39118a7d6542SBram Moolenaar 			    case EXPR_ADD:  n1 = n1 + n2; break;
3912b1f28570SBram Moolenaar 			    default:	    n1 = num_modulus(n1, n2, &failed);
3913b1f28570SBram Moolenaar 					    if (failed)
391499880f96SBram Moolenaar 						goto on_error;
391599880f96SBram Moolenaar 					    break;
39168a7d6542SBram Moolenaar 			}
39178a7d6542SBram Moolenaar 			clear_tv(tv1);
39188a7d6542SBram Moolenaar 			clear_tv(tv2);
39198a7d6542SBram Moolenaar 			tv1->v_type = VAR_NUMBER;
39208a7d6542SBram Moolenaar 			tv1->vval.v_number = n1;
39214c137214SBram Moolenaar 			--ectx->ec_stack.ga_len;
39228a7d6542SBram Moolenaar 		    }
39238a7d6542SBram Moolenaar 		}
39248a7d6542SBram Moolenaar 		break;
39258a7d6542SBram Moolenaar 
39268a7d6542SBram Moolenaar 	    case ISN_CONCAT:
39278a7d6542SBram Moolenaar 		{
39288a7d6542SBram Moolenaar 		    char_u *str1 = STACK_TV_BOT(-2)->vval.v_string;
39298a7d6542SBram Moolenaar 		    char_u *str2 = STACK_TV_BOT(-1)->vval.v_string;
39308a7d6542SBram Moolenaar 		    char_u *res;
39318a7d6542SBram Moolenaar 
39328a7d6542SBram Moolenaar 		    res = concat_str(str1, str2);
39338a7d6542SBram Moolenaar 		    clear_tv(STACK_TV_BOT(-2));
39348a7d6542SBram Moolenaar 		    clear_tv(STACK_TV_BOT(-1));
39354c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
39368a7d6542SBram Moolenaar 		    STACK_TV_BOT(-1)->vval.v_string = res;
39378a7d6542SBram Moolenaar 		}
39388a7d6542SBram Moolenaar 		break;
39398a7d6542SBram Moolenaar 
3940bf9d8c37SBram Moolenaar 	    case ISN_STRINDEX:
394111107babSBram Moolenaar 	    case ISN_STRSLICE:
3942bf9d8c37SBram Moolenaar 		{
394311107babSBram Moolenaar 		    int		is_slice = iptr->isn_type == ISN_STRSLICE;
394411107babSBram Moolenaar 		    varnumber_T	n1 = 0, n2;
3945bf9d8c37SBram Moolenaar 		    char_u	*res;
3946bf9d8c37SBram Moolenaar 
3947bf9d8c37SBram Moolenaar 		    // string index: string is at stack-2, index at stack-1
394811107babSBram Moolenaar 		    // string slice: string is at stack-3, first index at
394911107babSBram Moolenaar 		    // stack-2, second index at stack-1
395011107babSBram Moolenaar 		    if (is_slice)
395111107babSBram Moolenaar 		    {
395211107babSBram Moolenaar 			tv = STACK_TV_BOT(-2);
395311107babSBram Moolenaar 			n1 = tv->vval.v_number;
395411107babSBram Moolenaar 		    }
395511107babSBram Moolenaar 
3956bf9d8c37SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
395711107babSBram Moolenaar 		    n2 = tv->vval.v_number;
3958bf9d8c37SBram Moolenaar 
39594c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
3960bf9d8c37SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
396111107babSBram Moolenaar 		    if (is_slice)
396211107babSBram Moolenaar 			// Slice: Select the characters from the string
39636601b629SBram Moolenaar 			res = string_slice(tv->vval.v_string, n1, n2, FALSE);
396411107babSBram Moolenaar 		    else
396511107babSBram Moolenaar 			// Index: The resulting variable is a string of a
39660289a093SBram Moolenaar 			// single character (including composing characters).
39670289a093SBram Moolenaar 			// If the index is too big or negative the result is
39680289a093SBram Moolenaar 			// empty.
396911107babSBram Moolenaar 			res = char_from_string(tv->vval.v_string, n2);
3970bf9d8c37SBram Moolenaar 		    vim_free(tv->vval.v_string);
3971bf9d8c37SBram Moolenaar 		    tv->vval.v_string = res;
3972bf9d8c37SBram Moolenaar 		}
3973bf9d8c37SBram Moolenaar 		break;
3974bf9d8c37SBram Moolenaar 
3975bf9d8c37SBram Moolenaar 	    case ISN_LISTINDEX:
3976ed591877SBram Moolenaar 	    case ISN_LISTSLICE:
3977cfc3023cSBram Moolenaar 	    case ISN_BLOBINDEX:
3978cfc3023cSBram Moolenaar 	    case ISN_BLOBSLICE:
39798a7d6542SBram Moolenaar 		{
3980cfc3023cSBram Moolenaar 		    int		is_slice = iptr->isn_type == ISN_LISTSLICE
3981cfc3023cSBram Moolenaar 					    || iptr->isn_type == ISN_BLOBSLICE;
3982cfc3023cSBram Moolenaar 		    int		is_blob = iptr->isn_type == ISN_BLOBINDEX
3983cfc3023cSBram Moolenaar 					    || iptr->isn_type == ISN_BLOBSLICE;
3984ed591877SBram Moolenaar 		    varnumber_T	n1, n2;
3985cfc3023cSBram Moolenaar 		    typval_T	*val_tv;
39868a7d6542SBram Moolenaar 
39878a7d6542SBram Moolenaar 		    // list index: list is at stack-2, index at stack-1
3988ed591877SBram Moolenaar 		    // list slice: list is at stack-3, indexes at stack-2 and
3989ed591877SBram Moolenaar 		    // stack-1
3990cfc3023cSBram Moolenaar 		    // Same for blob.
3991cfc3023cSBram Moolenaar 		    val_tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
39928a7d6542SBram Moolenaar 
39938a7d6542SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
3994ed591877SBram Moolenaar 		    n1 = n2 = tv->vval.v_number;
39958a7d6542SBram Moolenaar 		    clear_tv(tv);
3996ed591877SBram Moolenaar 
3997ed591877SBram Moolenaar 		    if (is_slice)
3998ed591877SBram Moolenaar 		    {
3999ed591877SBram Moolenaar 			tv = STACK_TV_BOT(-2);
4000ed591877SBram Moolenaar 			n1 = tv->vval.v_number;
4001ed591877SBram Moolenaar 			clear_tv(tv);
4002ed591877SBram Moolenaar 		    }
4003ed591877SBram Moolenaar 
40044c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
4005435d8978SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
40061d634542SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
4007cfc3023cSBram Moolenaar 		    if (is_blob)
4008cfc3023cSBram Moolenaar 		    {
4009cfc3023cSBram Moolenaar 			if (blob_slice_or_index(val_tv->vval.v_blob, is_slice,
4010cfc3023cSBram Moolenaar 						    n1, n2, FALSE, tv) == FAIL)
4011ed591877SBram Moolenaar 			    goto on_error;
40128a7d6542SBram Moolenaar 		    }
4013cfc3023cSBram Moolenaar 		    else
4014cfc3023cSBram Moolenaar 		    {
4015cfc3023cSBram Moolenaar 			if (list_slice_or_index(val_tv->vval.v_list, is_slice,
4016cfc3023cSBram Moolenaar 					      n1, n2, FALSE, tv, TRUE) == FAIL)
4017cfc3023cSBram Moolenaar 			    goto on_error;
4018cfc3023cSBram Moolenaar 		    }
4019cfc3023cSBram Moolenaar 		}
40208a7d6542SBram Moolenaar 		break;
40218a7d6542SBram Moolenaar 
4022cc673e74SBram Moolenaar 	    case ISN_ANYINDEX:
4023cc673e74SBram Moolenaar 	    case ISN_ANYSLICE:
4024cc673e74SBram Moolenaar 		{
4025cc673e74SBram Moolenaar 		    int		is_slice = iptr->isn_type == ISN_ANYSLICE;
4026cc673e74SBram Moolenaar 		    typval_T	*var1, *var2;
4027cc673e74SBram Moolenaar 		    int		res;
4028cc673e74SBram Moolenaar 
4029cc673e74SBram Moolenaar 		    // index: composite is at stack-2, index at stack-1
4030cc673e74SBram Moolenaar 		    // slice: composite is at stack-3, indexes at stack-2 and
4031cc673e74SBram Moolenaar 		    // stack-1
4032cc673e74SBram Moolenaar 		    tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
40333affe7a6SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
4034cc673e74SBram Moolenaar 		    if (check_can_index(tv, TRUE, TRUE) == FAIL)
4035cc673e74SBram Moolenaar 			goto on_error;
4036cc673e74SBram Moolenaar 		    var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1);
4037cc673e74SBram Moolenaar 		    var2 = is_slice ? STACK_TV_BOT(-1) : NULL;
40386601b629SBram Moolenaar 		    res = eval_index_inner(tv, is_slice, var1, var2,
40396601b629SBram Moolenaar 							FALSE, NULL, -1, TRUE);
4040cc673e74SBram Moolenaar 		    clear_tv(var1);
4041cc673e74SBram Moolenaar 		    if (is_slice)
4042cc673e74SBram Moolenaar 			clear_tv(var2);
40434c137214SBram Moolenaar 		    ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
4044cc673e74SBram Moolenaar 		    if (res == FAIL)
4045cc673e74SBram Moolenaar 			goto on_error;
4046cc673e74SBram Moolenaar 		}
4047cc673e74SBram Moolenaar 		break;
4048cc673e74SBram Moolenaar 
40499af78769SBram Moolenaar 	    case ISN_SLICE:
40509af78769SBram Moolenaar 		{
40519af78769SBram Moolenaar 		    list_T	*list;
40529af78769SBram Moolenaar 		    int		count = iptr->isn_arg.number;
40539af78769SBram Moolenaar 
4054c5b1c20bSBram Moolenaar 		    // type will have been checked to be a list
40559af78769SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
40569af78769SBram Moolenaar 		    list = tv->vval.v_list;
40579af78769SBram Moolenaar 
40589af78769SBram Moolenaar 		    // no error for short list, expect it to be checked earlier
40599af78769SBram Moolenaar 		    if (list != NULL && list->lv_len >= count)
40609af78769SBram Moolenaar 		    {
40619af78769SBram Moolenaar 			list_T	*newlist = list_slice(list,
40629af78769SBram Moolenaar 						      count, list->lv_len - 1);
40639af78769SBram Moolenaar 
40649af78769SBram Moolenaar 			if (newlist != NULL)
40659af78769SBram Moolenaar 			{
40669af78769SBram Moolenaar 			    list_unref(list);
40679af78769SBram Moolenaar 			    tv->vval.v_list = newlist;
40689af78769SBram Moolenaar 			    ++newlist->lv_refcount;
40699af78769SBram Moolenaar 			}
40709af78769SBram Moolenaar 		    }
40719af78769SBram Moolenaar 		}
40729af78769SBram Moolenaar 		break;
40739af78769SBram Moolenaar 
407447a519a9SBram Moolenaar 	    case ISN_GETITEM:
407547a519a9SBram Moolenaar 		{
407647a519a9SBram Moolenaar 		    listitem_T	*li;
4077035bd1c9SBram Moolenaar 		    getitem_T	*gi = &iptr->isn_arg.getitem;
407847a519a9SBram Moolenaar 
4079c785b9a7SBram Moolenaar 		    // Get list item: list is at stack-1, push item.
4080c785b9a7SBram Moolenaar 		    // List type and length is checked for when compiling.
4081035bd1c9SBram Moolenaar 		    tv = STACK_TV_BOT(-1 - gi->gi_with_op);
4082035bd1c9SBram Moolenaar 		    li = list_find(tv->vval.v_list, gi->gi_index);
408347a519a9SBram Moolenaar 
408435578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
4085cbe178e3SBram Moolenaar 			goto theend;
40864c137214SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
408747a519a9SBram Moolenaar 		    copy_tv(&li->li_tv, STACK_TV_BOT(-1));
4088f785aa13SBram Moolenaar 
4089f785aa13SBram Moolenaar 		    // Useful when used in unpack assignment.  Reset at
4090f785aa13SBram Moolenaar 		    // ISN_DROP.
4091035bd1c9SBram Moolenaar 		    ectx->ec_where.wt_index = gi->gi_index + 1;
40924c137214SBram Moolenaar 		    ectx->ec_where.wt_variable = TRUE;
409347a519a9SBram Moolenaar 		}
409447a519a9SBram Moolenaar 		break;
409547a519a9SBram Moolenaar 
40968a7d6542SBram Moolenaar 	    case ISN_MEMBER:
40978a7d6542SBram Moolenaar 		{
40988a7d6542SBram Moolenaar 		    dict_T	*dict;
40991cc2a94fSBram Moolenaar 		    char_u	*key;
41001cc2a94fSBram Moolenaar 		    dictitem_T	*di;
41011cc2a94fSBram Moolenaar 
41021cc2a94fSBram Moolenaar 		    // dict member: dict is at stack-2, key at stack-1
41031cc2a94fSBram Moolenaar 		    tv = STACK_TV_BOT(-2);
41044dac32caSBram Moolenaar 		    // no need to check for VAR_DICT, CHECKTYPE will check.
41051cc2a94fSBram Moolenaar 		    dict = tv->vval.v_dict;
41061cc2a94fSBram Moolenaar 
41071cc2a94fSBram Moolenaar 		    tv = STACK_TV_BOT(-1);
41084dac32caSBram Moolenaar 		    // no need to check for VAR_STRING, 2STRING will check.
41091cc2a94fSBram Moolenaar 		    key = tv->vval.v_string;
4110086fc9a5SBram Moolenaar 		    if (key == NULL)
4111086fc9a5SBram Moolenaar 			key = (char_u *)"";
41124dac32caSBram Moolenaar 
41131cc2a94fSBram Moolenaar 		    if ((di = dict_find(dict, key, -1)) == NULL)
41141cc2a94fSBram Moolenaar 		    {
41157517ffdbSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
41161cc2a94fSBram Moolenaar 			semsg(_(e_dictkey), key);
41174029cabbSBram Moolenaar 
41184029cabbSBram Moolenaar 			// If :silent! is used we will continue, make sure the
4119b1b6f4deSBram Moolenaar 			// stack contents makes sense and the dict stack is
4120b1b6f4deSBram Moolenaar 			// updated.
41214029cabbSBram Moolenaar 			clear_tv(tv);
41224c137214SBram Moolenaar 			--ectx->ec_stack.ga_len;
41234029cabbSBram Moolenaar 			tv = STACK_TV_BOT(-1);
4124b1b6f4deSBram Moolenaar 			(void) dict_stack_save(tv);
41254029cabbSBram Moolenaar 			tv->v_type = VAR_NUMBER;
41264029cabbSBram Moolenaar 			tv->vval.v_number = 0;
4127af0df47aSBram Moolenaar 			goto on_fatal_error;
41281cc2a94fSBram Moolenaar 		    }
41291cc2a94fSBram Moolenaar 		    clear_tv(tv);
41304c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
4131b1b6f4deSBram Moolenaar 		    // Put the dict used on the dict stack, it might be used by
4132b1b6f4deSBram Moolenaar 		    // a dict function later.
413350788ef3SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
4134b1b6f4deSBram Moolenaar 		    if (dict_stack_save(tv) == FAIL)
4135b1b6f4deSBram Moolenaar 			goto on_fatal_error;
413650788ef3SBram Moolenaar 		    copy_tv(&di->di_tv, tv);
41371cc2a94fSBram Moolenaar 		}
41381cc2a94fSBram Moolenaar 		break;
41391cc2a94fSBram Moolenaar 
41401cc2a94fSBram Moolenaar 	    // dict member with string key
41411cc2a94fSBram Moolenaar 	    case ISN_STRINGMEMBER:
41421cc2a94fSBram Moolenaar 		{
41431cc2a94fSBram Moolenaar 		    dict_T	*dict;
41448a7d6542SBram Moolenaar 		    dictitem_T	*di;
41458a7d6542SBram Moolenaar 
41468a7d6542SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
41478a7d6542SBram Moolenaar 		    if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
41488a7d6542SBram Moolenaar 		    {
41497517ffdbSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
41508a7d6542SBram Moolenaar 			emsg(_(e_dictreq));
4151d032f34aSBram Moolenaar 			goto on_error;
41528a7d6542SBram Moolenaar 		    }
41538a7d6542SBram Moolenaar 		    dict = tv->vval.v_dict;
41548a7d6542SBram Moolenaar 
41558a7d6542SBram Moolenaar 		    if ((di = dict_find(dict, iptr->isn_arg.string, -1))
41568a7d6542SBram Moolenaar 								       == NULL)
41578a7d6542SBram Moolenaar 		    {
41587517ffdbSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
41598a7d6542SBram Moolenaar 			semsg(_(e_dictkey), iptr->isn_arg.string);
4160d032f34aSBram Moolenaar 			goto on_error;
41618a7d6542SBram Moolenaar 		    }
4162b1b6f4deSBram Moolenaar 		    // Put the dict used on the dict stack, it might be used by
4163b1b6f4deSBram Moolenaar 		    // a dict function later.
4164b1b6f4deSBram Moolenaar 		    if (dict_stack_save(tv) == FAIL)
4165b1b6f4deSBram Moolenaar 			goto on_fatal_error;
4166b1b6f4deSBram Moolenaar 
41678a7d6542SBram Moolenaar 		    copy_tv(&di->di_tv, tv);
4168b1b6f4deSBram Moolenaar 		}
4169b1b6f4deSBram Moolenaar 		break;
4170b1b6f4deSBram Moolenaar 
4171b1b6f4deSBram Moolenaar 	    case ISN_CLEARDICT:
4172b1b6f4deSBram Moolenaar 		dict_stack_drop();
4173b1b6f4deSBram Moolenaar 		break;
4174b1b6f4deSBram Moolenaar 
4175b1b6f4deSBram Moolenaar 	    case ISN_USEDICT:
4176b1b6f4deSBram Moolenaar 		{
4177b1b6f4deSBram Moolenaar 		    typval_T *dict_tv = dict_stack_get_tv();
4178b1b6f4deSBram Moolenaar 
4179b1b6f4deSBram Moolenaar 		    // Turn "dict.Func" into a partial for "Func" bound to
4180b1b6f4deSBram Moolenaar 		    // "dict".  Don't do this when "Func" is already a partial
4181b1b6f4deSBram Moolenaar 		    // that was bound explicitly (pt_auto is FALSE).
4182b1b6f4deSBram Moolenaar 		    tv = STACK_TV_BOT(-1);
4183b1b6f4deSBram Moolenaar 		    if (dict_tv != NULL
4184b1b6f4deSBram Moolenaar 			    && dict_tv->v_type == VAR_DICT
4185b1b6f4deSBram Moolenaar 			    && dict_tv->vval.v_dict != NULL
4186b1b6f4deSBram Moolenaar 			    && (tv->v_type == VAR_FUNC
4187b1b6f4deSBram Moolenaar 				|| (tv->v_type == VAR_PARTIAL
4188b1b6f4deSBram Moolenaar 				    && (tv->vval.v_partial->pt_auto
4189b1b6f4deSBram Moolenaar 				     || tv->vval.v_partial->pt_dict == NULL))))
4190b1b6f4deSBram Moolenaar 		    dict_tv->vval.v_dict =
4191b1b6f4deSBram Moolenaar 					make_partial(dict_tv->vval.v_dict, tv);
4192b1b6f4deSBram Moolenaar 		    dict_stack_drop();
41938a7d6542SBram Moolenaar 		}
41948a7d6542SBram Moolenaar 		break;
41958a7d6542SBram Moolenaar 
41968a7d6542SBram Moolenaar 	    case ISN_NEGATENR:
41978a7d6542SBram Moolenaar 		tv = STACK_TV_BOT(-1);
4198c58164c5SBram Moolenaar 		if (tv->v_type != VAR_NUMBER
4199c58164c5SBram Moolenaar #ifdef FEAT_FLOAT
4200c58164c5SBram Moolenaar 			&& tv->v_type != VAR_FLOAT
4201c58164c5SBram Moolenaar #endif
4202c58164c5SBram Moolenaar 			)
4203c58164c5SBram Moolenaar 		{
42047517ffdbSBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
4205e29a27f6SBram Moolenaar 		    emsg(_(e_number_expected));
4206f0b9f43cSBram Moolenaar 		    goto on_error;
4207c58164c5SBram Moolenaar 		}
4208c58164c5SBram Moolenaar #ifdef FEAT_FLOAT
4209c58164c5SBram Moolenaar 		if (tv->v_type == VAR_FLOAT)
4210c58164c5SBram Moolenaar 		    tv->vval.v_float = -tv->vval.v_float;
4211c58164c5SBram Moolenaar 		else
4212c58164c5SBram Moolenaar #endif
42138a7d6542SBram Moolenaar 		    tv->vval.v_number = -tv->vval.v_number;
42148a7d6542SBram Moolenaar 		break;
42158a7d6542SBram Moolenaar 
42168a7d6542SBram Moolenaar 	    case ISN_CHECKNR:
42178a7d6542SBram Moolenaar 		{
42188a7d6542SBram Moolenaar 		    int		error = FALSE;
42198a7d6542SBram Moolenaar 
42208a7d6542SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
42213affe7a6SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
42228a7d6542SBram Moolenaar 		    if (check_not_string(tv) == FAIL)
4223f0b9f43cSBram Moolenaar 			goto on_error;
42248a7d6542SBram Moolenaar 		    (void)tv_get_number_chk(tv, &error);
42258a7d6542SBram Moolenaar 		    if (error)
4226f0b9f43cSBram Moolenaar 			goto on_error;
42278a7d6542SBram Moolenaar 		}
42288a7d6542SBram Moolenaar 		break;
42298a7d6542SBram Moolenaar 
42308a7d6542SBram Moolenaar 	    case ISN_CHECKTYPE:
42318a7d6542SBram Moolenaar 		{
42328a7d6542SBram Moolenaar 		    checktype_T *ct = &iptr->isn_arg.type;
42338a7d6542SBram Moolenaar 
4234b3005ce1SBram Moolenaar 		    tv = STACK_TV_BOT((int)ct->ct_off);
42355e654230SBram Moolenaar 		    SOURCING_LNUM = iptr->isn_lnum;
42364c137214SBram Moolenaar 		    if (!ectx->ec_where.wt_variable)
42374c137214SBram Moolenaar 			ectx->ec_where.wt_index = ct->ct_arg_idx;
42384c137214SBram Moolenaar 		    if (check_typval_type(ct->ct_type, tv, ectx->ec_where)
42394c137214SBram Moolenaar 								       == FAIL)
42405e654230SBram Moolenaar 			goto on_error;
42414c137214SBram Moolenaar 		    if (!ectx->ec_where.wt_variable)
42424c137214SBram Moolenaar 			ectx->ec_where.wt_index = 0;
42435e654230SBram Moolenaar 
42445e654230SBram Moolenaar 		    // number 0 is FALSE, number 1 is TRUE
42455e654230SBram Moolenaar 		    if (tv->v_type == VAR_NUMBER
42465e654230SBram Moolenaar 			    && ct->ct_type->tt_type == VAR_BOOL
4247dadaddd5SBram Moolenaar 			    && (tv->vval.v_number == 0
4248dadaddd5SBram Moolenaar 						|| tv->vval.v_number == 1))
4249dadaddd5SBram Moolenaar 		    {
4250dadaddd5SBram Moolenaar 			tv->v_type = VAR_BOOL;
4251dadaddd5SBram Moolenaar 			tv->vval.v_number = tv->vval.v_number
4252dadaddd5SBram Moolenaar 						      ? VVAL_TRUE : VVAL_FALSE;
4253dadaddd5SBram Moolenaar 		    }
4254dadaddd5SBram Moolenaar 		}
42558a7d6542SBram Moolenaar 		break;
42568a7d6542SBram Moolenaar 
42579af78769SBram Moolenaar 	    case ISN_CHECKLEN:
42589af78769SBram Moolenaar 		{
42599af78769SBram Moolenaar 		    int	    min_len = iptr->isn_arg.checklen.cl_min_len;
42609af78769SBram Moolenaar 		    list_T  *list = NULL;
42619af78769SBram Moolenaar 
42629af78769SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
42639af78769SBram Moolenaar 		    if (tv->v_type == VAR_LIST)
42649af78769SBram Moolenaar 			    list = tv->vval.v_list;
42659af78769SBram Moolenaar 		    if (list == NULL || list->lv_len < min_len
42669af78769SBram Moolenaar 			    || (list->lv_len > min_len
42679af78769SBram Moolenaar 					&& !iptr->isn_arg.checklen.cl_more_OK))
42689af78769SBram Moolenaar 		    {
42697517ffdbSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
4270451c2e35SBram Moolenaar 			semsg(_(e_expected_nr_items_but_got_nr),
42719af78769SBram Moolenaar 				     min_len, list == NULL ? 0 : list->lv_len);
4272f0b9f43cSBram Moolenaar 			goto on_error;
42739af78769SBram Moolenaar 		    }
42749af78769SBram Moolenaar 		}
42759af78769SBram Moolenaar 		break;
42769af78769SBram Moolenaar 
4277aa210a3aSBram Moolenaar 	    case ISN_SETTYPE:
4278aa210a3aSBram Moolenaar 		{
4279aa210a3aSBram Moolenaar 		    checktype_T *ct = &iptr->isn_arg.type;
4280aa210a3aSBram Moolenaar 
4281aa210a3aSBram Moolenaar 		    tv = STACK_TV_BOT(-1);
4282aa210a3aSBram Moolenaar 		    if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
4283aa210a3aSBram Moolenaar 		    {
4284aa210a3aSBram Moolenaar 			free_type(tv->vval.v_dict->dv_type);
4285aa210a3aSBram Moolenaar 			tv->vval.v_dict->dv_type = alloc_type(ct->ct_type);
4286aa210a3aSBram Moolenaar 		    }
4287aa210a3aSBram Moolenaar 		    else if (tv->v_type == VAR_LIST && tv->vval.v_list != NULL)
4288aa210a3aSBram Moolenaar 		    {
4289aa210a3aSBram Moolenaar 			free_type(tv->vval.v_list->lv_type);
4290aa210a3aSBram Moolenaar 			tv->vval.v_list->lv_type = alloc_type(ct->ct_type);
4291aa210a3aSBram Moolenaar 		    }
4292aa210a3aSBram Moolenaar 		}
4293aa210a3aSBram Moolenaar 		break;
4294aa210a3aSBram Moolenaar 
42958a7d6542SBram Moolenaar 	    case ISN_2BOOL:
42962bb2658bSBram Moolenaar 	    case ISN_COND2BOOL:
42978a7d6542SBram Moolenaar 		{
42988a7d6542SBram Moolenaar 		    int n;
42992bb2658bSBram Moolenaar 		    int error = FALSE;
43008a7d6542SBram Moolenaar 
43012bb2658bSBram Moolenaar 		    if (iptr->isn_type == ISN_2BOOL)
43022bb2658bSBram Moolenaar 		    {
43035fa9b244SBram Moolenaar 			tv = STACK_TV_BOT(iptr->isn_arg.tobool.offset);
43048a7d6542SBram Moolenaar 			n = tv2bool(tv);
43055fa9b244SBram Moolenaar 			if (iptr->isn_arg.tobool.invert)
43068a7d6542SBram Moolenaar 			    n = !n;
43072bb2658bSBram Moolenaar 		    }
43082bb2658bSBram Moolenaar 		    else
43092bb2658bSBram Moolenaar 		    {
43105fa9b244SBram Moolenaar 			tv = STACK_TV_BOT(-1);
43112bb2658bSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
43122bb2658bSBram Moolenaar 			n = tv_get_bool_chk(tv, &error);
43132bb2658bSBram Moolenaar 			if (error)
43142bb2658bSBram Moolenaar 			    goto on_error;
43152bb2658bSBram Moolenaar 		    }
43168a7d6542SBram Moolenaar 		    clear_tv(tv);
43178a7d6542SBram Moolenaar 		    tv->v_type = VAR_BOOL;
43188a7d6542SBram Moolenaar 		    tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
43198a7d6542SBram Moolenaar 		}
43208a7d6542SBram Moolenaar 		break;
43218a7d6542SBram Moolenaar 
43228a7d6542SBram Moolenaar 	    case ISN_2STRING:
4323418f1df5SBram Moolenaar 	    case ISN_2STRING_ANY:
43240acbf5aeSBram Moolenaar 		SOURCING_LNUM = iptr->isn_lnum;
43255fa9b244SBram Moolenaar 		if (do_2string(STACK_TV_BOT(iptr->isn_arg.tostring.offset),
43265fa9b244SBram Moolenaar 				iptr->isn_type == ISN_2STRING_ANY,
43275fa9b244SBram Moolenaar 				      iptr->isn_arg.tostring.tolerant) == FAIL)
4328418f1df5SBram Moolenaar 			    goto on_error;
43298a7d6542SBram Moolenaar 		break;
43308a7d6542SBram Moolenaar 
433108597875SBram Moolenaar 	    case ISN_RANGE:
433208597875SBram Moolenaar 		{
433308597875SBram Moolenaar 		    exarg_T	ea;
433408597875SBram Moolenaar 		    char	*errormsg;
433508597875SBram Moolenaar 
4336ece0b87cSBram Moolenaar 		    ea.line2 = 0;
4337d1510ee9SBram Moolenaar 		    ea.addr_count = 0;
433808597875SBram Moolenaar 		    ea.addr_type = ADDR_LINES;
433908597875SBram Moolenaar 		    ea.cmd = iptr->isn_arg.string;
4340ece0b87cSBram Moolenaar 		    ea.skip = FALSE;
434108597875SBram Moolenaar 		    if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
4342ece0b87cSBram Moolenaar 			goto on_error;
4343a28639e7SBram Moolenaar 
434435578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, 1))
4345cbe178e3SBram Moolenaar 			goto theend;
43464c137214SBram Moolenaar 		    ++ectx->ec_stack.ga_len;
4347a28639e7SBram Moolenaar 		    tv = STACK_TV_BOT(-1);
4348a28639e7SBram Moolenaar 		    tv->v_type = VAR_NUMBER;
4349a28639e7SBram Moolenaar 		    tv->v_lock = 0;
435008597875SBram Moolenaar 		    if (ea.addr_count == 0)
435108597875SBram Moolenaar 			tv->vval.v_number = curwin->w_cursor.lnum;
435208597875SBram Moolenaar 		    else
435308597875SBram Moolenaar 			tv->vval.v_number = ea.line2;
435408597875SBram Moolenaar 		}
435508597875SBram Moolenaar 		break;
435608597875SBram Moolenaar 
4357c3516f7eSBram Moolenaar 	    case ISN_PUT:
4358c3516f7eSBram Moolenaar 		{
4359c3516f7eSBram Moolenaar 		    int		regname = iptr->isn_arg.put.put_regname;
4360c3516f7eSBram Moolenaar 		    linenr_T	lnum = iptr->isn_arg.put.put_lnum;
4361c3516f7eSBram Moolenaar 		    char_u	*expr = NULL;
4362c3516f7eSBram Moolenaar 		    int		dir = FORWARD;
4363c3516f7eSBram Moolenaar 
436408597875SBram Moolenaar 		    if (lnum < -2)
436508597875SBram Moolenaar 		    {
436608597875SBram Moolenaar 			// line number was put on the stack by ISN_RANGE
436708597875SBram Moolenaar 			tv = STACK_TV_BOT(-1);
436808597875SBram Moolenaar 			curwin->w_cursor.lnum = tv->vval.v_number;
436908597875SBram Moolenaar 			if (lnum == LNUM_VARIABLE_RANGE_ABOVE)
437008597875SBram Moolenaar 			    dir = BACKWARD;
43714c137214SBram Moolenaar 			--ectx->ec_stack.ga_len;
437208597875SBram Moolenaar 		    }
437308597875SBram Moolenaar 		    else if (lnum == -2)
4374c3516f7eSBram Moolenaar 			// :put! above cursor
4375c3516f7eSBram Moolenaar 			dir = BACKWARD;
4376c3516f7eSBram Moolenaar 		    else if (lnum >= 0)
4377c3516f7eSBram Moolenaar 			curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum;
4378a28639e7SBram Moolenaar 
4379a28639e7SBram Moolenaar 		    if (regname == '=')
4380a28639e7SBram Moolenaar 		    {
4381a28639e7SBram Moolenaar 			tv = STACK_TV_BOT(-1);
4382a28639e7SBram Moolenaar 			if (tv->v_type == VAR_STRING)
4383a28639e7SBram Moolenaar 			    expr = tv->vval.v_string;
4384a28639e7SBram Moolenaar 			else
4385a28639e7SBram Moolenaar 			{
4386a28639e7SBram Moolenaar 			    expr = typval2string(tv, TRUE); // allocates value
4387a28639e7SBram Moolenaar 			    clear_tv(tv);
4388a28639e7SBram Moolenaar 			}
43894c137214SBram Moolenaar 			--ectx->ec_stack.ga_len;
4390a28639e7SBram Moolenaar 		    }
4391c3516f7eSBram Moolenaar 		    check_cursor();
4392c3516f7eSBram Moolenaar 		    do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
4393c3516f7eSBram Moolenaar 		    vim_free(expr);
4394c3516f7eSBram Moolenaar 		}
4395c3516f7eSBram Moolenaar 		break;
4396c3516f7eSBram Moolenaar 
439702194d2bSBram Moolenaar 	    case ISN_CMDMOD:
43984c137214SBram Moolenaar 		ectx->ec_funclocal.floc_save_cmdmod = cmdmod;
43994c137214SBram Moolenaar 		ectx->ec_funclocal.floc_restore_cmdmod = TRUE;
44004c137214SBram Moolenaar 		ectx->ec_funclocal.floc_restore_cmdmod_stacklen =
44014c137214SBram Moolenaar 							 ectx->ec_stack.ga_len;
440202194d2bSBram Moolenaar 		cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod;
440302194d2bSBram Moolenaar 		apply_cmdmod(&cmdmod);
4404f4c6e1e7SBram Moolenaar 		break;
4405f4c6e1e7SBram Moolenaar 
440602194d2bSBram Moolenaar 	    case ISN_CMDMOD_REV:
440702194d2bSBram Moolenaar 		// filter regprog is owned by the instruction, don't free it
440802194d2bSBram Moolenaar 		cmdmod.cmod_filter_regmatch.regprog = NULL;
440902194d2bSBram Moolenaar 		undo_cmdmod(&cmdmod);
44104c137214SBram Moolenaar 		cmdmod = ectx->ec_funclocal.floc_save_cmdmod;
44114c137214SBram Moolenaar 		ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
4412f4c6e1e7SBram Moolenaar 		break;
4413f4c6e1e7SBram Moolenaar 
4414792f786aSBram Moolenaar 	    case ISN_UNPACK:
4415792f786aSBram Moolenaar 		{
4416792f786aSBram Moolenaar 		    int		count = iptr->isn_arg.unpack.unp_count;
4417792f786aSBram Moolenaar 		    int		semicolon = iptr->isn_arg.unpack.unp_semicolon;
4418792f786aSBram Moolenaar 		    list_T	*l;
4419792f786aSBram Moolenaar 		    listitem_T	*li;
4420792f786aSBram Moolenaar 		    int		i;
4421792f786aSBram Moolenaar 
4422792f786aSBram Moolenaar 		    // Check there is a valid list to unpack.
4423792f786aSBram Moolenaar 		    tv = STACK_TV_BOT(-1);
4424792f786aSBram Moolenaar 		    if (tv->v_type != VAR_LIST)
4425792f786aSBram Moolenaar 		    {
4426792f786aSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
4427792f786aSBram Moolenaar 			emsg(_(e_for_argument_must_be_sequence_of_lists));
4428792f786aSBram Moolenaar 			goto on_error;
4429792f786aSBram Moolenaar 		    }
4430792f786aSBram Moolenaar 		    l = tv->vval.v_list;
4431792f786aSBram Moolenaar 		    if (l == NULL
4432792f786aSBram Moolenaar 				|| l->lv_len < (semicolon ? count - 1 : count))
4433792f786aSBram Moolenaar 		    {
4434792f786aSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
4435792f786aSBram Moolenaar 			emsg(_(e_list_value_does_not_have_enough_items));
4436792f786aSBram Moolenaar 			goto on_error;
4437792f786aSBram Moolenaar 		    }
4438792f786aSBram Moolenaar 		    else if (!semicolon && l->lv_len > count)
4439792f786aSBram Moolenaar 		    {
4440792f786aSBram Moolenaar 			SOURCING_LNUM = iptr->isn_lnum;
4441792f786aSBram Moolenaar 			emsg(_(e_list_value_has_more_items_than_targets));
4442792f786aSBram Moolenaar 			goto on_error;
4443792f786aSBram Moolenaar 		    }
4444792f786aSBram Moolenaar 
4445792f786aSBram Moolenaar 		    CHECK_LIST_MATERIALIZE(l);
444635578168SBram Moolenaar 		    if (GA_GROW_FAILS(&ectx->ec_stack, count - 1))
4447cbe178e3SBram Moolenaar 			goto theend;
44484c137214SBram Moolenaar 		    ectx->ec_stack.ga_len += count - 1;
4449792f786aSBram Moolenaar 
4450792f786aSBram Moolenaar 		    // Variable after semicolon gets a list with the remaining
4451792f786aSBram Moolenaar 		    // items.
4452792f786aSBram Moolenaar 		    if (semicolon)
4453792f786aSBram Moolenaar 		    {
4454792f786aSBram Moolenaar 			list_T	*rem_list =
4455792f786aSBram Moolenaar 				  list_alloc_with_items(l->lv_len - count + 1);
4456792f786aSBram Moolenaar 
4457792f786aSBram Moolenaar 			if (rem_list == NULL)
4458cbe178e3SBram Moolenaar 			    goto theend;
4459792f786aSBram Moolenaar 			tv = STACK_TV_BOT(-count);
4460792f786aSBram Moolenaar 			tv->vval.v_list = rem_list;
4461792f786aSBram Moolenaar 			++rem_list->lv_refcount;
4462792f786aSBram Moolenaar 			tv->v_lock = 0;
4463792f786aSBram Moolenaar 			li = l->lv_first;
4464792f786aSBram Moolenaar 			for (i = 0; i < count - 1; ++i)
4465792f786aSBram Moolenaar 			    li = li->li_next;
4466792f786aSBram Moolenaar 			for (i = 0; li != NULL; ++i)
4467792f786aSBram Moolenaar 			{
4468792f786aSBram Moolenaar 			    list_set_item(rem_list, i, &li->li_tv);
4469792f786aSBram Moolenaar 			    li = li->li_next;
4470792f786aSBram Moolenaar 			}
4471792f786aSBram Moolenaar 			--count;
4472792f786aSBram Moolenaar 		    }
4473792f786aSBram Moolenaar 
4474792f786aSBram Moolenaar 		    // Produce the values in reverse order, first item last.
4475792f786aSBram Moolenaar 		    li = l->lv_first;
4476792f786aSBram Moolenaar 		    for (i = 0; i < count; ++i)
4477792f786aSBram Moolenaar 		    {
4478792f786aSBram Moolenaar 			tv = STACK_TV_BOT(-i - 1);
4479792f786aSBram Moolenaar 			copy_tv(&li->li_tv, tv);
4480792f786aSBram Moolenaar 			li = li->li_next;
4481792f786aSBram Moolenaar 		    }
4482792f786aSBram Moolenaar 
4483792f786aSBram Moolenaar 		    list_unref(l);
4484792f786aSBram Moolenaar 		}
4485792f786aSBram Moolenaar 		break;
4486792f786aSBram Moolenaar 
4487b2049903SBram Moolenaar 	    case ISN_PROF_START:
4488b2049903SBram Moolenaar 	    case ISN_PROF_END:
4489b2049903SBram Moolenaar 		{
4490f002a41dSBram Moolenaar #ifdef FEAT_PROFILE
4491b2049903SBram Moolenaar 		    funccall_T cookie;
4492b2049903SBram Moolenaar 		    ufunc_T	    *cur_ufunc =
4493b2049903SBram Moolenaar 				    (((dfunc_T *)def_functions.ga_data)
44944c137214SBram Moolenaar 					       + ectx->ec_dfunc_idx)->df_ufunc;
4495b2049903SBram Moolenaar 
4496b2049903SBram Moolenaar 		    cookie.func = cur_ufunc;
4497b2049903SBram Moolenaar 		    if (iptr->isn_type == ISN_PROF_START)
4498b2049903SBram Moolenaar 		    {
4499b2049903SBram Moolenaar 			func_line_start(&cookie, iptr->isn_lnum);
4500b2049903SBram Moolenaar 			// if we get here the instruction is executed
4501b2049903SBram Moolenaar 			func_line_exec(&cookie);
4502b2049903SBram Moolenaar 		    }
4503b2049903SBram Moolenaar 		    else
4504b2049903SBram Moolenaar 			func_line_end(&cookie);
4505f002a41dSBram Moolenaar #endif
4506b2049903SBram Moolenaar 		}
4507b2049903SBram Moolenaar 		break;
4508b2049903SBram Moolenaar 
4509e99d422bSBram Moolenaar 	    case ISN_DEBUG:
45104cea536bSBram Moolenaar 		handle_debug(iptr, ectx);
4511e99d422bSBram Moolenaar 		break;
4512e99d422bSBram Moolenaar 
4513389df259SBram Moolenaar 	    case ISN_SHUFFLE:
4514389df259SBram Moolenaar 		{
4515389df259SBram Moolenaar 		    typval_T	tmp_tv;
4516389df259SBram Moolenaar 		    int		item = iptr->isn_arg.shuffle.shfl_item;
4517389df259SBram Moolenaar 		    int		up = iptr->isn_arg.shuffle.shfl_up;
4518389df259SBram Moolenaar 
4519389df259SBram Moolenaar 		    tmp_tv = *STACK_TV_BOT(-item);
4520389df259SBram Moolenaar 		    for ( ; up > 0 && item > 1; --up)
4521389df259SBram Moolenaar 		    {
4522389df259SBram Moolenaar 			*STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1);
4523389df259SBram Moolenaar 			--item;
4524389df259SBram Moolenaar 		    }
4525389df259SBram Moolenaar 		    *STACK_TV_BOT(-item) = tmp_tv;
4526389df259SBram Moolenaar 		}
4527389df259SBram Moolenaar 		break;
4528389df259SBram Moolenaar 
45298a7d6542SBram Moolenaar 	    case ISN_DROP:
45304c137214SBram Moolenaar 		--ectx->ec_stack.ga_len;
45318a7d6542SBram Moolenaar 		clear_tv(STACK_TV_BOT(0));
45324c137214SBram Moolenaar 		ectx->ec_where.wt_index = 0;
45334c137214SBram Moolenaar 		ectx->ec_where.wt_variable = FALSE;
45348a7d6542SBram Moolenaar 		break;
45358a7d6542SBram Moolenaar 	}
4536f0b9f43cSBram Moolenaar 	continue;
4537f0b9f43cSBram Moolenaar 
4538d032f34aSBram Moolenaar func_return:
45397cbfaa51SBram Moolenaar 	// Restore previous function. If the frame pointer is where we started
45407cbfaa51SBram Moolenaar 	// then there is none and we are done.
45414c137214SBram Moolenaar 	if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
4542d032f34aSBram Moolenaar 	    goto done;
45437cbfaa51SBram Moolenaar 
45444c137214SBram Moolenaar 	if (func_return(ectx) == FAIL)
4545d032f34aSBram Moolenaar 	    // only fails when out of memory
4546cbe178e3SBram Moolenaar 	    goto theend;
4547c7db5778SBram Moolenaar 	continue;
4548d032f34aSBram Moolenaar 
4549f0b9f43cSBram Moolenaar on_error:
4550af0df47aSBram Moolenaar 	// Jump here for an error that does not require aborting execution.
455156602ba1SBram Moolenaar 	// If "emsg_silent" is set then ignore the error, unless it was set
455256602ba1SBram Moolenaar 	// when calling the function.
45534c137214SBram Moolenaar 	if (did_emsg_cumul + did_emsg == ectx->ec_did_emsg_before
455456602ba1SBram Moolenaar 					   && emsg_silent && did_emsg_def == 0)
4555f904133eSBram Moolenaar 	{
4556f904133eSBram Moolenaar 	    // If a sequence of instructions causes an error while ":silent!"
4557f904133eSBram Moolenaar 	    // was used, restore the stack length and jump ahead to restoring
4558f904133eSBram Moolenaar 	    // the cmdmod.
45594c137214SBram Moolenaar 	    if (ectx->ec_funclocal.floc_restore_cmdmod)
4560f904133eSBram Moolenaar 	    {
45614c137214SBram Moolenaar 		while (ectx->ec_stack.ga_len
45624c137214SBram Moolenaar 			     > ectx->ec_funclocal.floc_restore_cmdmod_stacklen)
4563f904133eSBram Moolenaar 		{
45644c137214SBram Moolenaar 		    --ectx->ec_stack.ga_len;
4565f904133eSBram Moolenaar 		    clear_tv(STACK_TV_BOT(0));
4566f904133eSBram Moolenaar 		}
45674c137214SBram Moolenaar 		while (ectx->ec_instr[ectx->ec_iidx].isn_type != ISN_CMDMOD_REV)
45684c137214SBram Moolenaar 		    ++ectx->ec_iidx;
4569f904133eSBram Moolenaar 	    }
4570cd030c4bSBram Moolenaar 	    continue;
4571f904133eSBram Moolenaar 	}
4572af0df47aSBram Moolenaar on_fatal_error:
4573af0df47aSBram Moolenaar 	// Jump here for an error that messes up the stack.
4574171fb923SBram Moolenaar 	// If we are not inside a try-catch started here, abort execution.
45754c137214SBram Moolenaar 	if (trylevel <= ectx->ec_trylevel_at_start)
4576cbe178e3SBram Moolenaar 	    goto theend;
45778a7d6542SBram Moolenaar     }
45788a7d6542SBram Moolenaar 
45798a7d6542SBram Moolenaar done:
4580cbe178e3SBram Moolenaar     ret = OK;
4581cbe178e3SBram Moolenaar theend:
4582b1b6f4deSBram Moolenaar     dict_stack_clear(dict_stack_len_at_start);
4583cbe178e3SBram Moolenaar     ectx->ec_trylevel_at_start = save_trylevel_at_start;
4584cbe178e3SBram Moolenaar     return ret;
45854c137214SBram Moolenaar }
45864c137214SBram Moolenaar 
45874c137214SBram Moolenaar /*
4588f18332fbSBram Moolenaar  * Execute the instructions from a VAR_INSTR typeval and put the result in
4589f18332fbSBram Moolenaar  * "rettv".
4590f18332fbSBram Moolenaar  * Return OK or FAIL.
4591f18332fbSBram Moolenaar  */
4592f18332fbSBram Moolenaar     int
exe_typval_instr(typval_T * tv,typval_T * rettv)4593f18332fbSBram Moolenaar exe_typval_instr(typval_T *tv, typval_T *rettv)
4594f18332fbSBram Moolenaar {
4595f18332fbSBram Moolenaar     ectx_T	*ectx = tv->vval.v_instr->instr_ectx;
4596f18332fbSBram Moolenaar     isn_T	*save_instr = ectx->ec_instr;
4597f18332fbSBram Moolenaar     int		save_iidx = ectx->ec_iidx;
4598f18332fbSBram Moolenaar     int		res;
4599f18332fbSBram Moolenaar 
4600f18332fbSBram Moolenaar     ectx->ec_instr = tv->vval.v_instr->instr_instr;
4601f18332fbSBram Moolenaar     res = exec_instructions(ectx);
4602f18332fbSBram Moolenaar     if (res == OK)
4603f18332fbSBram Moolenaar     {
4604f18332fbSBram Moolenaar 	*rettv = *STACK_TV_BOT(-1);
4605f18332fbSBram Moolenaar 	--ectx->ec_stack.ga_len;
4606f18332fbSBram Moolenaar     }
4607f18332fbSBram Moolenaar 
4608f18332fbSBram Moolenaar     ectx->ec_instr = save_instr;
4609f18332fbSBram Moolenaar     ectx->ec_iidx = save_iidx;
4610f18332fbSBram Moolenaar 
4611f18332fbSBram Moolenaar     return res;
4612f18332fbSBram Moolenaar }
4613f18332fbSBram Moolenaar 
4614f18332fbSBram Moolenaar /*
46154c137214SBram Moolenaar  * Execute the instructions from an ISN_SUBSTITUTE command, which are in
46164c137214SBram Moolenaar  * "substitute_instr".
46174c137214SBram Moolenaar  */
46184c137214SBram Moolenaar     char_u *
exe_substitute_instr(void)46194c137214SBram Moolenaar exe_substitute_instr(void)
46204c137214SBram Moolenaar {
46214c137214SBram Moolenaar     ectx_T	*ectx = substitute_instr->subs_ectx;
46224c137214SBram Moolenaar     isn_T	*save_instr = ectx->ec_instr;
46234c137214SBram Moolenaar     int		save_iidx = ectx->ec_iidx;
46244c137214SBram Moolenaar     char_u	*res;
46254c137214SBram Moolenaar 
46264c137214SBram Moolenaar     ectx->ec_instr = substitute_instr->subs_instr;
46274c137214SBram Moolenaar     if (exec_instructions(ectx) == OK)
46284c137214SBram Moolenaar     {
46294c137214SBram Moolenaar 	typval_T *tv = STACK_TV_BOT(-1);
46304c137214SBram Moolenaar 
463127523606SBram Moolenaar 	res = typval2string(tv, TRUE);
46324c137214SBram Moolenaar 	--ectx->ec_stack.ga_len;
46334c137214SBram Moolenaar 	clear_tv(tv);
46344c137214SBram Moolenaar     }
46354c137214SBram Moolenaar     else
46364c137214SBram Moolenaar     {
46374c137214SBram Moolenaar 	substitute_instr->subs_status = FAIL;
46384c137214SBram Moolenaar 	res = vim_strsave((char_u *)"");
46394c137214SBram Moolenaar     }
46404c137214SBram Moolenaar 
46414c137214SBram Moolenaar     ectx->ec_instr = save_instr;
46424c137214SBram Moolenaar     ectx->ec_iidx = save_iidx;
46434c137214SBram Moolenaar 
46444c137214SBram Moolenaar     return res;
46454c137214SBram Moolenaar }
46464c137214SBram Moolenaar 
46474c137214SBram Moolenaar /*
46484c137214SBram Moolenaar  * Call a "def" function from old Vim script.
46494c137214SBram Moolenaar  * Return OK or FAIL.
46504c137214SBram Moolenaar  */
46514c137214SBram Moolenaar     int
call_def_function(ufunc_T * ufunc,int argc_arg,typval_T * argv,partial_T * partial,typval_T * rettv)46524c137214SBram Moolenaar call_def_function(
46534c137214SBram Moolenaar     ufunc_T	*ufunc,
46544c137214SBram Moolenaar     int		argc_arg,	// nr of arguments
46554c137214SBram Moolenaar     typval_T	*argv,		// arguments
46564c137214SBram Moolenaar     partial_T	*partial,	// optional partial for context
46574c137214SBram Moolenaar     typval_T	*rettv)		// return value
46584c137214SBram Moolenaar {
46594c137214SBram Moolenaar     ectx_T	ectx;		// execution context
46604c137214SBram Moolenaar     int		argc = argc_arg;
46614c137214SBram Moolenaar     typval_T	*tv;
46624c137214SBram Moolenaar     int		idx;
46634c137214SBram Moolenaar     int		ret = FAIL;
46644c137214SBram Moolenaar     int		defcount = ufunc->uf_args.ga_len - argc;
46654c137214SBram Moolenaar     sctx_T	save_current_sctx = current_sctx;
46664c137214SBram Moolenaar     int		did_emsg_before = did_emsg_cumul + did_emsg;
46674c137214SBram Moolenaar     int		save_suppress_errthrow = suppress_errthrow;
46684c137214SBram Moolenaar     msglist_T	**saved_msg_list = NULL;
46694c137214SBram Moolenaar     msglist_T	*private_msg_list = NULL;
46704c137214SBram Moolenaar     int		save_emsg_silent_def = emsg_silent_def;
46714c137214SBram Moolenaar     int		save_did_emsg_def = did_emsg_def;
46724c137214SBram Moolenaar     int		orig_funcdepth;
4673e99d422bSBram Moolenaar     int		orig_nesting_level = ex_nesting_level;
46744c137214SBram Moolenaar 
46754c137214SBram Moolenaar // Get pointer to item in the stack.
46764c137214SBram Moolenaar #undef STACK_TV
46774c137214SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
46784c137214SBram Moolenaar 
46794c137214SBram Moolenaar // Get pointer to item at the bottom of the stack, -1 is the bottom.
46804c137214SBram Moolenaar #undef STACK_TV_BOT
46814c137214SBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
46824c137214SBram Moolenaar 
46834c137214SBram Moolenaar // Get pointer to a local variable on the stack.  Negative for arguments.
46844c137214SBram Moolenaar #undef STACK_TV_VAR
46854c137214SBram Moolenaar #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
46864c137214SBram Moolenaar 
46874f8f5428SBram Moolenaar     // Update uf_has_breakpoint if needed.
46884f8f5428SBram Moolenaar     update_has_breakpoint(ufunc);
46894f8f5428SBram Moolenaar 
46904c137214SBram Moolenaar     if (ufunc->uf_def_status == UF_NOT_COMPILED
46914c137214SBram Moolenaar 	    || ufunc->uf_def_status == UF_COMPILE_ERROR
4692e99d422bSBram Moolenaar 	    || (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
4693e99d422bSBram Moolenaar 		&& compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
46944c137214SBram Moolenaar 								      == FAIL))
46954c137214SBram Moolenaar     {
46964c137214SBram Moolenaar 	if (did_emsg_cumul + did_emsg == did_emsg_before)
46974c137214SBram Moolenaar 	    semsg(_(e_function_is_not_compiled_str),
46984c137214SBram Moolenaar 						   printable_func_name(ufunc));
46994c137214SBram Moolenaar 	return FAIL;
47004c137214SBram Moolenaar     }
47014c137214SBram Moolenaar 
47024c137214SBram Moolenaar     {
47034c137214SBram Moolenaar 	// Check the function was really compiled.
47044c137214SBram Moolenaar 	dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
47054c137214SBram Moolenaar 							 + ufunc->uf_dfunc_idx;
47064c137214SBram Moolenaar 	if (INSTRUCTIONS(dfunc) == NULL)
47074c137214SBram Moolenaar 	{
47084c137214SBram Moolenaar 	    iemsg("using call_def_function() on not compiled function");
47094c137214SBram Moolenaar 	    return FAIL;
47104c137214SBram Moolenaar 	}
47114c137214SBram Moolenaar     }
47124c137214SBram Moolenaar 
47134c137214SBram Moolenaar     // If depth of calling is getting too high, don't execute the function.
47144c137214SBram Moolenaar     orig_funcdepth = funcdepth_get();
47154c137214SBram Moolenaar     if (funcdepth_increment() == FAIL)
47164c137214SBram Moolenaar 	return FAIL;
47174c137214SBram Moolenaar 
47184c137214SBram Moolenaar     CLEAR_FIELD(ectx);
47194c137214SBram Moolenaar     ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
47204c137214SBram Moolenaar     ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
472135578168SBram Moolenaar     if (GA_GROW_FAILS(&ectx.ec_stack, 20))
47224c137214SBram Moolenaar     {
47234c137214SBram Moolenaar 	funcdepth_decrement();
47244c137214SBram Moolenaar 	return FAIL;
47254c137214SBram Moolenaar     }
47264c137214SBram Moolenaar     ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
47274c137214SBram Moolenaar     ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
47284c137214SBram Moolenaar     ectx.ec_did_emsg_before = did_emsg_before;
4729e99d422bSBram Moolenaar     ++ex_nesting_level;
47304c137214SBram Moolenaar 
47314c137214SBram Moolenaar     idx = argc - ufunc->uf_args.ga_len;
47324c137214SBram Moolenaar     if (idx > 0 && ufunc->uf_va_name == NULL)
47334c137214SBram Moolenaar     {
47344c137214SBram Moolenaar 	if (idx == 1)
47354c137214SBram Moolenaar 	    emsg(_(e_one_argument_too_many));
47364c137214SBram Moolenaar 	else
47374c137214SBram Moolenaar 	    semsg(_(e_nr_arguments_too_many), idx);
47384c137214SBram Moolenaar 	goto failed_early;
47394c137214SBram Moolenaar     }
4740c6d71532SBram Moolenaar     idx = argc - ufunc->uf_args.ga_len + ufunc->uf_def_args.ga_len;
4741c6d71532SBram Moolenaar     if (idx < 0)
47428da6d6dbSBram Moolenaar     {
47438da6d6dbSBram Moolenaar 	if (idx == -1)
47448da6d6dbSBram Moolenaar 	    emsg(_(e_one_argument_too_few));
47458da6d6dbSBram Moolenaar 	else
47468da6d6dbSBram Moolenaar 	    semsg(_(e_nr_arguments_too_few), -idx);
47478da6d6dbSBram Moolenaar 	goto failed_early;
47488da6d6dbSBram Moolenaar     }
47494c137214SBram Moolenaar 
47504c137214SBram Moolenaar     // Put arguments on the stack, but no more than what the function expects.
47514c137214SBram Moolenaar     // A lambda can be called with more arguments than it uses.
47524c137214SBram Moolenaar     for (idx = 0; idx < argc
47534c137214SBram Moolenaar 	    && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len);
47544c137214SBram Moolenaar 									 ++idx)
47554c137214SBram Moolenaar     {
47564c137214SBram Moolenaar 	if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len
47574c137214SBram Moolenaar 		&& argv[idx].v_type == VAR_SPECIAL
47584c137214SBram Moolenaar 		&& argv[idx].vval.v_number == VVAL_NONE)
47594c137214SBram Moolenaar 	{
47604c137214SBram Moolenaar 	    // Use the default value.
47614c137214SBram Moolenaar 	    STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
47624c137214SBram Moolenaar 	}
47634c137214SBram Moolenaar 	else
47644c137214SBram Moolenaar 	{
47654c137214SBram Moolenaar 	    if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
47664c137214SBram Moolenaar 		    && check_typval_arg_type(
47677a3fe3e1SBram Moolenaar 			ufunc->uf_arg_types[idx], &argv[idx],
47687a3fe3e1SBram Moolenaar 							NULL, idx + 1) == FAIL)
47694c137214SBram Moolenaar 		goto failed_early;
47704c137214SBram Moolenaar 	    copy_tv(&argv[idx], STACK_TV_BOT(0));
47714c137214SBram Moolenaar 	}
47724c137214SBram Moolenaar 	++ectx.ec_stack.ga_len;
47734c137214SBram Moolenaar     }
47744c137214SBram Moolenaar 
47754c137214SBram Moolenaar     // Turn varargs into a list.  Empty list if no args.
47764c137214SBram Moolenaar     if (ufunc->uf_va_name != NULL)
47774c137214SBram Moolenaar     {
47784c137214SBram Moolenaar 	int vararg_count = argc - ufunc->uf_args.ga_len;
47794c137214SBram Moolenaar 
47804c137214SBram Moolenaar 	if (vararg_count < 0)
47814c137214SBram Moolenaar 	    vararg_count = 0;
47824c137214SBram Moolenaar 	else
47834c137214SBram Moolenaar 	    argc -= vararg_count;
47844c137214SBram Moolenaar 	if (exe_newlist(vararg_count, &ectx) == FAIL)
47854c137214SBram Moolenaar 	    goto failed_early;
47864c137214SBram Moolenaar 
47874c137214SBram Moolenaar 	// Check the type of the list items.
47884c137214SBram Moolenaar 	tv = STACK_TV_BOT(-1);
47894c137214SBram Moolenaar 	if (ufunc->uf_va_type != NULL
47904c137214SBram Moolenaar 		&& ufunc->uf_va_type != &t_list_any
47914c137214SBram Moolenaar 		&& ufunc->uf_va_type->tt_member != &t_any
47924c137214SBram Moolenaar 		&& tv->vval.v_list != NULL)
47934c137214SBram Moolenaar 	{
47944c137214SBram Moolenaar 	    type_T	*expected = ufunc->uf_va_type->tt_member;
47954c137214SBram Moolenaar 	    listitem_T	*li = tv->vval.v_list->lv_first;
47964c137214SBram Moolenaar 
47974c137214SBram Moolenaar 	    for (idx = 0; idx < vararg_count; ++idx)
47984c137214SBram Moolenaar 	    {
47994c137214SBram Moolenaar 		if (check_typval_arg_type(expected, &li->li_tv,
48007a3fe3e1SBram Moolenaar 						 NULL, argc + idx + 1) == FAIL)
48014c137214SBram Moolenaar 		    goto failed_early;
48024c137214SBram Moolenaar 		li = li->li_next;
48034c137214SBram Moolenaar 	    }
48044c137214SBram Moolenaar 	}
48054c137214SBram Moolenaar 
48064c137214SBram Moolenaar 	if (defcount > 0)
48074c137214SBram Moolenaar 	    // Move varargs list to below missing default arguments.
48084c137214SBram Moolenaar 	    *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1);
48094c137214SBram Moolenaar 	--ectx.ec_stack.ga_len;
48104c137214SBram Moolenaar     }
48114c137214SBram Moolenaar 
48124c137214SBram Moolenaar     // Make space for omitted arguments, will store default value below.
48134c137214SBram Moolenaar     // Any varargs list goes after them.
48144c137214SBram Moolenaar     if (defcount > 0)
48154c137214SBram Moolenaar 	for (idx = 0; idx < defcount; ++idx)
48164c137214SBram Moolenaar 	{
48174c137214SBram Moolenaar 	    STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
48184c137214SBram Moolenaar 	    ++ectx.ec_stack.ga_len;
48194c137214SBram Moolenaar 	}
48204c137214SBram Moolenaar     if (ufunc->uf_va_name != NULL)
48214c137214SBram Moolenaar 	++ectx.ec_stack.ga_len;
48224c137214SBram Moolenaar 
48234c137214SBram Moolenaar     // Frame pointer points to just after arguments.
48244c137214SBram Moolenaar     ectx.ec_frame_idx = ectx.ec_stack.ga_len;
48254c137214SBram Moolenaar     ectx.ec_initial_frame_idx = ectx.ec_frame_idx;
48264c137214SBram Moolenaar 
48274c137214SBram Moolenaar     {
48284c137214SBram Moolenaar 	dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
48294c137214SBram Moolenaar 							 + ufunc->uf_dfunc_idx;
48304c137214SBram Moolenaar 	ufunc_T *base_ufunc = dfunc->df_ufunc;
48314c137214SBram Moolenaar 
48324c137214SBram Moolenaar 	// "uf_partial" is on the ufunc that "df_ufunc" points to, as is done
48334c137214SBram Moolenaar 	// by copy_func().
48344c137214SBram Moolenaar 	if (partial != NULL || base_ufunc->uf_partial != NULL)
48354c137214SBram Moolenaar 	{
4836c04f2a4cSBram Moolenaar 	    ectx.ec_outer_ref = ALLOC_CLEAR_ONE(outer_ref_T);
4837c04f2a4cSBram Moolenaar 	    if (ectx.ec_outer_ref == NULL)
48384c137214SBram Moolenaar 		goto failed_early;
48394c137214SBram Moolenaar 	    if (partial != NULL)
48404c137214SBram Moolenaar 	    {
48414c137214SBram Moolenaar 		if (partial->pt_outer.out_stack == NULL && current_ectx != NULL)
48424c137214SBram Moolenaar 		{
4843c04f2a4cSBram Moolenaar 		    if (current_ectx->ec_outer_ref != NULL
4844c04f2a4cSBram Moolenaar 			    && current_ectx->ec_outer_ref->or_outer != NULL)
4845c04f2a4cSBram Moolenaar 			ectx.ec_outer_ref->or_outer =
4846c04f2a4cSBram Moolenaar 					  current_ectx->ec_outer_ref->or_outer;
48474c137214SBram Moolenaar 		}
48484c137214SBram Moolenaar 		else
4849c04f2a4cSBram Moolenaar 		{
4850c04f2a4cSBram Moolenaar 		    ectx.ec_outer_ref->or_outer = &partial->pt_outer;
4851c04f2a4cSBram Moolenaar 		    ++partial->pt_refcount;
4852c04f2a4cSBram Moolenaar 		    ectx.ec_outer_ref->or_partial = partial;
4853c04f2a4cSBram Moolenaar 		}
48544c137214SBram Moolenaar 	    }
48554c137214SBram Moolenaar 	    else
4856c04f2a4cSBram Moolenaar 	    {
4857c04f2a4cSBram Moolenaar 		ectx.ec_outer_ref->or_outer = &base_ufunc->uf_partial->pt_outer;
4858c04f2a4cSBram Moolenaar 		++base_ufunc->uf_partial->pt_refcount;
4859c04f2a4cSBram Moolenaar 		ectx.ec_outer_ref->or_partial = base_ufunc->uf_partial;
4860c04f2a4cSBram Moolenaar 	    }
48614c137214SBram Moolenaar 	}
48624c137214SBram Moolenaar     }
48634c137214SBram Moolenaar 
48644c137214SBram Moolenaar     // dummy frame entries
48654c137214SBram Moolenaar     for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
48664c137214SBram Moolenaar     {
48674c137214SBram Moolenaar 	STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
48684c137214SBram Moolenaar 	++ectx.ec_stack.ga_len;
48694c137214SBram Moolenaar     }
48704c137214SBram Moolenaar 
48714c137214SBram Moolenaar     {
48724c137214SBram Moolenaar 	// Reserve space for local variables and any closure reference count.
48734c137214SBram Moolenaar 	dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
48744c137214SBram Moolenaar 							 + ufunc->uf_dfunc_idx;
48754c137214SBram Moolenaar 
48764c137214SBram Moolenaar 	for (idx = 0; idx < dfunc->df_varcount; ++idx)
48774c137214SBram Moolenaar 	    STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
48784c137214SBram Moolenaar 	ectx.ec_stack.ga_len += dfunc->df_varcount;
48794c137214SBram Moolenaar 	if (dfunc->df_has_closure)
48804c137214SBram Moolenaar 	{
48814c137214SBram Moolenaar 	    STACK_TV_VAR(idx)->v_type = VAR_NUMBER;
48824c137214SBram Moolenaar 	    STACK_TV_VAR(idx)->vval.v_number = 0;
48834c137214SBram Moolenaar 	    ++ectx.ec_stack.ga_len;
48844c137214SBram Moolenaar 	}
48854c137214SBram Moolenaar 
48864c137214SBram Moolenaar 	ectx.ec_instr = INSTRUCTIONS(dfunc);
48874c137214SBram Moolenaar     }
48884c137214SBram Moolenaar 
48894c137214SBram Moolenaar     // Following errors are in the function, not the caller.
48904c137214SBram Moolenaar     // Commands behave like vim9script.
48914c137214SBram Moolenaar     estack_push_ufunc(ufunc, 1);
48924c137214SBram Moolenaar     current_sctx = ufunc->uf_script_ctx;
48934c137214SBram Moolenaar     current_sctx.sc_version = SCRIPT_VERSION_VIM9;
48944c137214SBram Moolenaar 
48954c137214SBram Moolenaar     // Use a specific location for storing error messages to be converted to an
48964c137214SBram Moolenaar     // exception.
48974c137214SBram Moolenaar     saved_msg_list = msg_list;
48984c137214SBram Moolenaar     msg_list = &private_msg_list;
48994c137214SBram Moolenaar 
49004c137214SBram Moolenaar     // Do turn errors into exceptions.
49014c137214SBram Moolenaar     suppress_errthrow = FALSE;
49024c137214SBram Moolenaar 
49034c137214SBram Moolenaar     // Do not delete the function while executing it.
49044c137214SBram Moolenaar     ++ufunc->uf_calls;
49054c137214SBram Moolenaar 
49064c137214SBram Moolenaar     // When ":silent!" was used before calling then we still abort the
49074c137214SBram Moolenaar     // function.  If ":silent!" is used in the function then we don't.
49084c137214SBram Moolenaar     emsg_silent_def = emsg_silent;
49094c137214SBram Moolenaar     did_emsg_def = 0;
49104c137214SBram Moolenaar 
49114c137214SBram Moolenaar     ectx.ec_where.wt_index = 0;
49124c137214SBram Moolenaar     ectx.ec_where.wt_variable = FALSE;
49134c137214SBram Moolenaar 
49144c137214SBram Moolenaar     // Execute the instructions until done.
49154c137214SBram Moolenaar     ret = exec_instructions(&ectx);
49164c137214SBram Moolenaar     if (ret == OK)
49174c137214SBram Moolenaar     {
49188a7d6542SBram Moolenaar 	// function finished, get result from the stack.
491990193e61SBram Moolenaar 	if (ufunc->uf_ret_type == &t_void)
492090193e61SBram Moolenaar 	{
492190193e61SBram Moolenaar 	    rettv->v_type = VAR_VOID;
492290193e61SBram Moolenaar 	}
492390193e61SBram Moolenaar 	else
492490193e61SBram Moolenaar 	{
49258a7d6542SBram Moolenaar 	    tv = STACK_TV_BOT(-1);
49268a7d6542SBram Moolenaar 	    *rettv = *tv;
49278a7d6542SBram Moolenaar 	    tv->v_type = VAR_UNKNOWN;
492890193e61SBram Moolenaar 	}
49294c137214SBram Moolenaar     }
49308a7d6542SBram Moolenaar 
49317eeefd4aSBram Moolenaar     // When failed need to unwind the call stack.
49324c137214SBram Moolenaar     while (ectx.ec_frame_idx != ectx.ec_initial_frame_idx)
49334c137214SBram Moolenaar 	func_return(&ectx);
4934bf67ea1aSBram Moolenaar 
4935c70bdab0SBram Moolenaar     // Deal with any remaining closures, they may be in use somewhere.
4936c70bdab0SBram Moolenaar     if (ectx.ec_funcrefs.ga_len > 0)
4937f112f30aSBram Moolenaar     {
4938c70bdab0SBram Moolenaar 	handle_closure_in_use(&ectx, FALSE);
4939f112f30aSBram Moolenaar 	ga_clear(&ectx.ec_funcrefs);  // TODO: should not be needed?
4940f112f30aSBram Moolenaar     }
4941c70bdab0SBram Moolenaar 
4942ee8580e5SBram Moolenaar     estack_pop();
4943ee8580e5SBram Moolenaar     current_sctx = save_current_sctx;
4944ee8580e5SBram Moolenaar 
4945c970e422SBram Moolenaar     // TODO: when is it safe to delete the function if it is no longer used?
4946c970e422SBram Moolenaar     --ufunc->uf_calls;
4947c970e422SBram Moolenaar 
4948352134bbSBram Moolenaar     if (*msg_list != NULL && saved_msg_list != NULL)
4949352134bbSBram Moolenaar     {
4950352134bbSBram Moolenaar 	msglist_T **plist = saved_msg_list;
4951352134bbSBram Moolenaar 
4952352134bbSBram Moolenaar 	// Append entries from the current msg_list (uncaught exceptions) to
4953352134bbSBram Moolenaar 	// the saved msg_list.
4954352134bbSBram Moolenaar 	while (*plist != NULL)
4955352134bbSBram Moolenaar 	    plist = &(*plist)->next;
4956352134bbSBram Moolenaar 
4957352134bbSBram Moolenaar 	*plist = *msg_list;
4958352134bbSBram Moolenaar     }
4959352134bbSBram Moolenaar     msg_list = saved_msg_list;
4960352134bbSBram Moolenaar 
49614c137214SBram Moolenaar     if (ectx.ec_funclocal.floc_restore_cmdmod)
496202194d2bSBram Moolenaar     {
496302194d2bSBram Moolenaar 	cmdmod.cmod_filter_regmatch.regprog = NULL;
496402194d2bSBram Moolenaar 	undo_cmdmod(&cmdmod);
49654c137214SBram Moolenaar 	cmdmod = ectx.ec_funclocal.floc_save_cmdmod;
496602194d2bSBram Moolenaar     }
496756602ba1SBram Moolenaar     emsg_silent_def = save_emsg_silent_def;
496856602ba1SBram Moolenaar     did_emsg_def += save_did_emsg_def;
4969f4c6e1e7SBram Moolenaar 
4970ee8580e5SBram Moolenaar failed_early:
4971bf67ea1aSBram Moolenaar     // Free all local variables, but not arguments.
49728a7d6542SBram Moolenaar     for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
49738a7d6542SBram Moolenaar 	clear_tv(STACK_TV(idx));
4974e99d422bSBram Moolenaar     ex_nesting_level = orig_nesting_level;
4975bf67ea1aSBram Moolenaar 
49768a7d6542SBram Moolenaar     vim_free(ectx.ec_stack.ga_data);
497720431c9dSBram Moolenaar     vim_free(ectx.ec_trystack.ga_data);
4978c04f2a4cSBram Moolenaar     if (ectx.ec_outer_ref != NULL)
49790186e586SBram Moolenaar     {
4980c04f2a4cSBram Moolenaar 	if (ectx.ec_outer_ref->or_outer_allocated)
4981c04f2a4cSBram Moolenaar 	    vim_free(ectx.ec_outer_ref->or_outer);
4982c04f2a4cSBram Moolenaar 	partial_unref(ectx.ec_outer_ref->or_partial);
4983c04f2a4cSBram Moolenaar 	vim_free(ectx.ec_outer_ref);
49840186e586SBram Moolenaar     }
49850186e586SBram Moolenaar 
498677e5dcc3SBram Moolenaar     // Not sure if this is necessary.
498777e5dcc3SBram Moolenaar     suppress_errthrow = save_suppress_errthrow;
498877e5dcc3SBram Moolenaar 
4989b5841b99SBram Moolenaar     if (ret != OK && did_emsg_cumul + did_emsg == did_emsg_before
4990b5841b99SBram Moolenaar 							      && !need_rethrow)
4991451c2e35SBram Moolenaar 	semsg(_(e_unknown_error_while_executing_str),
4992682d0a15SBram Moolenaar 						   printable_func_name(ufunc));
49930ba48e8cSBram Moolenaar     funcdepth_restore(orig_funcdepth);
49948a7d6542SBram Moolenaar     return ret;
49958a7d6542SBram Moolenaar }
49968a7d6542SBram Moolenaar 
49978a7d6542SBram Moolenaar /*
49984c137214SBram Moolenaar  * List instructions "instr" up to "instr_count" or until ISN_FINISH.
49994c137214SBram Moolenaar  * "ufunc" has the source lines, NULL for the instructions of ISN_SUBSTITUTE.
50004c137214SBram Moolenaar  * "pfx" is prefixed to every line.
50014c137214SBram Moolenaar  */
50024c137214SBram Moolenaar     static void
list_instructions(char * pfx,isn_T * instr,int instr_count,ufunc_T * ufunc)50034c137214SBram Moolenaar list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
50044c137214SBram Moolenaar {
50054c137214SBram Moolenaar     int		line_idx = 0;
50064c137214SBram Moolenaar     int		prev_current = 0;
50074c137214SBram Moolenaar     int		current;
50089ce47ec0SBram Moolenaar     int		def_arg_idx = 0;
50094c137214SBram Moolenaar 
50104c137214SBram Moolenaar     for (current = 0; current < instr_count; ++current)
50114c137214SBram Moolenaar     {
50124c137214SBram Moolenaar 	isn_T	    *iptr = &instr[current];
50134c137214SBram Moolenaar 	char	    *line;
50144c137214SBram Moolenaar 
50154c137214SBram Moolenaar 	if (ufunc != NULL)
50169ce47ec0SBram Moolenaar 	{
50174c137214SBram Moolenaar 	    while (line_idx < iptr->isn_lnum
50184c137214SBram Moolenaar 					  && line_idx < ufunc->uf_lines.ga_len)
50194c137214SBram Moolenaar 	    {
50204c137214SBram Moolenaar 		if (current > prev_current)
50214c137214SBram Moolenaar 		{
50224c137214SBram Moolenaar 		    msg_puts("\n\n");
50234c137214SBram Moolenaar 		    prev_current = current;
50244c137214SBram Moolenaar 		}
50254c137214SBram Moolenaar 		line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
50264c137214SBram Moolenaar 		if (line != NULL)
50274c137214SBram Moolenaar 		    msg(line);
50284c137214SBram Moolenaar 	    }
50299ce47ec0SBram Moolenaar 	    if (iptr->isn_type == ISN_JUMP_IF_ARG_SET)
50309ce47ec0SBram Moolenaar 	    {
50319ce47ec0SBram Moolenaar 		int	first_def_arg = ufunc->uf_args.ga_len
50329ce47ec0SBram Moolenaar 						   - ufunc->uf_def_args.ga_len;
50339ce47ec0SBram Moolenaar 
50349ce47ec0SBram Moolenaar 		if (def_arg_idx > 0)
50359ce47ec0SBram Moolenaar 		    msg_puts("\n\n");
50369ce47ec0SBram Moolenaar 		msg_start();
50379ce47ec0SBram Moolenaar 		msg_puts("  ");
50389ce47ec0SBram Moolenaar 		msg_puts(((char **)(ufunc->uf_args.ga_data))[
50399ce47ec0SBram Moolenaar 						 first_def_arg + def_arg_idx]);
50409ce47ec0SBram Moolenaar 		msg_puts(" = ");
50419ce47ec0SBram Moolenaar 		msg_puts(((char **)(ufunc->uf_def_args.ga_data))[def_arg_idx++]);
50429ce47ec0SBram Moolenaar 		msg_clr_eos();
50439ce47ec0SBram Moolenaar 		msg_end();
50449ce47ec0SBram Moolenaar 	    }
50459ce47ec0SBram Moolenaar 	}
50464c137214SBram Moolenaar 
50474c137214SBram Moolenaar 	switch (iptr->isn_type)
50484c137214SBram Moolenaar 	{
50494c137214SBram Moolenaar 	    case ISN_EXEC:
50504c137214SBram Moolenaar 		smsg("%s%4d EXEC %s", pfx, current, iptr->isn_arg.string);
50514c137214SBram Moolenaar 		break;
50522067733bSBram Moolenaar 	    case ISN_EXEC_SPLIT:
50532067733bSBram Moolenaar 		smsg("%s%4d EXEC_SPLIT %s", pfx, current, iptr->isn_arg.string);
50542067733bSBram Moolenaar 		break;
50553b1373b1SBram Moolenaar 	    case ISN_LEGACY_EVAL:
50563b1373b1SBram Moolenaar 		smsg("%s%4d EVAL legacy %s", pfx, current,
50573b1373b1SBram Moolenaar 							 iptr->isn_arg.string);
50583b1373b1SBram Moolenaar 		break;
50592d1c57edSBram Moolenaar 	    case ISN_REDIRSTART:
50602d1c57edSBram Moolenaar 		smsg("%s%4d REDIR", pfx, current);
50612d1c57edSBram Moolenaar 		break;
50622d1c57edSBram Moolenaar 	    case ISN_REDIREND:
50632d1c57edSBram Moolenaar 		smsg("%s%4d REDIR END%s", pfx, current,
50642d1c57edSBram Moolenaar 					iptr->isn_arg.number ? " append" : "");
50652d1c57edSBram Moolenaar 		break;
50665f7d4c04SBram Moolenaar 	    case ISN_CEXPR_AUCMD:
5067b7c97815SBram Moolenaar #ifdef FEAT_QUICKFIX
50685f7d4c04SBram Moolenaar 		smsg("%s%4d CEXPR pre %s", pfx, current,
50695f7d4c04SBram Moolenaar 				       cexpr_get_auname(iptr->isn_arg.number));
5070b7c97815SBram Moolenaar #endif
50715f7d4c04SBram Moolenaar 		break;
50725f7d4c04SBram Moolenaar 	    case ISN_CEXPR_CORE:
5073b7c97815SBram Moolenaar #ifdef FEAT_QUICKFIX
50745f7d4c04SBram Moolenaar 		{
50755f7d4c04SBram Moolenaar 		    cexprref_T	    *cer = iptr->isn_arg.cexpr.cexpr_ref;
50765f7d4c04SBram Moolenaar 
50775f7d4c04SBram Moolenaar 		    smsg("%s%4d CEXPR core %s%s \"%s\"", pfx, current,
50785f7d4c04SBram Moolenaar 				       cexpr_get_auname(cer->cer_cmdidx),
50795f7d4c04SBram Moolenaar 				       cer->cer_forceit ? "!" : "",
50805f7d4c04SBram Moolenaar 				       cer->cer_cmdline);
50815f7d4c04SBram Moolenaar 		}
5082b7c97815SBram Moolenaar #endif
50835f7d4c04SBram Moolenaar 		break;
5084f18332fbSBram Moolenaar 	    case ISN_INSTR:
5085f18332fbSBram Moolenaar 		{
5086f18332fbSBram Moolenaar 		    smsg("%s%4d INSTR", pfx, current);
5087f18332fbSBram Moolenaar 		    list_instructions("    ", iptr->isn_arg.instr,
5088f18332fbSBram Moolenaar 								INT_MAX, NULL);
5089f18332fbSBram Moolenaar 		    msg("     -------------");
5090f18332fbSBram Moolenaar 		}
5091f18332fbSBram Moolenaar 		break;
50924c137214SBram Moolenaar 	    case ISN_SUBSTITUTE:
50934c137214SBram Moolenaar 		{
50944c137214SBram Moolenaar 		    subs_T *subs = &iptr->isn_arg.subs;
50954c137214SBram Moolenaar 
50964c137214SBram Moolenaar 		    smsg("%s%4d SUBSTITUTE %s", pfx, current, subs->subs_cmd);
50974c137214SBram Moolenaar 		    list_instructions("    ", subs->subs_instr, INT_MAX, NULL);
50984c137214SBram Moolenaar 		    msg("     -------------");
50994c137214SBram Moolenaar 		}
51004c137214SBram Moolenaar 		break;
51014c137214SBram Moolenaar 	    case ISN_EXECCONCAT:
51024c137214SBram Moolenaar 		smsg("%s%4d EXECCONCAT %lld", pfx, current,
51034c137214SBram Moolenaar 					      (varnumber_T)iptr->isn_arg.number);
51044c137214SBram Moolenaar 		break;
51054c137214SBram Moolenaar 	    case ISN_ECHO:
51064c137214SBram Moolenaar 		{
51074c137214SBram Moolenaar 		    echo_T *echo = &iptr->isn_arg.echo;
51084c137214SBram Moolenaar 
51094c137214SBram Moolenaar 		    smsg("%s%4d %s %d", pfx, current,
51104c137214SBram Moolenaar 			    echo->echo_with_white ? "ECHO" : "ECHON",
51114c137214SBram Moolenaar 			    echo->echo_count);
51124c137214SBram Moolenaar 		}
51134c137214SBram Moolenaar 		break;
51144c137214SBram Moolenaar 	    case ISN_EXECUTE:
51154c137214SBram Moolenaar 		smsg("%s%4d EXECUTE %lld", pfx, current,
51164c137214SBram Moolenaar 					  (varnumber_T)(iptr->isn_arg.number));
51174c137214SBram Moolenaar 		break;
51184c137214SBram Moolenaar 	    case ISN_ECHOMSG:
51194c137214SBram Moolenaar 		smsg("%s%4d ECHOMSG %lld", pfx, current,
51204c137214SBram Moolenaar 					  (varnumber_T)(iptr->isn_arg.number));
51214c137214SBram Moolenaar 		break;
51227de62623SBram Moolenaar 	    case ISN_ECHOCONSOLE:
51237de62623SBram Moolenaar 		smsg("%s%4d ECHOCONSOLE %lld", pfx, current,
51247de62623SBram Moolenaar 					  (varnumber_T)(iptr->isn_arg.number));
51257de62623SBram Moolenaar 		break;
51264c137214SBram Moolenaar 	    case ISN_ECHOERR:
51274c137214SBram Moolenaar 		smsg("%s%4d ECHOERR %lld", pfx, current,
51284c137214SBram Moolenaar 					  (varnumber_T)(iptr->isn_arg.number));
51294c137214SBram Moolenaar 		break;
51304c137214SBram Moolenaar 	    case ISN_LOAD:
51314c137214SBram Moolenaar 		{
51324c137214SBram Moolenaar 		    if (iptr->isn_arg.number < 0)
51334c137214SBram Moolenaar 			smsg("%s%4d LOAD arg[%lld]", pfx, current,
51344c137214SBram Moolenaar 				(varnumber_T)(iptr->isn_arg.number
51354c137214SBram Moolenaar 							  + STACK_FRAME_SIZE));
51364c137214SBram Moolenaar 		    else
51374c137214SBram Moolenaar 			smsg("%s%4d LOAD $%lld", pfx, current,
51384c137214SBram Moolenaar 					  (varnumber_T)(iptr->isn_arg.number));
51394c137214SBram Moolenaar 		}
51404c137214SBram Moolenaar 		break;
51414c137214SBram Moolenaar 	    case ISN_LOADOUTER:
51424c137214SBram Moolenaar 		{
51434c137214SBram Moolenaar 		    if (iptr->isn_arg.number < 0)
51444c137214SBram Moolenaar 			smsg("%s%4d LOADOUTER level %d arg[%d]", pfx, current,
51454c137214SBram Moolenaar 				iptr->isn_arg.outer.outer_depth,
51464c137214SBram Moolenaar 				iptr->isn_arg.outer.outer_idx
51474c137214SBram Moolenaar 							  + STACK_FRAME_SIZE);
51484c137214SBram Moolenaar 		    else
51494c137214SBram Moolenaar 			smsg("%s%4d LOADOUTER level %d $%d", pfx, current,
51504c137214SBram Moolenaar 					      iptr->isn_arg.outer.outer_depth,
51514c137214SBram Moolenaar 					      iptr->isn_arg.outer.outer_idx);
51524c137214SBram Moolenaar 		}
51534c137214SBram Moolenaar 		break;
51544c137214SBram Moolenaar 	    case ISN_LOADV:
51554c137214SBram Moolenaar 		smsg("%s%4d LOADV v:%s", pfx, current,
51564c137214SBram Moolenaar 				       get_vim_var_name(iptr->isn_arg.number));
51574c137214SBram Moolenaar 		break;
51584c137214SBram Moolenaar 	    case ISN_LOADSCRIPT:
51594c137214SBram Moolenaar 		{
51604c137214SBram Moolenaar 		    scriptref_T	    *sref = iptr->isn_arg.script.scriptref;
51614c137214SBram Moolenaar 		    scriptitem_T    *si = SCRIPT_ITEM(sref->sref_sid);
51626db660beSBram Moolenaar 		    svar_T	    *sv;
51634c137214SBram Moolenaar 
51646db660beSBram Moolenaar 		    sv = get_script_svar(sref, -1);
51656db660beSBram Moolenaar 		    if (sv == NULL)
51666db660beSBram Moolenaar 			smsg("%s%4d LOADSCRIPT [deleted] from %s",
51676db660beSBram Moolenaar 						    pfx, current, si->sn_name);
51686db660beSBram Moolenaar 		    else
51694c137214SBram Moolenaar 			smsg("%s%4d LOADSCRIPT %s-%d from %s", pfx, current,
51704c137214SBram Moolenaar 					    sv->sv_name,
51714c137214SBram Moolenaar 					    sref->sref_idx,
51724c137214SBram Moolenaar 					    si->sn_name);
51734c137214SBram Moolenaar 		}
51744c137214SBram Moolenaar 		break;
51754c137214SBram Moolenaar 	    case ISN_LOADS:
51764c137214SBram Moolenaar 		{
51774c137214SBram Moolenaar 		    scriptitem_T *si = SCRIPT_ITEM(
51784c137214SBram Moolenaar 					       iptr->isn_arg.loadstore.ls_sid);
51794c137214SBram Moolenaar 
51804c137214SBram Moolenaar 		    smsg("%s%4d LOADS s:%s from %s", pfx, current,
51814c137214SBram Moolenaar 				 iptr->isn_arg.loadstore.ls_name, si->sn_name);
51824c137214SBram Moolenaar 		}
51834c137214SBram Moolenaar 		break;
51844c137214SBram Moolenaar 	    case ISN_LOADAUTO:
51854c137214SBram Moolenaar 		smsg("%s%4d LOADAUTO %s", pfx, current, iptr->isn_arg.string);
51864c137214SBram Moolenaar 		break;
51874c137214SBram Moolenaar 	    case ISN_LOADG:
51884c137214SBram Moolenaar 		smsg("%s%4d LOADG g:%s", pfx, current, iptr->isn_arg.string);
51894c137214SBram Moolenaar 		break;
51904c137214SBram Moolenaar 	    case ISN_LOADB:
51914c137214SBram Moolenaar 		smsg("%s%4d LOADB b:%s", pfx, current, iptr->isn_arg.string);
51924c137214SBram Moolenaar 		break;
51934c137214SBram Moolenaar 	    case ISN_LOADW:
51944c137214SBram Moolenaar 		smsg("%s%4d LOADW w:%s", pfx, current, iptr->isn_arg.string);
51954c137214SBram Moolenaar 		break;
51964c137214SBram Moolenaar 	    case ISN_LOADT:
51974c137214SBram Moolenaar 		smsg("%s%4d LOADT t:%s", pfx, current, iptr->isn_arg.string);
51984c137214SBram Moolenaar 		break;
51994c137214SBram Moolenaar 	    case ISN_LOADGDICT:
52004c137214SBram Moolenaar 		smsg("%s%4d LOAD g:", pfx, current);
52014c137214SBram Moolenaar 		break;
52024c137214SBram Moolenaar 	    case ISN_LOADBDICT:
52034c137214SBram Moolenaar 		smsg("%s%4d LOAD b:", pfx, current);
52044c137214SBram Moolenaar 		break;
52054c137214SBram Moolenaar 	    case ISN_LOADWDICT:
52064c137214SBram Moolenaar 		smsg("%s%4d LOAD w:", pfx, current);
52074c137214SBram Moolenaar 		break;
52084c137214SBram Moolenaar 	    case ISN_LOADTDICT:
52094c137214SBram Moolenaar 		smsg("%s%4d LOAD t:", pfx, current);
52104c137214SBram Moolenaar 		break;
52114c137214SBram Moolenaar 	    case ISN_LOADOPT:
52124c137214SBram Moolenaar 		smsg("%s%4d LOADOPT %s", pfx, current, iptr->isn_arg.string);
52134c137214SBram Moolenaar 		break;
52144c137214SBram Moolenaar 	    case ISN_LOADENV:
52154c137214SBram Moolenaar 		smsg("%s%4d LOADENV %s", pfx, current, iptr->isn_arg.string);
52164c137214SBram Moolenaar 		break;
52174c137214SBram Moolenaar 	    case ISN_LOADREG:
52186db660beSBram Moolenaar 		smsg("%s%4d LOADREG @%c", pfx, current,
52196db660beSBram Moolenaar 						  (int)(iptr->isn_arg.number));
52204c137214SBram Moolenaar 		break;
52214c137214SBram Moolenaar 
52224c137214SBram Moolenaar 	    case ISN_STORE:
52234c137214SBram Moolenaar 		if (iptr->isn_arg.number < 0)
52244c137214SBram Moolenaar 		    smsg("%s%4d STORE arg[%lld]", pfx, current,
52254c137214SBram Moolenaar 				      iptr->isn_arg.number + STACK_FRAME_SIZE);
52264c137214SBram Moolenaar 		else
52276db660beSBram Moolenaar 		    smsg("%s%4d STORE $%lld", pfx, current,
52286db660beSBram Moolenaar 							 iptr->isn_arg.number);
52294c137214SBram Moolenaar 		break;
52304c137214SBram Moolenaar 	    case ISN_STOREOUTER:
52314c137214SBram Moolenaar 		{
52324c137214SBram Moolenaar 		if (iptr->isn_arg.number < 0)
52334c137214SBram Moolenaar 		    smsg("%s%4d STOREOUTEr level %d arg[%d]", pfx, current,
52344c137214SBram Moolenaar 			    iptr->isn_arg.outer.outer_depth,
52354c137214SBram Moolenaar 			    iptr->isn_arg.outer.outer_idx + STACK_FRAME_SIZE);
52364c137214SBram Moolenaar 		else
52374c137214SBram Moolenaar 		    smsg("%s%4d STOREOUTER level %d $%d", pfx, current,
52384c137214SBram Moolenaar 			    iptr->isn_arg.outer.outer_depth,
52394c137214SBram Moolenaar 			    iptr->isn_arg.outer.outer_idx);
52404c137214SBram Moolenaar 		}
52414c137214SBram Moolenaar 		break;
52424c137214SBram Moolenaar 	    case ISN_STOREV:
52434c137214SBram Moolenaar 		smsg("%s%4d STOREV v:%s", pfx, current,
52444c137214SBram Moolenaar 				       get_vim_var_name(iptr->isn_arg.number));
52454c137214SBram Moolenaar 		break;
52464c137214SBram Moolenaar 	    case ISN_STOREAUTO:
52474c137214SBram Moolenaar 		smsg("%s%4d STOREAUTO %s", pfx, current, iptr->isn_arg.string);
52484c137214SBram Moolenaar 		break;
52494c137214SBram Moolenaar 	    case ISN_STOREG:
52504c137214SBram Moolenaar 		smsg("%s%4d STOREG %s", pfx, current, iptr->isn_arg.string);
52514c137214SBram Moolenaar 		break;
52524c137214SBram Moolenaar 	    case ISN_STOREB:
52534c137214SBram Moolenaar 		smsg("%s%4d STOREB %s", pfx, current, iptr->isn_arg.string);
52544c137214SBram Moolenaar 		break;
52554c137214SBram Moolenaar 	    case ISN_STOREW:
52564c137214SBram Moolenaar 		smsg("%s%4d STOREW %s", pfx, current, iptr->isn_arg.string);
52574c137214SBram Moolenaar 		break;
52584c137214SBram Moolenaar 	    case ISN_STORET:
52594c137214SBram Moolenaar 		smsg("%s%4d STORET %s", pfx, current, iptr->isn_arg.string);
52604c137214SBram Moolenaar 		break;
52614c137214SBram Moolenaar 	    case ISN_STORES:
52624c137214SBram Moolenaar 		{
52634c137214SBram Moolenaar 		    scriptitem_T *si = SCRIPT_ITEM(
52644c137214SBram Moolenaar 					       iptr->isn_arg.loadstore.ls_sid);
52654c137214SBram Moolenaar 
52664c137214SBram Moolenaar 		    smsg("%s%4d STORES %s in %s", pfx, current,
52674c137214SBram Moolenaar 				 iptr->isn_arg.loadstore.ls_name, si->sn_name);
52684c137214SBram Moolenaar 		}
52694c137214SBram Moolenaar 		break;
52704c137214SBram Moolenaar 	    case ISN_STORESCRIPT:
52714c137214SBram Moolenaar 		{
52724c137214SBram Moolenaar 		    scriptref_T	    *sref = iptr->isn_arg.script.scriptref;
52734c137214SBram Moolenaar 		    scriptitem_T    *si = SCRIPT_ITEM(sref->sref_sid);
52746db660beSBram Moolenaar 		    svar_T	    *sv;
52754c137214SBram Moolenaar 
52766db660beSBram Moolenaar 		    sv = get_script_svar(sref, -1);
52776db660beSBram Moolenaar 		    if (sv == NULL)
52786db660beSBram Moolenaar 			smsg("%s%4d STORESCRIPT [deleted] in %s",
52796db660beSBram Moolenaar 						    pfx, current, si->sn_name);
52806db660beSBram Moolenaar 		    else
52814c137214SBram Moolenaar 			smsg("%s%4d STORESCRIPT %s-%d in %s", pfx, current,
52824c137214SBram Moolenaar 					     sv->sv_name,
52834c137214SBram Moolenaar 					     sref->sref_idx,
52844c137214SBram Moolenaar 					     si->sn_name);
52854c137214SBram Moolenaar 		}
52864c137214SBram Moolenaar 		break;
52874c137214SBram Moolenaar 	    case ISN_STOREOPT:
52884c137214SBram Moolenaar 		smsg("%s%4d STOREOPT &%s", pfx, current,
52894c137214SBram Moolenaar 					       iptr->isn_arg.storeopt.so_name);
52904c137214SBram Moolenaar 		break;
52914c137214SBram Moolenaar 	    case ISN_STOREENV:
52924c137214SBram Moolenaar 		smsg("%s%4d STOREENV $%s", pfx, current, iptr->isn_arg.string);
52934c137214SBram Moolenaar 		break;
52944c137214SBram Moolenaar 	    case ISN_STOREREG:
52956db660beSBram Moolenaar 		smsg("%s%4d STOREREG @%c", pfx, current,
52966db660beSBram Moolenaar 						    (int)iptr->isn_arg.number);
52974c137214SBram Moolenaar 		break;
52984c137214SBram Moolenaar 	    case ISN_STORENR:
52994c137214SBram Moolenaar 		smsg("%s%4d STORE %lld in $%d", pfx, current,
53004c137214SBram Moolenaar 				iptr->isn_arg.storenr.stnr_val,
53014c137214SBram Moolenaar 				iptr->isn_arg.storenr.stnr_idx);
53024c137214SBram Moolenaar 		break;
53034c137214SBram Moolenaar 
53044c137214SBram Moolenaar 	    case ISN_STOREINDEX:
53054c137214SBram Moolenaar 		smsg("%s%4d STOREINDEX %s", pfx, current,
53064c137214SBram Moolenaar 					  vartype_name(iptr->isn_arg.vartype));
53074c137214SBram Moolenaar 		break;
53084c137214SBram Moolenaar 
53094c137214SBram Moolenaar 	    case ISN_STORERANGE:
53104c137214SBram Moolenaar 		smsg("%s%4d STORERANGE", pfx, current);
53114c137214SBram Moolenaar 		break;
53124c137214SBram Moolenaar 
53134c137214SBram Moolenaar 	    // constants
53144c137214SBram Moolenaar 	    case ISN_PUSHNR:
53154c137214SBram Moolenaar 		smsg("%s%4d PUSHNR %lld", pfx, current,
53164c137214SBram Moolenaar 					    (varnumber_T)(iptr->isn_arg.number));
53174c137214SBram Moolenaar 		break;
53184c137214SBram Moolenaar 	    case ISN_PUSHBOOL:
53194c137214SBram Moolenaar 	    case ISN_PUSHSPEC:
53204c137214SBram Moolenaar 		smsg("%s%4d PUSH %s", pfx, current,
53214c137214SBram Moolenaar 				   get_var_special_name(iptr->isn_arg.number));
53224c137214SBram Moolenaar 		break;
53234c137214SBram Moolenaar 	    case ISN_PUSHF:
53244c137214SBram Moolenaar #ifdef FEAT_FLOAT
53254c137214SBram Moolenaar 		smsg("%s%4d PUSHF %g", pfx, current, iptr->isn_arg.fnumber);
53264c137214SBram Moolenaar #endif
53274c137214SBram Moolenaar 		break;
53284c137214SBram Moolenaar 	    case ISN_PUSHS:
53294c137214SBram Moolenaar 		smsg("%s%4d PUSHS \"%s\"", pfx, current, iptr->isn_arg.string);
53304c137214SBram Moolenaar 		break;
53314c137214SBram Moolenaar 	    case ISN_PUSHBLOB:
53324c137214SBram Moolenaar 		{
53334c137214SBram Moolenaar 		    char_u	*r;
53344c137214SBram Moolenaar 		    char_u	numbuf[NUMBUFLEN];
53354c137214SBram Moolenaar 		    char_u	*tofree;
53364c137214SBram Moolenaar 
53374c137214SBram Moolenaar 		    r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
53384c137214SBram Moolenaar 		    smsg("%s%4d PUSHBLOB %s", pfx, current, r);
53394c137214SBram Moolenaar 		    vim_free(tofree);
53404c137214SBram Moolenaar 		}
53414c137214SBram Moolenaar 		break;
53424c137214SBram Moolenaar 	    case ISN_PUSHFUNC:
53434c137214SBram Moolenaar 		{
53444c137214SBram Moolenaar 		    char *name = (char *)iptr->isn_arg.string;
53454c137214SBram Moolenaar 
53464c137214SBram Moolenaar 		    smsg("%s%4d PUSHFUNC \"%s\"", pfx, current,
53474c137214SBram Moolenaar 					       name == NULL ? "[none]" : name);
53484c137214SBram Moolenaar 		}
53494c137214SBram Moolenaar 		break;
53504c137214SBram Moolenaar 	    case ISN_PUSHCHANNEL:
53514c137214SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
53524c137214SBram Moolenaar 		{
53534c137214SBram Moolenaar 		    channel_T *channel = iptr->isn_arg.channel;
53544c137214SBram Moolenaar 
53554c137214SBram Moolenaar 		    smsg("%s%4d PUSHCHANNEL %d", pfx, current,
53564c137214SBram Moolenaar 					 channel == NULL ? 0 : channel->ch_id);
53574c137214SBram Moolenaar 		}
53584c137214SBram Moolenaar #endif
53594c137214SBram Moolenaar 		break;
53604c137214SBram Moolenaar 	    case ISN_PUSHJOB:
53614c137214SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
53624c137214SBram Moolenaar 		{
53634c137214SBram Moolenaar 		    typval_T	tv;
53644c137214SBram Moolenaar 		    char_u	*name;
53651328bde9SBram Moolenaar 		    char_u	buf[NUMBUFLEN];
53664c137214SBram Moolenaar 
53674c137214SBram Moolenaar 		    tv.v_type = VAR_JOB;
53684c137214SBram Moolenaar 		    tv.vval.v_job = iptr->isn_arg.job;
53691328bde9SBram Moolenaar 		    name = job_to_string_buf(&tv, buf);
53704c137214SBram Moolenaar 		    smsg("%s%4d PUSHJOB \"%s\"", pfx, current, name);
53714c137214SBram Moolenaar 		}
53724c137214SBram Moolenaar #endif
53734c137214SBram Moolenaar 		break;
53744c137214SBram Moolenaar 	    case ISN_PUSHEXC:
53754c137214SBram Moolenaar 		smsg("%s%4d PUSH v:exception", pfx, current);
53764c137214SBram Moolenaar 		break;
53774c137214SBram Moolenaar 	    case ISN_UNLET:
53784c137214SBram Moolenaar 		smsg("%s%4d UNLET%s %s", pfx, current,
53794c137214SBram Moolenaar 			iptr->isn_arg.unlet.ul_forceit ? "!" : "",
53804c137214SBram Moolenaar 			iptr->isn_arg.unlet.ul_name);
53814c137214SBram Moolenaar 		break;
53824c137214SBram Moolenaar 	    case ISN_UNLETENV:
53834c137214SBram Moolenaar 		smsg("%s%4d UNLETENV%s $%s", pfx, current,
53844c137214SBram Moolenaar 			iptr->isn_arg.unlet.ul_forceit ? "!" : "",
53854c137214SBram Moolenaar 			iptr->isn_arg.unlet.ul_name);
53864c137214SBram Moolenaar 		break;
53874c137214SBram Moolenaar 	    case ISN_UNLETINDEX:
53884c137214SBram Moolenaar 		smsg("%s%4d UNLETINDEX", pfx, current);
53894c137214SBram Moolenaar 		break;
53904c137214SBram Moolenaar 	    case ISN_UNLETRANGE:
53914c137214SBram Moolenaar 		smsg("%s%4d UNLETRANGE", pfx, current);
53924c137214SBram Moolenaar 		break;
5393aacc966cSBram Moolenaar 	    case ISN_LOCKUNLOCK:
5394aacc966cSBram Moolenaar 		smsg("%s%4d LOCKUNLOCK %s", pfx, current, iptr->isn_arg.string);
5395aacc966cSBram Moolenaar 		break;
53964c137214SBram Moolenaar 	    case ISN_LOCKCONST:
53974c137214SBram Moolenaar 		smsg("%s%4d LOCKCONST", pfx, current);
53984c137214SBram Moolenaar 		break;
53994c137214SBram Moolenaar 	    case ISN_NEWLIST:
54004c137214SBram Moolenaar 		smsg("%s%4d NEWLIST size %lld", pfx, current,
54014c137214SBram Moolenaar 					    (varnumber_T)(iptr->isn_arg.number));
54024c137214SBram Moolenaar 		break;
54034c137214SBram Moolenaar 	    case ISN_NEWDICT:
54044c137214SBram Moolenaar 		smsg("%s%4d NEWDICT size %lld", pfx, current,
54054c137214SBram Moolenaar 					    (varnumber_T)(iptr->isn_arg.number));
54064c137214SBram Moolenaar 		break;
54074c137214SBram Moolenaar 
54084c137214SBram Moolenaar 	    // function call
54094c137214SBram Moolenaar 	    case ISN_BCALL:
54104c137214SBram Moolenaar 		{
54114c137214SBram Moolenaar 		    cbfunc_T	*cbfunc = &iptr->isn_arg.bfunc;
54124c137214SBram Moolenaar 
54134c137214SBram Moolenaar 		    smsg("%s%4d BCALL %s(argc %d)", pfx, current,
54144c137214SBram Moolenaar 			    internal_func_name(cbfunc->cbf_idx),
54154c137214SBram Moolenaar 			    cbfunc->cbf_argcount);
54164c137214SBram Moolenaar 		}
54174c137214SBram Moolenaar 		break;
54184c137214SBram Moolenaar 	    case ISN_DCALL:
54194c137214SBram Moolenaar 		{
54204c137214SBram Moolenaar 		    cdfunc_T	*cdfunc = &iptr->isn_arg.dfunc;
54214c137214SBram Moolenaar 		    dfunc_T	*df = ((dfunc_T *)def_functions.ga_data)
54224c137214SBram Moolenaar 							     + cdfunc->cdf_idx;
54234c137214SBram Moolenaar 
54244c137214SBram Moolenaar 		    smsg("%s%4d DCALL %s(argc %d)", pfx, current,
54256db660beSBram Moolenaar 					    printable_func_name(df->df_ufunc),
54266db660beSBram Moolenaar 							 cdfunc->cdf_argcount);
54274c137214SBram Moolenaar 		}
54284c137214SBram Moolenaar 		break;
54294c137214SBram Moolenaar 	    case ISN_UCALL:
54304c137214SBram Moolenaar 		{
54314c137214SBram Moolenaar 		    cufunc_T	*cufunc = &iptr->isn_arg.ufunc;
54324c137214SBram Moolenaar 
54334c137214SBram Moolenaar 		    smsg("%s%4d UCALL %s(argc %d)", pfx, current,
54344c137214SBram Moolenaar 				       cufunc->cuf_name, cufunc->cuf_argcount);
54354c137214SBram Moolenaar 		}
54364c137214SBram Moolenaar 		break;
54374c137214SBram Moolenaar 	    case ISN_PCALL:
54384c137214SBram Moolenaar 		{
54394c137214SBram Moolenaar 		    cpfunc_T	*cpfunc = &iptr->isn_arg.pfunc;
54404c137214SBram Moolenaar 
54414c137214SBram Moolenaar 		    smsg("%s%4d PCALL%s (argc %d)", pfx, current,
54424c137214SBram Moolenaar 			   cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
54434c137214SBram Moolenaar 		}
54444c137214SBram Moolenaar 		break;
54454c137214SBram Moolenaar 	    case ISN_PCALL_END:
54464c137214SBram Moolenaar 		smsg("%s%4d PCALL end", pfx, current);
54474c137214SBram Moolenaar 		break;
54484c137214SBram Moolenaar 	    case ISN_RETURN:
54494c137214SBram Moolenaar 		smsg("%s%4d RETURN", pfx, current);
54504c137214SBram Moolenaar 		break;
5451f57b43c2SBram Moolenaar 	    case ISN_RETURN_VOID:
5452f57b43c2SBram Moolenaar 		smsg("%s%4d RETURN void", pfx, current);
54534c137214SBram Moolenaar 		break;
54544c137214SBram Moolenaar 	    case ISN_FUNCREF:
54554c137214SBram Moolenaar 		{
54564c137214SBram Moolenaar 		    funcref_T	*funcref = &iptr->isn_arg.funcref;
54574c137214SBram Moolenaar 		    dfunc_T	*df = ((dfunc_T *)def_functions.ga_data)
54584c137214SBram Moolenaar 							    + funcref->fr_func;
54594c137214SBram Moolenaar 
54604c137214SBram Moolenaar 		    smsg("%s%4d FUNCREF %s", pfx, current, df->df_ufunc->uf_name);
54614c137214SBram Moolenaar 		}
54624c137214SBram Moolenaar 		break;
54634c137214SBram Moolenaar 
54644c137214SBram Moolenaar 	    case ISN_NEWFUNC:
54654c137214SBram Moolenaar 		{
54664c137214SBram Moolenaar 		    newfunc_T	*newfunc = &iptr->isn_arg.newfunc;
54674c137214SBram Moolenaar 
54684c137214SBram Moolenaar 		    smsg("%s%4d NEWFUNC %s %s", pfx, current,
54694c137214SBram Moolenaar 				       newfunc->nf_lambda, newfunc->nf_global);
54704c137214SBram Moolenaar 		}
54714c137214SBram Moolenaar 		break;
54724c137214SBram Moolenaar 
54734c137214SBram Moolenaar 	    case ISN_DEF:
54744c137214SBram Moolenaar 		{
54754c137214SBram Moolenaar 		    char_u *name = iptr->isn_arg.string;
54764c137214SBram Moolenaar 
54774c137214SBram Moolenaar 		    smsg("%s%4d DEF %s", pfx, current,
54784c137214SBram Moolenaar 					   name == NULL ? (char_u *)"" : name);
54794c137214SBram Moolenaar 		}
54804c137214SBram Moolenaar 		break;
54814c137214SBram Moolenaar 
54824c137214SBram Moolenaar 	    case ISN_JUMP:
54834c137214SBram Moolenaar 		{
54844c137214SBram Moolenaar 		    char *when = "?";
54854c137214SBram Moolenaar 
54864c137214SBram Moolenaar 		    switch (iptr->isn_arg.jump.jump_when)
54874c137214SBram Moolenaar 		    {
54884c137214SBram Moolenaar 			case JUMP_ALWAYS:
54894c137214SBram Moolenaar 			    when = "JUMP";
54904c137214SBram Moolenaar 			    break;
54911a7ee4ddSBram Moolenaar 			case JUMP_NEVER:
54921a7ee4ddSBram Moolenaar 			    iemsg("JUMP_NEVER should not be used");
54931a7ee4ddSBram Moolenaar 			    break;
54944c137214SBram Moolenaar 			case JUMP_AND_KEEP_IF_TRUE:
54954c137214SBram Moolenaar 			    when = "JUMP_AND_KEEP_IF_TRUE";
54964c137214SBram Moolenaar 			    break;
54974c137214SBram Moolenaar 			case JUMP_IF_FALSE:
54984c137214SBram Moolenaar 			    when = "JUMP_IF_FALSE";
54994c137214SBram Moolenaar 			    break;
55004c137214SBram Moolenaar 			case JUMP_AND_KEEP_IF_FALSE:
55014c137214SBram Moolenaar 			    when = "JUMP_AND_KEEP_IF_FALSE";
55024c137214SBram Moolenaar 			    break;
55034c137214SBram Moolenaar 			case JUMP_IF_COND_FALSE:
55044c137214SBram Moolenaar 			    when = "JUMP_IF_COND_FALSE";
55054c137214SBram Moolenaar 			    break;
55064c137214SBram Moolenaar 			case JUMP_IF_COND_TRUE:
55074c137214SBram Moolenaar 			    when = "JUMP_IF_COND_TRUE";
55084c137214SBram Moolenaar 			    break;
55094c137214SBram Moolenaar 		    }
55104c137214SBram Moolenaar 		    smsg("%s%4d %s -> %d", pfx, current, when,
55114c137214SBram Moolenaar 						iptr->isn_arg.jump.jump_where);
55124c137214SBram Moolenaar 		}
55134c137214SBram Moolenaar 		break;
55144c137214SBram Moolenaar 
55154c137214SBram Moolenaar 	    case ISN_JUMP_IF_ARG_SET:
55164c137214SBram Moolenaar 		smsg("%s%4d JUMP_IF_ARG_SET arg[%d] -> %d", pfx, current,
55174c137214SBram Moolenaar 			 iptr->isn_arg.jumparg.jump_arg_off + STACK_FRAME_SIZE,
55184c137214SBram Moolenaar 						iptr->isn_arg.jump.jump_where);
55194c137214SBram Moolenaar 		break;
55204c137214SBram Moolenaar 
55214c137214SBram Moolenaar 	    case ISN_FOR:
55224c137214SBram Moolenaar 		{
55234c137214SBram Moolenaar 		    forloop_T *forloop = &iptr->isn_arg.forloop;
55244c137214SBram Moolenaar 
55254c137214SBram Moolenaar 		    smsg("%s%4d FOR $%d -> %d", pfx, current,
55264c137214SBram Moolenaar 					   forloop->for_idx, forloop->for_end);
55274c137214SBram Moolenaar 		}
55284c137214SBram Moolenaar 		break;
55294c137214SBram Moolenaar 
55304c137214SBram Moolenaar 	    case ISN_TRY:
55314c137214SBram Moolenaar 		{
55324c137214SBram Moolenaar 		    try_T *try = &iptr->isn_arg.try;
55334c137214SBram Moolenaar 
55344c137214SBram Moolenaar 		    if (try->try_ref->try_finally == 0)
55354c137214SBram Moolenaar 			smsg("%s%4d TRY catch -> %d, endtry -> %d",
55364c137214SBram Moolenaar 				pfx, current,
55374c137214SBram Moolenaar 				try->try_ref->try_catch,
55384c137214SBram Moolenaar 				try->try_ref->try_endtry);
55394c137214SBram Moolenaar 		    else
55404c137214SBram Moolenaar 			smsg("%s%4d TRY catch -> %d, finally -> %d, endtry -> %d",
55414c137214SBram Moolenaar 				pfx, current,
55424c137214SBram Moolenaar 				try->try_ref->try_catch,
55434c137214SBram Moolenaar 				try->try_ref->try_finally,
55444c137214SBram Moolenaar 				try->try_ref->try_endtry);
55454c137214SBram Moolenaar 		}
55464c137214SBram Moolenaar 		break;
55474c137214SBram Moolenaar 	    case ISN_CATCH:
55484c137214SBram Moolenaar 		// TODO
55494c137214SBram Moolenaar 		smsg("%s%4d CATCH", pfx, current);
55504c137214SBram Moolenaar 		break;
55514c137214SBram Moolenaar 	    case ISN_TRYCONT:
55524c137214SBram Moolenaar 		{
55534c137214SBram Moolenaar 		    trycont_T *trycont = &iptr->isn_arg.trycont;
55544c137214SBram Moolenaar 
55554c137214SBram Moolenaar 		    smsg("%s%4d TRY-CONTINUE %d level%s -> %d", pfx, current,
55564c137214SBram Moolenaar 				      trycont->tct_levels,
55574c137214SBram Moolenaar 				      trycont->tct_levels == 1 ? "" : "s",
55584c137214SBram Moolenaar 				      trycont->tct_where);
55594c137214SBram Moolenaar 		}
55604c137214SBram Moolenaar 		break;
55614c137214SBram Moolenaar 	    case ISN_FINALLY:
55624c137214SBram Moolenaar 		smsg("%s%4d FINALLY", pfx, current);
55634c137214SBram Moolenaar 		break;
55644c137214SBram Moolenaar 	    case ISN_ENDTRY:
55654c137214SBram Moolenaar 		smsg("%s%4d ENDTRY", pfx, current);
55664c137214SBram Moolenaar 		break;
55674c137214SBram Moolenaar 	    case ISN_THROW:
55684c137214SBram Moolenaar 		smsg("%s%4d THROW", pfx, current);
55694c137214SBram Moolenaar 		break;
55704c137214SBram Moolenaar 
55714c137214SBram Moolenaar 	    // expression operations on number
55724c137214SBram Moolenaar 	    case ISN_OPNR:
55734c137214SBram Moolenaar 	    case ISN_OPFLOAT:
55744c137214SBram Moolenaar 	    case ISN_OPANY:
55754c137214SBram Moolenaar 		{
55764c137214SBram Moolenaar 		    char *what;
55774c137214SBram Moolenaar 		    char *ins;
55784c137214SBram Moolenaar 
55794c137214SBram Moolenaar 		    switch (iptr->isn_arg.op.op_type)
55804c137214SBram Moolenaar 		    {
55814c137214SBram Moolenaar 			case EXPR_MULT: what = "*"; break;
55824c137214SBram Moolenaar 			case EXPR_DIV: what = "/"; break;
55834c137214SBram Moolenaar 			case EXPR_REM: what = "%"; break;
55844c137214SBram Moolenaar 			case EXPR_SUB: what = "-"; break;
55854c137214SBram Moolenaar 			case EXPR_ADD: what = "+"; break;
55864c137214SBram Moolenaar 			default:       what = "???"; break;
55874c137214SBram Moolenaar 		    }
55884c137214SBram Moolenaar 		    switch (iptr->isn_type)
55894c137214SBram Moolenaar 		    {
55904c137214SBram Moolenaar 			case ISN_OPNR: ins = "OPNR"; break;
55914c137214SBram Moolenaar 			case ISN_OPFLOAT: ins = "OPFLOAT"; break;
55924c137214SBram Moolenaar 			case ISN_OPANY: ins = "OPANY"; break;
55934c137214SBram Moolenaar 			default: ins = "???"; break;
55944c137214SBram Moolenaar 		    }
55954c137214SBram Moolenaar 		    smsg("%s%4d %s %s", pfx, current, ins, what);
55964c137214SBram Moolenaar 		}
55974c137214SBram Moolenaar 		break;
55984c137214SBram Moolenaar 
55994c137214SBram Moolenaar 	    case ISN_COMPAREBOOL:
56004c137214SBram Moolenaar 	    case ISN_COMPARESPECIAL:
56014c137214SBram Moolenaar 	    case ISN_COMPARENR:
56024c137214SBram Moolenaar 	    case ISN_COMPAREFLOAT:
56034c137214SBram Moolenaar 	    case ISN_COMPARESTRING:
56044c137214SBram Moolenaar 	    case ISN_COMPAREBLOB:
56054c137214SBram Moolenaar 	    case ISN_COMPARELIST:
56064c137214SBram Moolenaar 	    case ISN_COMPAREDICT:
56074c137214SBram Moolenaar 	    case ISN_COMPAREFUNC:
56084c137214SBram Moolenaar 	    case ISN_COMPAREANY:
56094c137214SBram Moolenaar 		   {
56104c137214SBram Moolenaar 		       char *p;
56114c137214SBram Moolenaar 		       char buf[10];
56124c137214SBram Moolenaar 		       char *type;
56134c137214SBram Moolenaar 
56144c137214SBram Moolenaar 		       switch (iptr->isn_arg.op.op_type)
56154c137214SBram Moolenaar 		       {
56164c137214SBram Moolenaar 			   case EXPR_EQUAL:	 p = "=="; break;
56174c137214SBram Moolenaar 			   case EXPR_NEQUAL:    p = "!="; break;
56184c137214SBram Moolenaar 			   case EXPR_GREATER:   p = ">"; break;
56194c137214SBram Moolenaar 			   case EXPR_GEQUAL:    p = ">="; break;
56204c137214SBram Moolenaar 			   case EXPR_SMALLER:   p = "<"; break;
56214c137214SBram Moolenaar 			   case EXPR_SEQUAL:    p = "<="; break;
56224c137214SBram Moolenaar 			   case EXPR_MATCH:	 p = "=~"; break;
56234c137214SBram Moolenaar 			   case EXPR_IS:	 p = "is"; break;
56244c137214SBram Moolenaar 			   case EXPR_ISNOT:	 p = "isnot"; break;
56254c137214SBram Moolenaar 			   case EXPR_NOMATCH:	 p = "!~"; break;
56264c137214SBram Moolenaar 			   default:  p = "???"; break;
56274c137214SBram Moolenaar 		       }
56284c137214SBram Moolenaar 		       STRCPY(buf, p);
56294c137214SBram Moolenaar 		       if (iptr->isn_arg.op.op_ic == TRUE)
56304c137214SBram Moolenaar 			   strcat(buf, "?");
56314c137214SBram Moolenaar 		       switch(iptr->isn_type)
56324c137214SBram Moolenaar 		       {
56334c137214SBram Moolenaar 			   case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
56344c137214SBram Moolenaar 			   case ISN_COMPARESPECIAL:
56354c137214SBram Moolenaar 						 type = "COMPARESPECIAL"; break;
56364c137214SBram Moolenaar 			   case ISN_COMPARENR: type = "COMPARENR"; break;
56374c137214SBram Moolenaar 			   case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
56384c137214SBram Moolenaar 			   case ISN_COMPARESTRING:
56394c137214SBram Moolenaar 						  type = "COMPARESTRING"; break;
56404c137214SBram Moolenaar 			   case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
56414c137214SBram Moolenaar 			   case ISN_COMPARELIST: type = "COMPARELIST"; break;
56424c137214SBram Moolenaar 			   case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
56434c137214SBram Moolenaar 			   case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
56444c137214SBram Moolenaar 			   case ISN_COMPAREANY: type = "COMPAREANY"; break;
56454c137214SBram Moolenaar 			   default: type = "???"; break;
56464c137214SBram Moolenaar 		       }
56474c137214SBram Moolenaar 
56484c137214SBram Moolenaar 		       smsg("%s%4d %s %s", pfx, current, type, buf);
56494c137214SBram Moolenaar 		   }
56504c137214SBram Moolenaar 		   break;
56514c137214SBram Moolenaar 
56524c137214SBram Moolenaar 	    case ISN_ADDLIST: smsg("%s%4d ADDLIST", pfx, current); break;
56534c137214SBram Moolenaar 	    case ISN_ADDBLOB: smsg("%s%4d ADDBLOB", pfx, current); break;
56544c137214SBram Moolenaar 
56554c137214SBram Moolenaar 	    // expression operations
56564c137214SBram Moolenaar 	    case ISN_CONCAT: smsg("%s%4d CONCAT", pfx, current); break;
56574c137214SBram Moolenaar 	    case ISN_STRINDEX: smsg("%s%4d STRINDEX", pfx, current); break;
56584c137214SBram Moolenaar 	    case ISN_STRSLICE: smsg("%s%4d STRSLICE", pfx, current); break;
56594c137214SBram Moolenaar 	    case ISN_BLOBINDEX: smsg("%s%4d BLOBINDEX", pfx, current); break;
56604c137214SBram Moolenaar 	    case ISN_BLOBSLICE: smsg("%s%4d BLOBSLICE", pfx, current); break;
56614c137214SBram Moolenaar 	    case ISN_LISTAPPEND: smsg("%s%4d LISTAPPEND", pfx, current); break;
56624c137214SBram Moolenaar 	    case ISN_BLOBAPPEND: smsg("%s%4d BLOBAPPEND", pfx, current); break;
56634c137214SBram Moolenaar 	    case ISN_LISTINDEX: smsg("%s%4d LISTINDEX", pfx, current); break;
56644c137214SBram Moolenaar 	    case ISN_LISTSLICE: smsg("%s%4d LISTSLICE", pfx, current); break;
56654c137214SBram Moolenaar 	    case ISN_ANYINDEX: smsg("%s%4d ANYINDEX", pfx, current); break;
56664c137214SBram Moolenaar 	    case ISN_ANYSLICE: smsg("%s%4d ANYSLICE", pfx, current); break;
56674c137214SBram Moolenaar 	    case ISN_SLICE: smsg("%s%4d SLICE %lld",
56684c137214SBram Moolenaar 				    pfx, current, iptr->isn_arg.number); break;
5669035bd1c9SBram Moolenaar 	    case ISN_GETITEM: smsg("%s%4d ITEM %lld%s", pfx, current,
5670035bd1c9SBram Moolenaar 					 iptr->isn_arg.getitem.gi_index,
5671035bd1c9SBram Moolenaar 					 iptr->isn_arg.getitem.gi_with_op ?
5672035bd1c9SBram Moolenaar 						       " with op" : ""); break;
56734c137214SBram Moolenaar 	    case ISN_MEMBER: smsg("%s%4d MEMBER", pfx, current); break;
56744c137214SBram Moolenaar 	    case ISN_STRINGMEMBER: smsg("%s%4d MEMBER %s", pfx, current,
56754c137214SBram Moolenaar 						  iptr->isn_arg.string); break;
5676b1b6f4deSBram Moolenaar 	    case ISN_CLEARDICT: smsg("%s%4d CLEARDICT", pfx, current); break;
5677b1b6f4deSBram Moolenaar 	    case ISN_USEDICT: smsg("%s%4d USEDICT", pfx, current); break;
5678b1b6f4deSBram Moolenaar 
56794c137214SBram Moolenaar 	    case ISN_NEGATENR: smsg("%s%4d NEGATENR", pfx, current); break;
56804c137214SBram Moolenaar 
56814c137214SBram Moolenaar 	    case ISN_CHECKNR: smsg("%s%4d CHECKNR", pfx, current); break;
56824c137214SBram Moolenaar 	    case ISN_CHECKTYPE:
56834c137214SBram Moolenaar 		  {
56844c137214SBram Moolenaar 		      checktype_T *ct = &iptr->isn_arg.type;
56854c137214SBram Moolenaar 		      char *tofree;
56864c137214SBram Moolenaar 
56874c137214SBram Moolenaar 		      if (ct->ct_arg_idx == 0)
56884c137214SBram Moolenaar 			  smsg("%s%4d CHECKTYPE %s stack[%d]", pfx, current,
56894c137214SBram Moolenaar 					  type_name(ct->ct_type, &tofree),
56904c137214SBram Moolenaar 					  (int)ct->ct_off);
56914c137214SBram Moolenaar 		      else
56924f0884d6SBram Moolenaar 			  smsg("%s%4d CHECKTYPE %s stack[%d] arg %d",
56934f0884d6SBram Moolenaar 					  pfx, current,
56944c137214SBram Moolenaar 					  type_name(ct->ct_type, &tofree),
56954c137214SBram Moolenaar 					  (int)ct->ct_off,
56964c137214SBram Moolenaar 					  (int)ct->ct_arg_idx);
56974c137214SBram Moolenaar 		      vim_free(tofree);
56984c137214SBram Moolenaar 		      break;
56994c137214SBram Moolenaar 		  }
57004c137214SBram Moolenaar 	    case ISN_CHECKLEN: smsg("%s%4d CHECKLEN %s%d", pfx, current,
57014c137214SBram Moolenaar 				iptr->isn_arg.checklen.cl_more_OK ? ">= " : "",
57024c137214SBram Moolenaar 				iptr->isn_arg.checklen.cl_min_len);
57034c137214SBram Moolenaar 			       break;
57044c137214SBram Moolenaar 	    case ISN_SETTYPE:
57054c137214SBram Moolenaar 		  {
57064c137214SBram Moolenaar 		      char *tofree;
57074c137214SBram Moolenaar 
57084c137214SBram Moolenaar 		      smsg("%s%4d SETTYPE %s", pfx, current,
57094c137214SBram Moolenaar 			      type_name(iptr->isn_arg.type.ct_type, &tofree));
57104c137214SBram Moolenaar 		      vim_free(tofree);
57114c137214SBram Moolenaar 		      break;
57124c137214SBram Moolenaar 		  }
57134c137214SBram Moolenaar 	    case ISN_COND2BOOL: smsg("%s%4d COND2BOOL", pfx, current); break;
57145fa9b244SBram Moolenaar 	    case ISN_2BOOL: if (iptr->isn_arg.tobool.invert)
57155fa9b244SBram Moolenaar 				smsg("%s%4d INVERT %d (!val)", pfx, current,
57165fa9b244SBram Moolenaar 					 iptr->isn_arg.tobool.offset);
57174c137214SBram Moolenaar 			    else
57185fa9b244SBram Moolenaar 				smsg("%s%4d 2BOOL %d (!!val)", pfx, current,
57195fa9b244SBram Moolenaar 					 iptr->isn_arg.tobool.offset);
57204c137214SBram Moolenaar 			    break;
57214c137214SBram Moolenaar 	    case ISN_2STRING: smsg("%s%4d 2STRING stack[%lld]", pfx, current,
57225fa9b244SBram Moolenaar 				 (varnumber_T)(iptr->isn_arg.tostring.offset));
57234c137214SBram Moolenaar 			      break;
57245fa9b244SBram Moolenaar 	    case ISN_2STRING_ANY: smsg("%s%4d 2STRING_ANY stack[%lld]",
57255fa9b244SBram Moolenaar 								  pfx, current,
57265fa9b244SBram Moolenaar 				 (varnumber_T)(iptr->isn_arg.tostring.offset));
57274c137214SBram Moolenaar 			      break;
57285fa9b244SBram Moolenaar 	    case ISN_RANGE: smsg("%s%4d RANGE %s", pfx, current,
57295fa9b244SBram Moolenaar 							 iptr->isn_arg.string);
57304c137214SBram Moolenaar 			    break;
57314c137214SBram Moolenaar 	    case ISN_PUT:
57324c137214SBram Moolenaar 	        if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE_ABOVE)
57334c137214SBram Moolenaar 		    smsg("%s%4d PUT %c above range",
57344c137214SBram Moolenaar 				  pfx, current, iptr->isn_arg.put.put_regname);
57354c137214SBram Moolenaar 		else if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE)
57364c137214SBram Moolenaar 		    smsg("%s%4d PUT %c range",
57374c137214SBram Moolenaar 				  pfx, current, iptr->isn_arg.put.put_regname);
57384c137214SBram Moolenaar 		else
57394c137214SBram Moolenaar 		    smsg("%s%4d PUT %c %ld", pfx, current,
57404c137214SBram Moolenaar 						 iptr->isn_arg.put.put_regname,
57414c137214SBram Moolenaar 					     (long)iptr->isn_arg.put.put_lnum);
57424c137214SBram Moolenaar 		break;
57434c137214SBram Moolenaar 
57444c137214SBram Moolenaar 		// TODO: summarize modifiers
57454c137214SBram Moolenaar 	    case ISN_CMDMOD:
57464c137214SBram Moolenaar 		{
57474c137214SBram Moolenaar 		    char_u  *buf;
57484c137214SBram Moolenaar 		    size_t  len = produce_cmdmods(
57494c137214SBram Moolenaar 				  NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
57504c137214SBram Moolenaar 
57514c137214SBram Moolenaar 		    buf = alloc(len + 1);
57525a9e5845SDominique Pelle 		    if (likely(buf != NULL))
57534c137214SBram Moolenaar 		    {
57544c137214SBram Moolenaar 			(void)produce_cmdmods(
57554c137214SBram Moolenaar 				   buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
57564c137214SBram Moolenaar 			smsg("%s%4d CMDMOD %s", pfx, current, buf);
57574c137214SBram Moolenaar 			vim_free(buf);
57584c137214SBram Moolenaar 		    }
57594c137214SBram Moolenaar 		    break;
57604c137214SBram Moolenaar 		}
57614c137214SBram Moolenaar 	    case ISN_CMDMOD_REV: smsg("%s%4d CMDMOD_REV", pfx, current); break;
57624c137214SBram Moolenaar 
57634c137214SBram Moolenaar 	    case ISN_PROF_START:
5764e99d422bSBram Moolenaar 		 smsg("%s%4d PROFILE START line %d", pfx, current,
5765e99d422bSBram Moolenaar 							       iptr->isn_lnum);
57664c137214SBram Moolenaar 		 break;
57674c137214SBram Moolenaar 
57684c137214SBram Moolenaar 	    case ISN_PROF_END:
57694c137214SBram Moolenaar 		smsg("%s%4d PROFILE END", pfx, current);
57704c137214SBram Moolenaar 		break;
57714c137214SBram Moolenaar 
5772e99d422bSBram Moolenaar 	    case ISN_DEBUG:
57738cec9273SBram Moolenaar 		smsg("%s%4d DEBUG line %d-%d varcount %lld", pfx, current,
57748cec9273SBram Moolenaar 			iptr->isn_arg.debug.dbg_break_lnum + 1,
57758cec9273SBram Moolenaar 			iptr->isn_lnum,
57768cec9273SBram Moolenaar 			iptr->isn_arg.debug.dbg_var_names_len);
5777e99d422bSBram Moolenaar 		break;
5778e99d422bSBram Moolenaar 
57794c137214SBram Moolenaar 	    case ISN_UNPACK: smsg("%s%4d UNPACK %d%s", pfx, current,
57804c137214SBram Moolenaar 			iptr->isn_arg.unpack.unp_count,
57814c137214SBram Moolenaar 			iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");
57824c137214SBram Moolenaar 			      break;
57834c137214SBram Moolenaar 	    case ISN_SHUFFLE: smsg("%s%4d SHUFFLE %d up %d", pfx, current,
57844c137214SBram Moolenaar 					 iptr->isn_arg.shuffle.shfl_item,
57854c137214SBram Moolenaar 					 iptr->isn_arg.shuffle.shfl_up);
57864c137214SBram Moolenaar 			      break;
57874c137214SBram Moolenaar 	    case ISN_DROP: smsg("%s%4d DROP", pfx, current); break;
57884c137214SBram Moolenaar 
57894c137214SBram Moolenaar 	    case ISN_FINISH: // End of list of instructions for ISN_SUBSTITUTE.
57904c137214SBram Moolenaar 			   return;
57914c137214SBram Moolenaar 	}
57924c137214SBram Moolenaar 
57934c137214SBram Moolenaar 	out_flush();	    // output one line at a time
57944c137214SBram Moolenaar 	ui_breakcheck();
57954c137214SBram Moolenaar 	if (got_int)
57964c137214SBram Moolenaar 	    break;
57974c137214SBram Moolenaar     }
57984c137214SBram Moolenaar }
57994c137214SBram Moolenaar 
58004c137214SBram Moolenaar /*
58014ee9d8e0SBram Moolenaar  * Handle command line completion for the :disassemble command.
58024ee9d8e0SBram Moolenaar  */
58034ee9d8e0SBram Moolenaar     void
set_context_in_disassemble_cmd(expand_T * xp,char_u * arg)58044ee9d8e0SBram Moolenaar set_context_in_disassemble_cmd(expand_T *xp, char_u *arg)
58054ee9d8e0SBram Moolenaar {
58064ee9d8e0SBram Moolenaar     char_u	*p;
58074ee9d8e0SBram Moolenaar 
58084ee9d8e0SBram Moolenaar     // Default: expand user functions, "debug" and "profile"
58094ee9d8e0SBram Moolenaar     xp->xp_context = EXPAND_DISASSEMBLE;
58104ee9d8e0SBram Moolenaar     xp->xp_pattern = arg;
58114ee9d8e0SBram Moolenaar 
58124ee9d8e0SBram Moolenaar     // first argument already typed: only user function names
58134ee9d8e0SBram Moolenaar     if (*arg != NUL && *(p = skiptowhite(arg)) != NUL)
58144ee9d8e0SBram Moolenaar     {
58154ee9d8e0SBram Moolenaar 	xp->xp_context = EXPAND_USER_FUNC;
58164ee9d8e0SBram Moolenaar 	xp->xp_pattern = skipwhite(p);
58174ee9d8e0SBram Moolenaar     }
58184ee9d8e0SBram Moolenaar }
58194ee9d8e0SBram Moolenaar 
58204ee9d8e0SBram Moolenaar /*
58214ee9d8e0SBram Moolenaar  * Function given to ExpandGeneric() to obtain the list of :disassemble
58224ee9d8e0SBram Moolenaar  * arguments.
58234ee9d8e0SBram Moolenaar  */
58244ee9d8e0SBram Moolenaar     char_u *
get_disassemble_argument(expand_T * xp,int idx)58254ee9d8e0SBram Moolenaar get_disassemble_argument(expand_T *xp, int idx)
58264ee9d8e0SBram Moolenaar {
58274ee9d8e0SBram Moolenaar     if (idx == 0)
58284ee9d8e0SBram Moolenaar 	return (char_u *)"debug";
58294ee9d8e0SBram Moolenaar     if (idx == 1)
58304ee9d8e0SBram Moolenaar 	return (char_u *)"profile";
58314ee9d8e0SBram Moolenaar     return get_user_func_name(xp, idx - 2);
58324ee9d8e0SBram Moolenaar }
58334ee9d8e0SBram Moolenaar 
58344ee9d8e0SBram Moolenaar /*
58358e7d6223SBram Moolenaar  * ":disassemble".
5836777770fbSBram Moolenaar  * We don't really need this at runtime, but we do have tests that require it,
5837777770fbSBram Moolenaar  * so always include this.
58388a7d6542SBram Moolenaar  */
58398a7d6542SBram Moolenaar     void
ex_disassemble(exarg_T * eap)58408a7d6542SBram Moolenaar ex_disassemble(exarg_T *eap)
58418a7d6542SBram Moolenaar {
584221456cdcSBram Moolenaar     char_u	*arg = eap->arg;
58430f18b6d1SBram Moolenaar     char_u	*fname;
58440f18b6d1SBram Moolenaar     ufunc_T	*ufunc;
58458a7d6542SBram Moolenaar     dfunc_T	*dfunc;
58468a7d6542SBram Moolenaar     isn_T	*instr;
5847b2049903SBram Moolenaar     int		instr_count;
58484c17ad94SBram Moolenaar     int		is_global = FALSE;
5849e99d422bSBram Moolenaar     compiletype_T compile_type = CT_NONE;
5850e99d422bSBram Moolenaar 
5851e99d422bSBram Moolenaar     if (STRNCMP(arg, "profile", 7) == 0)
5852e99d422bSBram Moolenaar     {
5853e99d422bSBram Moolenaar 	compile_type = CT_PROFILE;
5854e99d422bSBram Moolenaar 	arg = skipwhite(arg + 7);
5855e99d422bSBram Moolenaar     }
5856e99d422bSBram Moolenaar     else if (STRNCMP(arg, "debug", 5) == 0)
5857e99d422bSBram Moolenaar     {
5858e99d422bSBram Moolenaar 	compile_type = CT_DEBUG;
5859e99d422bSBram Moolenaar 	arg = skipwhite(arg + 5);
5860e99d422bSBram Moolenaar     }
58618a7d6542SBram Moolenaar 
5862bfd65589SBram Moolenaar     if (STRNCMP(arg, "<lambda>", 8) == 0)
5863bfd65589SBram Moolenaar     {
5864bfd65589SBram Moolenaar 	arg += 8;
5865bfd65589SBram Moolenaar 	(void)getdigits(&arg);
5866bfd65589SBram Moolenaar 	fname = vim_strnsave(eap->arg, arg - eap->arg);
5867bfd65589SBram Moolenaar     }
5868bfd65589SBram Moolenaar     else
58694c17ad94SBram Moolenaar 	fname = trans_function_name(&arg, &is_global, FALSE,
587032b3f820SBram Moolenaar 		      TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL);
587121456cdcSBram Moolenaar     if (fname == NULL)
587221456cdcSBram Moolenaar     {
587321456cdcSBram Moolenaar 	semsg(_(e_invarg2), eap->arg);
587421456cdcSBram Moolenaar 	return;
587521456cdcSBram Moolenaar     }
587621456cdcSBram Moolenaar 
58774c17ad94SBram Moolenaar     ufunc = find_func(fname, is_global, NULL);
5878a26b9700SBram Moolenaar     if (ufunc == NULL)
5879a26b9700SBram Moolenaar     {
5880a26b9700SBram Moolenaar 	char_u *p = untrans_function_name(fname);
5881a26b9700SBram Moolenaar 
5882a26b9700SBram Moolenaar 	if (p != NULL)
5883a26b9700SBram Moolenaar 	    // Try again without making it script-local.
58844c17ad94SBram Moolenaar 	    ufunc = find_func(p, FALSE, NULL);
5885a26b9700SBram Moolenaar     }
58860f18b6d1SBram Moolenaar     vim_free(fname);
58878a7d6542SBram Moolenaar     if (ufunc == NULL)
58888a7d6542SBram Moolenaar     {
5889451c2e35SBram Moolenaar 	semsg(_(e_cannot_find_function_str), eap->arg);
58908a7d6542SBram Moolenaar 	return;
58918a7d6542SBram Moolenaar     }
5892e99d422bSBram Moolenaar     if (func_needs_compiling(ufunc, compile_type)
5893e99d422bSBram Moolenaar 	    && compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
5894822ba247SBram Moolenaar 	return;
58950cb5bcf5SBram Moolenaar     if (ufunc->uf_def_status != UF_COMPILED)
58968a7d6542SBram Moolenaar     {
5897451c2e35SBram Moolenaar 	semsg(_(e_function_is_not_compiled_str), eap->arg);
58988a7d6542SBram Moolenaar 	return;
58998a7d6542SBram Moolenaar     }
59006db660beSBram Moolenaar     msg((char *)printable_func_name(ufunc));
59018a7d6542SBram Moolenaar 
59028a7d6542SBram Moolenaar     dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5903e99d422bSBram Moolenaar     switch (compile_type)
5904e99d422bSBram Moolenaar     {
5905e99d422bSBram Moolenaar 	case CT_PROFILE:
5906f002a41dSBram Moolenaar #ifdef FEAT_PROFILE
5907e99d422bSBram Moolenaar 	    instr = dfunc->df_instr_prof;
5908e99d422bSBram Moolenaar 	    instr_count = dfunc->df_instr_prof_count;
5909e99d422bSBram Moolenaar 	    break;
5910e99d422bSBram Moolenaar #endif
5911e99d422bSBram Moolenaar 	    // FALLTHROUGH
5912e99d422bSBram Moolenaar 	case CT_NONE:
5913f002a41dSBram Moolenaar 	    instr = dfunc->df_instr;
5914f002a41dSBram Moolenaar 	    instr_count = dfunc->df_instr_count;
5915e99d422bSBram Moolenaar 	    break;
5916e99d422bSBram Moolenaar 	case CT_DEBUG:
5917e99d422bSBram Moolenaar 	    instr = dfunc->df_instr_debug;
5918e99d422bSBram Moolenaar 	    instr_count = dfunc->df_instr_debug_count;
5919e99d422bSBram Moolenaar 	    break;
5920e99d422bSBram Moolenaar     }
59218a7d6542SBram Moolenaar 
59224c137214SBram Moolenaar     list_instructions("", instr, instr_count, ufunc);
59238a7d6542SBram Moolenaar }
59248a7d6542SBram Moolenaar 
59258a7d6542SBram Moolenaar /*
592613106605SBram Moolenaar  * Return TRUE when "tv" is not falsy: non-zero, non-empty string, non-empty
59278a7d6542SBram Moolenaar  * list, etc.  Mostly like what JavaScript does, except that empty list and
59288a7d6542SBram Moolenaar  * empty dictionary are FALSE.
59298a7d6542SBram Moolenaar  */
59308a7d6542SBram Moolenaar     int
tv2bool(typval_T * tv)59318a7d6542SBram Moolenaar tv2bool(typval_T *tv)
59328a7d6542SBram Moolenaar {
59338a7d6542SBram Moolenaar     switch (tv->v_type)
59348a7d6542SBram Moolenaar     {
59358a7d6542SBram Moolenaar 	case VAR_NUMBER:
59368a7d6542SBram Moolenaar 	    return tv->vval.v_number != 0;
59378a7d6542SBram Moolenaar 	case VAR_FLOAT:
59388a7d6542SBram Moolenaar #ifdef FEAT_FLOAT
59398a7d6542SBram Moolenaar 	    return tv->vval.v_float != 0.0;
59408a7d6542SBram Moolenaar #else
59418a7d6542SBram Moolenaar 	    break;
59428a7d6542SBram Moolenaar #endif
59438a7d6542SBram Moolenaar 	case VAR_PARTIAL:
59448a7d6542SBram Moolenaar 	    return tv->vval.v_partial != NULL;
59458a7d6542SBram Moolenaar 	case VAR_FUNC:
59468a7d6542SBram Moolenaar 	case VAR_STRING:
59478a7d6542SBram Moolenaar 	    return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
59488a7d6542SBram Moolenaar 	case VAR_LIST:
59498a7d6542SBram Moolenaar 	    return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
59508a7d6542SBram Moolenaar 	case VAR_DICT:
59518a7d6542SBram Moolenaar 	    return tv->vval.v_dict != NULL
59528a7d6542SBram Moolenaar 				    && tv->vval.v_dict->dv_hashtab.ht_used > 0;
59538a7d6542SBram Moolenaar 	case VAR_BOOL:
59548a7d6542SBram Moolenaar 	case VAR_SPECIAL:
59558a7d6542SBram Moolenaar 	    return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
59568a7d6542SBram Moolenaar 	case VAR_JOB:
59578a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
59588a7d6542SBram Moolenaar 	    return tv->vval.v_job != NULL;
59598a7d6542SBram Moolenaar #else
59608a7d6542SBram Moolenaar 	    break;
59618a7d6542SBram Moolenaar #endif
59628a7d6542SBram Moolenaar 	case VAR_CHANNEL:
59638a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
59648a7d6542SBram Moolenaar 	    return tv->vval.v_channel != NULL;
59658a7d6542SBram Moolenaar #else
59668a7d6542SBram Moolenaar 	    break;
59678a7d6542SBram Moolenaar #endif
59688a7d6542SBram Moolenaar 	case VAR_BLOB:
59698a7d6542SBram Moolenaar 	    return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
59708a7d6542SBram Moolenaar 	case VAR_UNKNOWN:
59714c683750SBram Moolenaar 	case VAR_ANY:
59728a7d6542SBram Moolenaar 	case VAR_VOID:
5973f18332fbSBram Moolenaar 	case VAR_INSTR:
59748a7d6542SBram Moolenaar 	    break;
59758a7d6542SBram Moolenaar     }
59768a7d6542SBram Moolenaar     return FALSE;
59778a7d6542SBram Moolenaar }
59788a7d6542SBram Moolenaar 
5979ea2d407fSBram Moolenaar     void
emsg_using_string_as(typval_T * tv,int as_number)5980ea2d407fSBram Moolenaar emsg_using_string_as(typval_T *tv, int as_number)
5981ea2d407fSBram Moolenaar {
5982ea2d407fSBram Moolenaar     semsg(_(as_number ? e_using_string_as_number_str
5983ea2d407fSBram Moolenaar 						 : e_using_string_as_bool_str),
5984ea2d407fSBram Moolenaar 		       tv->vval.v_string == NULL
5985ea2d407fSBram Moolenaar 					   ? (char_u *)"" : tv->vval.v_string);
5986ea2d407fSBram Moolenaar }
5987ea2d407fSBram Moolenaar 
59888a7d6542SBram Moolenaar /*
59898a7d6542SBram Moolenaar  * If "tv" is a string give an error and return FAIL.
59908a7d6542SBram Moolenaar  */
59918a7d6542SBram Moolenaar     int
check_not_string(typval_T * tv)59928a7d6542SBram Moolenaar check_not_string(typval_T *tv)
59938a7d6542SBram Moolenaar {
59948a7d6542SBram Moolenaar     if (tv->v_type == VAR_STRING)
59958a7d6542SBram Moolenaar     {
5996ea2d407fSBram Moolenaar 	emsg_using_string_as(tv, TRUE);
59978a7d6542SBram Moolenaar 	clear_tv(tv);
59988a7d6542SBram Moolenaar 	return FAIL;
59998a7d6542SBram Moolenaar     }
60008a7d6542SBram Moolenaar     return OK;
60018a7d6542SBram Moolenaar }
60028a7d6542SBram Moolenaar 
60038a7d6542SBram Moolenaar 
60048a7d6542SBram Moolenaar #endif // FEAT_EVAL
6005