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