blob: f944fd7093fbd8a134189191c87df30ccb97551b [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9execute.c: execute Vim9 script instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#include "vim9.h"
24
Dominique Pelle5a9e5842021-07-24 19:32:12 +020025#if defined(__GNUC__) || defined(__clang__)
26# define likely(x) __builtin_expect((x), 1)
27# define unlikely(x) __builtin_expect((x), 0)
28#else
29# define unlikely(x) (x)
30# define likely(x) (x)
31#endif
32
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010033// Structure put on ec_trystack when ISN_TRY is encountered.
34typedef struct {
Bram Moolenaard9d77892021-02-12 21:32:47 +010035 int tcd_frame_idx; // ec_frame_idx at ISN_TRY
36 int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY
Bram Moolenaard3d8fee2021-06-30 19:54:43 +020037 int tcd_in_catch; // in catch or finally block
38 int tcd_did_throw; // set did_throw in :endtry
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +010039 int tcd_catch_idx; // instruction of the first :catch or :finally
40 int tcd_finally_idx; // instruction of the :finally block or zero
41 int tcd_endtry_idx; // instruction of the :endtry
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010042 int tcd_caught; // catch block entered
Bram Moolenaar2e34c342021-03-14 12:13:33 +010043 int tcd_cont; // :continue encountered, jump here (minus one)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010044 int tcd_return; // when TRUE return from end of :finally
45} trycmd_T;
46
Bram Moolenaar4c137212021-04-19 16:48:48 +020047// Data local to a function.
48// On a function call, if not empty, is saved on the stack and restored when
49// returning.
50typedef struct {
51 int floc_restore_cmdmod;
52 cmdmod_T floc_save_cmdmod;
53 int floc_restore_cmdmod_stacklen;
54} funclocal_T;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010055
Bram Moolenaarc04f2a42021-06-09 19:30:03 +020056// Structure to hold a reference to an outer_T, with information of whether it
57// was allocated.
58typedef struct {
59 outer_T *or_outer;
60 partial_T *or_partial; // decrement "or_partial->pt_refcount" later
61 int or_outer_allocated; // free "or_outer" later
62} outer_ref_T;
63
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010064// A stack is used to store:
65// - arguments passed to a :def function
66// - info about the calling function, to use when returning
67// - local variables
68// - temporary values
69//
70// In detail (FP == Frame Pointer):
71// arg1 first argument from caller (if present)
72// arg2 second argument from caller (if present)
73// extra_arg1 any missing optional argument default value
74// FP -> cur_func calling function
75// current previous instruction pointer
76// frame_ptr previous Frame Pointer
77// var1 space for local variable
78// var2 space for local variable
79// .... fixed space for max. number of local variables
80// temp temporary values
81// .... flexible space for temporary values (can grow big)
82
83/*
84 * Execution context.
85 */
Bram Moolenaarcd45ed02020-12-22 17:35:54 +010086struct ectx_S {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010087 garray_T ec_stack; // stack of typval_T values
Bram Moolenaarbf67ea12020-05-02 17:52:42 +020088 int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx
Bram Moolenaar4c137212021-04-19 16:48:48 +020089 int ec_initial_frame_idx; // frame index when called
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010090
Bram Moolenaarc04f2a42021-06-09 19:30:03 +020091 outer_ref_T *ec_outer_ref; // outer scope used for closures, allocated
Bram Moolenaar4c137212021-04-19 16:48:48 +020092 funclocal_T ec_funclocal;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +020093
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010094 garray_T ec_trystack; // stack of trycmd_T values
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010095
96 int ec_dfunc_idx; // current function index
97 isn_T *ec_instr; // array with instructions
98 int ec_iidx; // index in ec_instr: instruction to execute
Bram Moolenaar148ce7a2020-09-23 21:57:23 +020099
100 garray_T ec_funcrefs; // partials that might be a closure
Bram Moolenaar4c137212021-04-19 16:48:48 +0200101
102 int ec_did_emsg_before;
103 int ec_trylevel_at_start;
104 where_T ec_where;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100105};
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100106
Bram Moolenaar12d26532021-02-19 19:13:21 +0100107#ifdef FEAT_PROFILE
108// stack of profinfo_T used when profiling.
109static garray_T profile_info_ga = {0, 0, sizeof(profinfo_T), 20, NULL};
110#endif
111
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100112// Get pointer to item relative to the bottom of the stack, -1 is the last one.
Bram Moolenaar11107ba2020-08-15 21:10:16 +0200113#define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100114
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200115 void
116to_string_error(vartype_T vartype)
117{
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200118 semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype));
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200119}
120
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100121/*
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100122 * Return the number of arguments, including optional arguments and any vararg.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100123 */
124 static int
125ufunc_argcount(ufunc_T *ufunc)
126{
127 return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0);
128}
129
130/*
Bram Moolenaarfe270812020-04-11 22:31:27 +0200131 * Create a new list from "count" items at the bottom of the stack.
132 * When "count" is zero an empty list is added to the stack.
133 */
134 static int
135exe_newlist(int count, ectx_T *ectx)
136{
137 list_T *list = list_alloc_with_items(count);
138 int idx;
139 typval_T *tv;
140
141 if (list == NULL)
142 return FAIL;
143 for (idx = 0; idx < count; ++idx)
144 list_set_item(list, idx, STACK_TV_BOT(idx - count));
145
146 if (count > 0)
147 ectx->ec_stack.ga_len -= count - 1;
Dominique Pelle5a9e5842021-07-24 19:32:12 +0200148 else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarfe270812020-04-11 22:31:27 +0200149 return FAIL;
150 else
151 ++ectx->ec_stack.ga_len;
152 tv = STACK_TV_BOT(-1);
153 tv->v_type = VAR_LIST;
154 tv->vval.v_list = list;
155 ++list->lv_refcount;
156 return OK;
157}
158
159/*
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200160 * If debug_tick changed check if "ufunc" has a breakpoint and update
161 * "uf_has_breakpoint".
162 */
163 static void
164update_has_breakpoint(ufunc_T *ufunc)
165{
166 if (ufunc->uf_debug_tick != debug_tick)
167 {
168 linenr_T breakpoint;
169
170 ufunc->uf_debug_tick = debug_tick;
171 breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name, 0);
172 ufunc->uf_has_breakpoint = breakpoint > 0;
173 }
174}
175
176/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100177 * Call compiled function "cdf_idx" from compiled code.
Bram Moolenaarab360522021-01-10 14:02:28 +0100178 * This adds a stack frame and sets the instruction pointer to the start of the
179 * called function.
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200180 * If "pt" is not null use "pt->pt_outer" for ec_outer_ref->or_outer.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100181 *
182 * Stack has:
183 * - current arguments (already there)
184 * - omitted optional argument (default values) added here
185 * - stack frame:
186 * - pointer to calling function
187 * - Index of next instruction in calling function
188 * - previous frame pointer
189 * - reserved space for local variables
190 */
191 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100192call_dfunc(
193 int cdf_idx,
194 partial_T *pt,
195 int argcount_arg,
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100196 ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100197{
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100198 int argcount = argcount_arg;
199 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
200 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200201 int did_emsg_before = did_emsg_cumul + did_emsg;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100202 int arg_to_add;
203 int vararg_count = 0;
204 int varcount;
205 int idx;
206 estack_T *entry;
207 funclocal_T *floc = NULL;
Bram Moolenaar648594e2021-07-11 17:55:01 +0200208 int res = OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100209
210 if (dfunc->df_deleted)
211 {
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100212 // don't use ufunc->uf_name, it may have been freed
213 emsg_funcname(e_func_deleted,
214 dfunc->df_name == NULL ? (char_u *)"unknown" : dfunc->df_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100215 return FAIL;
216 }
217
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100218#ifdef FEAT_PROFILE
Bram Moolenaar12d26532021-02-19 19:13:21 +0100219 if (do_profiling == PROF_YES)
220 {
Dominique Pelle5a9e5842021-07-24 19:32:12 +0200221 if (likely(ga_grow(&profile_info_ga, 1) == OK))
Bram Moolenaar12d26532021-02-19 19:13:21 +0100222 {
223 profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data)
224 + profile_info_ga.ga_len;
225 ++profile_info_ga.ga_len;
226 CLEAR_POINTER(info);
227 profile_may_start_func(info, ufunc,
228 (((dfunc_T *)def_functions.ga_data)
229 + ectx->ec_dfunc_idx)->df_ufunc);
230 }
Bram Moolenaar12d26532021-02-19 19:13:21 +0100231 }
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100232#endif
233
Bram Moolenaar2ac4b252021-06-20 20:09:42 +0200234 // Update uf_has_breakpoint if needed.
235 update_has_breakpoint(ufunc);
236
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200237 // When debugging and using "cont" switches to the not-debugged
238 // instructions, may need to still compile them.
Bram Moolenaar648594e2021-07-11 17:55:01 +0200239 if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc)))
240 {
241 res = compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL);
242
243 // compile_def_function() may cause def_functions.ga_data to change
244 dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
245 }
246 if (res == FAIL || INSTRUCTIONS(dfunc) == NULL)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200247 {
248 if (did_emsg_cumul + did_emsg == did_emsg_before)
249 semsg(_(e_function_is_not_compiled_str),
250 printable_func_name(ufunc));
251 return FAIL;
252 }
253
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200254 if (ufunc->uf_va_name != NULL)
255 {
Bram Moolenaarfe270812020-04-11 22:31:27 +0200256 // Need to make a list out of the vararg arguments.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200257 // Stack at time of call with 2 varargs:
258 // normal_arg
259 // optional_arg
260 // vararg_1
261 // vararg_2
Bram Moolenaarfe270812020-04-11 22:31:27 +0200262 // After creating the list:
263 // normal_arg
264 // optional_arg
265 // vararg-list
266 // With missing optional arguments we get:
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200267 // normal_arg
Bram Moolenaarfe270812020-04-11 22:31:27 +0200268 // After creating the list
269 // normal_arg
270 // (space for optional_arg)
271 // vararg-list
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200272 vararg_count = argcount - ufunc->uf_args.ga_len;
273 if (vararg_count < 0)
274 vararg_count = 0;
275 else
276 argcount -= vararg_count;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200277 if (exe_newlist(vararg_count, ectx) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200278 return FAIL;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200279
280 vararg_count = 1;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200281 }
282
Bram Moolenaarfe270812020-04-11 22:31:27 +0200283 arg_to_add = ufunc->uf_args.ga_len - argcount;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200284 if (arg_to_add < 0)
285 {
Bram Moolenaar79e8db92020-08-14 22:16:33 +0200286 if (arg_to_add == -1)
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200287 emsg(_(e_one_argument_too_many));
Bram Moolenaar79e8db92020-08-14 22:16:33 +0200288 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200289 semsg(_(e_nr_arguments_too_many), -arg_to_add);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200290 return FAIL;
291 }
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200292
293 // Reserve space for:
294 // - missing arguments
295 // - stack frame
296 // - local variables
297 // - if needed: a counter for number of closures created in
298 // ectx->ec_funcrefs.
299 varcount = dfunc->df_varcount + dfunc->df_has_closure;
Dominique Pelle5a9e5842021-07-24 19:32:12 +0200300 if (unlikely(ga_grow(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE
301 + varcount) == FAIL))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100302 return FAIL;
303
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100304 // If depth of calling is getting too high, don't execute the function.
305 if (funcdepth_increment() == FAIL)
306 return FAIL;
Bram Moolenaare99d4222021-06-13 14:01:26 +0200307 ++ex_nesting_level;
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100308
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100309 // Only make a copy of funclocal if it contains something to restore.
Bram Moolenaar4c137212021-04-19 16:48:48 +0200310 if (ectx->ec_funclocal.floc_restore_cmdmod)
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100311 {
312 floc = ALLOC_ONE(funclocal_T);
313 if (floc == NULL)
314 return FAIL;
Bram Moolenaar4c137212021-04-19 16:48:48 +0200315 *floc = ectx->ec_funclocal;
316 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100317 }
318
Bram Moolenaarfe270812020-04-11 22:31:27 +0200319 // Move the vararg-list to below the missing optional arguments.
320 if (vararg_count > 0 && arg_to_add > 0)
321 *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100322
323 // Reserve space for omitted optional arguments, filled in soon.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200324 for (idx = 0; idx < arg_to_add; ++idx)
Bram Moolenaarfe270812020-04-11 22:31:27 +0200325 STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200326 ectx->ec_stack.ga_len += arg_to_add;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100327
328 // Store current execution state in stack frame for ISN_RETURN.
Bram Moolenaar0186e582021-01-10 18:33:11 +0100329 STACK_TV_BOT(STACK_FRAME_FUNC_OFF)->vval.v_number = ectx->ec_dfunc_idx;
330 STACK_TV_BOT(STACK_FRAME_IIDX_OFF)->vval.v_number = ectx->ec_iidx;
Bram Moolenaar5930ddc2021-04-26 20:32:59 +0200331 STACK_TV_BOT(STACK_FRAME_INSTR_OFF)->vval.v_string = (void *)ectx->ec_instr;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200332 STACK_TV_BOT(STACK_FRAME_OUTER_OFF)->vval.v_string =
333 (void *)ectx->ec_outer_ref;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100334 STACK_TV_BOT(STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string = (void *)floc;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100335 STACK_TV_BOT(STACK_FRAME_IDX_OFF)->vval.v_number = ectx->ec_frame_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200336 ectx->ec_frame_idx = ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100337
338 // Initialize local variables
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200339 for (idx = 0; idx < dfunc->df_varcount; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100340 STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200341 if (dfunc->df_has_closure)
342 {
343 typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + dfunc->df_varcount);
344
345 tv->v_type = VAR_NUMBER;
346 tv->vval.v_number = 0;
347 }
348 ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100349
Bram Moolenaar0d3de8c2021-01-22 20:46:27 +0100350 if (pt != NULL || ufunc->uf_partial != NULL
351 || (ufunc->uf_flags & FC_CLOSURE))
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100352 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200353 outer_ref_T *ref = ALLOC_CLEAR_ONE(outer_ref_T);
Bram Moolenaar0186e582021-01-10 18:33:11 +0100354
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200355 if (ref == NULL)
Bram Moolenaar0186e582021-01-10 18:33:11 +0100356 return FAIL;
357 if (pt != NULL)
358 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200359 ref->or_outer = &pt->pt_outer;
360 ++pt->pt_refcount;
361 ref->or_partial = pt;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100362 }
363 else if (ufunc->uf_partial != NULL)
364 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200365 ref->or_outer = &ufunc->uf_partial->pt_outer;
366 ++ufunc->uf_partial->pt_refcount;
367 ref->or_partial = ufunc->uf_partial;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100368 }
369 else
370 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200371 ref->or_outer = ALLOC_CLEAR_ONE(outer_T);
Dominique Pelle5a9e5842021-07-24 19:32:12 +0200372 if (unlikely(ref->or_outer == NULL))
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200373 {
374 vim_free(ref);
375 return FAIL;
376 }
377 ref->or_outer_allocated = TRUE;
378 ref->or_outer->out_stack = &ectx->ec_stack;
379 ref->or_outer->out_frame_idx = ectx->ec_frame_idx;
380 if (ectx->ec_outer_ref != NULL)
381 ref->or_outer->out_up = ectx->ec_outer_ref->or_outer;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100382 }
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200383 ectx->ec_outer_ref = ref;
Bram Moolenaarab360522021-01-10 14:02:28 +0100384 }
Bram Moolenaar0186e582021-01-10 18:33:11 +0100385 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200386 ectx->ec_outer_ref = NULL;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100387
Bram Moolenaarc970e422021-03-17 15:03:04 +0100388 ++ufunc->uf_calls;
389
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100390 // Set execution state to the start of the called function.
391 ectx->ec_dfunc_idx = cdf_idx;
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100392 ectx->ec_instr = INSTRUCTIONS(dfunc);
Bram Moolenaarb2049902021-01-24 12:53:53 +0100393 entry = estack_push_ufunc(ufunc, 1);
Bram Moolenaarc620c052020-07-08 15:16:19 +0200394 if (entry != NULL)
395 {
396 // Set the script context to the script where the function was defined.
Bram Moolenaarc70fe462021-04-17 17:59:19 +0200397 // Save the current context so it can be restored on return.
398 entry->es_save_sctx = current_sctx;
399 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaarc620c052020-07-08 15:16:19 +0200400 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100401
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200402 // Start execution at the first instruction.
403 ectx->ec_iidx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100404
405 return OK;
406}
407
408// Get pointer to item in the stack.
409#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
410
411/*
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200412 * Used when returning from a function: Check if any closure is still
413 * referenced. If so then move the arguments and variables to a separate piece
414 * of stack to be used when the closure is called.
415 * When "free_arguments" is TRUE the arguments are to be freed.
416 * Returns FAIL when out of memory.
417 */
418 static int
419handle_closure_in_use(ectx_T *ectx, int free_arguments)
420{
421 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
422 + ectx->ec_dfunc_idx;
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200423 int argcount;
424 int top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200425 int idx;
426 typval_T *tv;
427 int closure_in_use = FALSE;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200428 garray_T *gap = &ectx->ec_funcrefs;
429 varnumber_T closure_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200430
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200431 if (dfunc->df_ufunc == NULL)
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200432 return OK; // function was freed
433 if (dfunc->df_has_closure == 0)
434 return OK; // no closures
435 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + dfunc->df_varcount);
436 closure_count = tv->vval.v_number;
437 if (closure_count == 0)
438 return OK; // no funcrefs created
439
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200440 argcount = ufunc_argcount(dfunc->df_ufunc);
441 top = ectx->ec_frame_idx - argcount;
442
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200443 // Check if any created closure is still in use.
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200444 for (idx = 0; idx < closure_count; ++idx)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200445 {
Bram Moolenaarc70bdab2020-09-26 19:59:38 +0200446 partial_T *pt;
447 int off = gap->ga_len - closure_count + idx;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200448
Bram Moolenaarc70bdab2020-09-26 19:59:38 +0200449 if (off < 0)
450 continue; // count is off or already done
451 pt = ((partial_T **)gap->ga_data)[off];
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200452 if (pt->pt_refcount > 1)
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200453 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200454 int refcount = pt->pt_refcount;
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200455 int i;
456
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200457 // A Reference in a local variables doesn't count, it gets
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200458 // unreferenced on return.
459 for (i = 0; i < dfunc->df_varcount; ++i)
460 {
461 typval_T *stv = STACK_TV(ectx->ec_frame_idx
462 + STACK_FRAME_SIZE + i);
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200463 if (stv->v_type == VAR_PARTIAL && pt == stv->vval.v_partial)
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200464 --refcount;
465 }
466 if (refcount > 1)
467 {
468 closure_in_use = TRUE;
469 break;
470 }
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200471 }
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200472 }
473
474 if (closure_in_use)
475 {
476 funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T);
477 typval_T *stack;
478
479 // A closure is using the arguments and/or local variables.
480 // Move them to the called function.
481 if (funcstack == NULL)
482 return FAIL;
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200483 funcstack->fs_var_offset = argcount + STACK_FRAME_SIZE;
484 funcstack->fs_ga.ga_len = funcstack->fs_var_offset + dfunc->df_varcount;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200485 stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len);
486 funcstack->fs_ga.ga_data = stack;
487 if (stack == NULL)
488 {
489 vim_free(funcstack);
490 return FAIL;
491 }
492
493 // Move or copy the arguments.
494 for (idx = 0; idx < argcount; ++idx)
495 {
496 tv = STACK_TV(top + idx);
497 if (free_arguments)
498 {
499 *(stack + idx) = *tv;
500 tv->v_type = VAR_UNKNOWN;
501 }
502 else
503 copy_tv(tv, stack + idx);
504 }
505 // Move the local variables.
506 for (idx = 0; idx < dfunc->df_varcount; ++idx)
507 {
508 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx);
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200509
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200510 // A partial created for a local function, that is also used as a
511 // local variable, has a reference count for the variable, thus
512 // will never go down to zero. When all these refcounts are one
513 // then the funcstack is unused. We need to count how many we have
514 // so we need when to check.
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200515 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
516 {
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200517 int i;
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200518
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200519 for (i = 0; i < closure_count; ++i)
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200520 if (tv->vval.v_partial == ((partial_T **)gap->ga_data)[
521 gap->ga_len - closure_count + i])
522 ++funcstack->fs_min_refcount;
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200523 }
524
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200525 *(stack + funcstack->fs_var_offset + idx) = *tv;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200526 tv->v_type = VAR_UNKNOWN;
527 }
528
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200529 for (idx = 0; idx < closure_count; ++idx)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200530 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200531 partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len
532 - closure_count + idx];
533 if (pt->pt_refcount > 1)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200534 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200535 ++funcstack->fs_refcount;
536 pt->pt_funcstack = funcstack;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100537 pt->pt_outer.out_stack = &funcstack->fs_ga;
538 pt->pt_outer.out_frame_idx = ectx->ec_frame_idx - top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200539 }
540 }
541 }
542
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200543 for (idx = 0; idx < closure_count; ++idx)
544 partial_unref(((partial_T **)gap->ga_data)[gap->ga_len
545 - closure_count + idx]);
546 gap->ga_len -= closure_count;
547 if (gap->ga_len == 0)
548 ga_clear(gap);
549
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200550 return OK;
551}
552
553/*
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200554 * Called when a partial is freed or its reference count goes down to one. The
555 * funcstack may be the only reference to the partials in the local variables.
556 * Go over all of them, the funcref and can be freed if all partials
557 * referencing the funcstack have a reference count of one.
558 */
559 void
560funcstack_check_refcount(funcstack_T *funcstack)
561{
562 int i;
563 garray_T *gap = &funcstack->fs_ga;
564 int done = 0;
565
566 if (funcstack->fs_refcount > funcstack->fs_min_refcount)
567 return;
568 for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i)
569 {
570 typval_T *tv = ((typval_T *)gap->ga_data) + i;
571
572 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL
573 && tv->vval.v_partial->pt_funcstack == funcstack
574 && tv->vval.v_partial->pt_refcount == 1)
575 ++done;
576 }
577 if (done == funcstack->fs_min_refcount)
578 {
579 typval_T *stack = gap->ga_data;
580
581 // All partials referencing the funcstack have a reference count of
582 // one, thus the funcstack is no longer of use.
583 for (i = 0; i < gap->ga_len; ++i)
584 clear_tv(stack + i);
585 vim_free(stack);
586 vim_free(funcstack);
587 }
588}
589
590/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100591 * Return from the current function.
592 */
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200593 static int
Bram Moolenaar4c137212021-04-19 16:48:48 +0200594func_return(ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100595{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100596 int idx;
Bram Moolenaar34c54eb2020-11-25 19:15:19 +0100597 int ret_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200598 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
599 + ectx->ec_dfunc_idx;
600 int argcount = ufunc_argcount(dfunc->df_ufunc);
601 int top = ectx->ec_frame_idx - argcount;
Bram Moolenaarc620c052020-07-08 15:16:19 +0200602 estack_T *entry;
Bram Moolenaar12d26532021-02-19 19:13:21 +0100603 int prev_dfunc_idx = STACK_TV(ectx->ec_frame_idx
604 + STACK_FRAME_FUNC_OFF)->vval.v_number;
Bram Moolenaarb06b50d2021-04-26 21:39:25 +0200605 funclocal_T *floc;
606#ifdef FEAT_PROFILE
Bram Moolenaar12d26532021-02-19 19:13:21 +0100607 dfunc_T *prev_dfunc = ((dfunc_T *)def_functions.ga_data)
608 + prev_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100609
Bram Moolenaar12d26532021-02-19 19:13:21 +0100610 if (do_profiling == PROF_YES)
611 {
612 ufunc_T *caller = prev_dfunc->df_ufunc;
613
614 if (dfunc->df_ufunc->uf_profiling
615 || (caller != NULL && caller->uf_profiling))
616 {
617 profile_may_end_func(((profinfo_T *)profile_info_ga.ga_data)
618 + profile_info_ga.ga_len - 1, dfunc->df_ufunc, caller);
619 --profile_info_ga.ga_len;
620 }
621 }
622#endif
Bram Moolenaarc970e422021-03-17 15:03:04 +0100623 // TODO: when is it safe to delete the function when it is no longer used?
624 --dfunc->df_ufunc->uf_calls;
625
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100626 // execution context goes one level up
Bram Moolenaarc620c052020-07-08 15:16:19 +0200627 entry = estack_pop();
628 if (entry != NULL)
Bram Moolenaarc70fe462021-04-17 17:59:19 +0200629 current_sctx = entry->es_save_sctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100630
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200631 if (handle_closure_in_use(ectx, TRUE) == FAIL)
632 return FAIL;
633
634 // Clear the arguments.
635 for (idx = top; idx < ectx->ec_frame_idx; ++idx)
636 clear_tv(STACK_TV(idx));
637
638 // Clear local variables and temp values, but not the return value.
639 for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100640 idx < ectx->ec_stack.ga_len - 1; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100641 clear_tv(STACK_TV(idx));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100642
Bram Moolenaar34c54eb2020-11-25 19:15:19 +0100643 // The return value should be on top of the stack. However, when aborting
644 // it may not be there and ec_frame_idx is the top of the stack.
645 ret_idx = ectx->ec_stack.ga_len - 1;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100646 if (ret_idx == ectx->ec_frame_idx + STACK_FRAME_IDX_OFF)
Bram Moolenaar34c54eb2020-11-25 19:15:19 +0100647 ret_idx = 0;
648
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200649 if (ectx->ec_outer_ref != NULL)
650 {
651 if (ectx->ec_outer_ref->or_outer_allocated)
652 vim_free(ectx->ec_outer_ref->or_outer);
653 partial_unref(ectx->ec_outer_ref->or_partial);
654 vim_free(ectx->ec_outer_ref);
655 }
Bram Moolenaar0186e582021-01-10 18:33:11 +0100656
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100657 // Restore the previous frame.
Bram Moolenaar12d26532021-02-19 19:13:21 +0100658 ectx->ec_dfunc_idx = prev_dfunc_idx;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100659 ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx
660 + STACK_FRAME_IIDX_OFF)->vval.v_number;
Bram Moolenaar5930ddc2021-04-26 20:32:59 +0200661 ectx->ec_instr = (void *)STACK_TV(ectx->ec_frame_idx
662 + STACK_FRAME_INSTR_OFF)->vval.v_string;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200663 ectx->ec_outer_ref = (void *)STACK_TV(ectx->ec_frame_idx
Bram Moolenaar0186e582021-01-10 18:33:11 +0100664 + STACK_FRAME_OUTER_OFF)->vval.v_string;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100665 floc = (void *)STACK_TV(ectx->ec_frame_idx
666 + STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string;
Bram Moolenaar5366e1a2020-10-01 13:01:34 +0200667 // restoring ec_frame_idx must be last
Bram Moolenaar0186e582021-01-10 18:33:11 +0100668 ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx
669 + STACK_FRAME_IDX_OFF)->vval.v_number;
Bram Moolenaard386e922021-04-25 14:48:49 +0200670
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100671 if (floc == NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +0200672 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100673 else
674 {
Bram Moolenaar4c137212021-04-19 16:48:48 +0200675 ectx->ec_funclocal = *floc;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100676 vim_free(floc);
677 }
678
Bram Moolenaar34c54eb2020-11-25 19:15:19 +0100679 if (ret_idx > 0)
680 {
681 // Reset the stack to the position before the call, with a spot for the
682 // return value, moved there from above the frame.
683 ectx->ec_stack.ga_len = top + 1;
684 *STACK_TV_BOT(-1) = *STACK_TV(ret_idx);
685 }
686 else
687 // Reset the stack to the position before the call.
688 ectx->ec_stack.ga_len = top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200689
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100690 funcdepth_decrement();
Bram Moolenaare99d4222021-06-13 14:01:26 +0200691 --ex_nesting_level;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200692 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100693}
694
695#undef STACK_TV
696
697/*
698 * Prepare arguments and rettv for calling a builtin or user function.
699 */
700 static int
701call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
702{
703 int idx;
704 typval_T *tv;
705
706 // Move arguments from bottom of the stack to argvars[] and add terminator.
707 for (idx = 0; idx < argcount; ++idx)
708 argvars[idx] = *STACK_TV_BOT(idx - argcount);
709 argvars[argcount].v_type = VAR_UNKNOWN;
710
711 // Result replaces the arguments on the stack.
712 if (argcount > 0)
713 ectx->ec_stack.ga_len -= argcount - 1;
Dominique Pelle5a9e5842021-07-24 19:32:12 +0200714 else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100715 return FAIL;
716 else
717 ++ectx->ec_stack.ga_len;
718
719 // Default return value is zero.
720 tv = STACK_TV_BOT(-1);
721 tv->v_type = VAR_NUMBER;
722 tv->vval.v_number = 0;
723
724 return OK;
725}
726
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200727// Ugly global to avoid passing the execution context around through many
728// layers.
729static ectx_T *current_ectx = NULL;
730
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100731/*
732 * Call a builtin function by index.
733 */
734 static int
735call_bfunc(int func_idx, int argcount, ectx_T *ectx)
736{
737 typval_T argvars[MAX_FUNC_ARGS];
738 int idx;
Bram Moolenaar171fb922020-10-28 16:54:47 +0100739 int did_emsg_before = did_emsg;
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200740 ectx_T *prev_ectx = current_ectx;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +0200741 char *save_func_name = ectx->ec_where.wt_func_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100742
743 if (call_prepare(argcount, argvars, ectx) == FAIL)
744 return FAIL;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +0200745 ectx->ec_where.wt_func_name = internal_func_name(func_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100746
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200747 // Call the builtin function. Set "current_ectx" so that when it
748 // recursively invokes call_def_function() a closure context can be set.
749 current_ectx = ectx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100750 call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1));
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200751 current_ectx = prev_ectx;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +0200752 ectx->ec_where.wt_func_name = save_func_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100753
754 // Clear the arguments.
755 for (idx = 0; idx < argcount; ++idx)
756 clear_tv(&argvars[idx]);
Bram Moolenaar015f4262020-05-05 21:25:22 +0200757
Bram Moolenaar57f799e2020-12-12 20:42:19 +0100758 if (did_emsg > did_emsg_before)
Bram Moolenaar015f4262020-05-05 21:25:22 +0200759 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100760 return OK;
761}
762
763/*
764 * Execute a user defined function.
Bram Moolenaarab360522021-01-10 14:02:28 +0100765 * If the function is compiled this will add a stack frame and set the
766 * instruction pointer at the start of the function.
767 * Otherwise the function is called here.
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200768 * If "pt" is not null use "pt->pt_outer" for ec_outer_ref->or_outer.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100769 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100770 */
771 static int
Bram Moolenaar0186e582021-01-10 18:33:11 +0100772call_ufunc(
773 ufunc_T *ufunc,
774 partial_T *pt,
775 int argcount,
776 ectx_T *ectx,
777 isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100778{
779 typval_T argvars[MAX_FUNC_ARGS];
780 funcexe_T funcexe;
781 int error;
782 int idx;
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100783 int did_emsg_before = did_emsg;
Bram Moolenaar968a5b62021-06-15 19:32:40 +0200784 compiletype_T compile_type = COMPILE_TYPE(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100785
Bram Moolenaare99d4222021-06-13 14:01:26 +0200786 if (func_needs_compiling(ufunc, compile_type)
787 && compile_def_function(ufunc, FALSE, compile_type, NULL)
788 == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +0200789 return FAIL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +0200790 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100791 {
Bram Moolenaar52c124d2020-12-20 21:43:35 +0100792 error = check_user_func_argcount(ufunc, argcount);
Bram Moolenaar50824712020-12-20 21:10:17 +0100793 if (error != FCERR_UNKNOWN)
794 {
795 if (error == FCERR_TOOMANY)
796 semsg(_(e_toomanyarg), ufunc->uf_name);
797 else
798 semsg(_(e_toofewarg), ufunc->uf_name);
799 return FAIL;
800 }
801
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100802 // The function has been compiled, can call it quickly. For a function
803 // that was defined later: we can call it directly next time.
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100804 // TODO: what if the function was deleted and then defined again?
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100805 if (iptr != NULL)
806 {
Bram Moolenaar20431c92020-03-20 18:39:46 +0100807 delete_instr(iptr);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100808 iptr->isn_type = ISN_DCALL;
809 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
810 iptr->isn_arg.dfunc.cdf_argcount = argcount;
811 }
Bram Moolenaar4c137212021-04-19 16:48:48 +0200812 return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, ectx);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100813 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100814
815 if (call_prepare(argcount, argvars, ectx) == FAIL)
816 return FAIL;
Bram Moolenaara80faa82020-04-12 19:37:17 +0200817 CLEAR_FIELD(funcexe);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100818 funcexe.evaluate = TRUE;
819
820 // Call the user function. Result goes in last position on the stack.
821 // TODO: add selfdict if there is one
822 error = call_user_func_check(ufunc, argcount, argvars,
823 STACK_TV_BOT(-1), &funcexe, NULL);
824
825 // Clear the arguments.
826 for (idx = 0; idx < argcount; ++idx)
827 clear_tv(&argvars[idx]);
828
829 if (error != FCERR_NONE)
830 {
831 user_func_error(error, ufunc->uf_name);
832 return FAIL;
833 }
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100834 if (did_emsg > did_emsg_before)
Bram Moolenaared677f52020-08-12 16:38:10 +0200835 // Error other than from calling the function itself.
836 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100837 return OK;
838}
839
840/*
Bram Moolenaara91a7132021-03-25 21:12:15 +0100841 * If command modifiers were applied restore them.
842 */
843 static void
844may_restore_cmdmod(funclocal_T *funclocal)
845{
846 if (funclocal->floc_restore_cmdmod)
847 {
848 cmdmod.cmod_filter_regmatch.regprog = NULL;
849 undo_cmdmod(&cmdmod);
850 cmdmod = funclocal->floc_save_cmdmod;
851 funclocal->floc_restore_cmdmod = FALSE;
852 }
853}
854
855/*
Bram Moolenaara1773442020-08-12 15:21:22 +0200856 * Return TRUE if an error was given or CTRL-C was pressed.
857 */
858 static int
859vim9_aborting(int prev_called_emsg)
860{
861 return called_emsg > prev_called_emsg || got_int || did_throw;
862}
863
864/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100865 * Execute a function by "name".
866 * This can be a builtin function or a user function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100867 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100868 * Returns FAIL if not found without an error message.
869 */
870 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100871call_by_name(
872 char_u *name,
873 int argcount,
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100874 ectx_T *ectx,
875 isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100876{
877 ufunc_T *ufunc;
878
879 if (builtin_function(name, -1))
880 {
881 int func_idx = find_internal_func(name);
882
883 if (func_idx < 0)
884 return FAIL;
Bram Moolenaar389df252020-07-09 21:20:47 +0200885 if (check_internal_func(func_idx, argcount) < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100886 return FAIL;
887 return call_bfunc(func_idx, argcount, ectx);
888 }
889
Bram Moolenaar4c17ad92020-04-27 22:47:51 +0200890 ufunc = find_func(name, FALSE, NULL);
Bram Moolenaara1773442020-08-12 15:21:22 +0200891
892 if (ufunc == NULL)
893 {
894 int called_emsg_before = called_emsg;
895
896 if (script_autoload(name, TRUE))
897 // loaded a package, search for the function again
898 ufunc = find_func(name, FALSE, NULL);
899 if (vim9_aborting(called_emsg_before))
900 return FAIL; // bail out if loading the script caused an error
901 }
902
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100903 if (ufunc != NULL)
Bram Moolenaar04947cc2021-03-06 19:26:46 +0100904 {
905 if (ufunc->uf_arg_types != NULL)
906 {
907 int i;
908 typval_T *argv = STACK_TV_BOT(0) - argcount;
909
910 // The function can change at runtime, check that the argument
911 // types are correct.
912 for (i = 0; i < argcount; ++i)
913 {
Bram Moolenaare3ffcd92021-03-08 21:47:13 +0100914 type_T *type = NULL;
Bram Moolenaar04947cc2021-03-06 19:26:46 +0100915
Bram Moolenaare3ffcd92021-03-08 21:47:13 +0100916 if (i < ufunc->uf_args.ga_len)
917 type = ufunc->uf_arg_types[i];
918 else if (ufunc->uf_va_type != NULL)
919 type = ufunc->uf_va_type->tt_member;
Bram Moolenaar04947cc2021-03-06 19:26:46 +0100920 if (type != NULL && check_typval_arg_type(type,
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +0200921 &argv[i], NULL, i + 1) == FAIL)
Bram Moolenaar04947cc2021-03-06 19:26:46 +0100922 return FAIL;
923 }
924 }
925
Bram Moolenaar4c137212021-04-19 16:48:48 +0200926 return call_ufunc(ufunc, NULL, argcount, ectx, iptr);
Bram Moolenaar04947cc2021-03-06 19:26:46 +0100927 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100928
929 return FAIL;
930}
931
932 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100933call_partial(
934 typval_T *tv,
935 int argcount_arg,
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100936 ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100937{
Bram Moolenaara90afb92020-07-15 22:38:56 +0200938 int argcount = argcount_arg;
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200939 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100940 int called_emsg_before = called_emsg;
Bram Moolenaarcb6cbf22021-01-12 17:17:01 +0100941 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100942
943 if (tv->v_type == VAR_PARTIAL)
944 {
Bram Moolenaara90afb92020-07-15 22:38:56 +0200945 partial_T *pt = tv->vval.v_partial;
946 int i;
947
948 if (pt->pt_argc > 0)
949 {
950 // Make space for arguments from the partial, shift the "argcount"
951 // arguments up.
Dominique Pelle5a9e5842021-07-24 19:32:12 +0200952 if (unlikely(ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL))
Bram Moolenaara90afb92020-07-15 22:38:56 +0200953 return FAIL;
954 for (i = 1; i <= argcount; ++i)
955 *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i);
956 ectx->ec_stack.ga_len += pt->pt_argc;
957 argcount += pt->pt_argc;
958
959 // copy the arguments from the partial onto the stack
960 for (i = 0; i < pt->pt_argc; ++i)
961 copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i));
962 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100963
964 if (pt->pt_func != NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +0200965 return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL);
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200966
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100967 name = pt->pt_name;
968 }
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200969 else if (tv->v_type == VAR_FUNC)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100970 name = tv->vval.v_string;
Bram Moolenaar95006e32020-08-29 17:47:08 +0200971 if (name != NULL)
972 {
973 char_u fname_buf[FLEN_FIXED + 1];
974 char_u *tofree = NULL;
975 int error = FCERR_NONE;
976 char_u *fname;
977
978 // May need to translate <SNR>123_ to K_SNR.
979 fname = fname_trans_sid(name, fname_buf, &tofree, &error);
980 if (error != FCERR_NONE)
981 res = FAIL;
982 else
Bram Moolenaar4c137212021-04-19 16:48:48 +0200983 res = call_by_name(fname, argcount, ectx, NULL);
Bram Moolenaar95006e32020-08-29 17:47:08 +0200984 vim_free(tofree);
985 }
986
Bram Moolenaarcb6cbf22021-01-12 17:17:01 +0100987 if (res == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100988 {
989 if (called_emsg == called_emsg_before)
Bram Moolenaar015f4262020-05-05 21:25:22 +0200990 semsg(_(e_unknownfunc),
991 name == NULL ? (char_u *)"[unknown]" : name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100992 return FAIL;
993 }
994 return OK;
995}
996
997/*
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200998 * Check if "lock" is VAR_LOCKED or VAR_FIXED. If so give an error and return
999 * TRUE.
1000 */
1001 static int
1002error_if_locked(int lock, char *error)
1003{
1004 if (lock & (VAR_LOCKED | VAR_FIXED))
1005 {
1006 emsg(_(error));
1007 return TRUE;
1008 }
1009 return FALSE;
1010}
1011
1012/*
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01001013 * Give an error if "tv" is not a number and return FAIL.
1014 */
1015 static int
1016check_for_number(typval_T *tv)
1017{
1018 if (tv->v_type != VAR_NUMBER)
1019 {
1020 semsg(_(e_expected_str_but_got_str),
1021 vartype_name(VAR_NUMBER), vartype_name(tv->v_type));
1022 return FAIL;
1023 }
1024 return OK;
1025}
1026
1027/*
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001028 * Store "tv" in variable "name".
1029 * This is for s: and g: variables.
1030 */
1031 static void
1032store_var(char_u *name, typval_T *tv)
1033{
1034 funccal_entry_T entry;
Bram Moolenaard877a572021-04-01 19:42:48 +02001035 int flags = ASSIGN_DECL;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001036
Bram Moolenaard877a572021-04-01 19:42:48 +02001037 if (tv->v_lock)
1038 flags |= ASSIGN_CONST;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001039 save_funccal(&entry);
Bram Moolenaard877a572021-04-01 19:42:48 +02001040 set_var_const(name, NULL, tv, FALSE, flags, 0);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001041 restore_funccal();
1042}
1043
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001044/*
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001045 * Convert "tv" to a string.
1046 * Return FAIL if not allowed.
1047 */
1048 static int
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001049do_2string(typval_T *tv, int is_2string_any, int tolerant)
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001050{
1051 if (tv->v_type != VAR_STRING)
1052 {
1053 char_u *str;
1054
1055 if (is_2string_any)
1056 {
1057 switch (tv->v_type)
1058 {
1059 case VAR_SPECIAL:
1060 case VAR_BOOL:
1061 case VAR_NUMBER:
1062 case VAR_FLOAT:
1063 case VAR_BLOB: break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001064
1065 case VAR_LIST:
1066 if (tolerant)
1067 {
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001068 char_u *s, *e, *p;
1069 garray_T ga;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001070
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001071 ga_init2(&ga, sizeof(char_u *), 1);
1072
1073 // Convert to NL separated items, then
1074 // escape the items and replace the NL with
1075 // a space.
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001076 str = typval2string(tv, TRUE);
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001077 if (str == NULL)
1078 return FAIL;
1079 s = str;
1080 while ((e = vim_strchr(s, '\n')) != NULL)
1081 {
1082 *e = NUL;
1083 p = vim_strsave_fnameescape(s, FALSE);
1084 if (p != NULL)
1085 {
1086 ga_concat(&ga, p);
1087 ga_concat(&ga, (char_u *)" ");
1088 vim_free(p);
1089 }
1090 s = e + 1;
1091 }
1092 vim_free(str);
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001093 clear_tv(tv);
1094 tv->v_type = VAR_STRING;
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001095 tv->vval.v_string = ga.ga_data;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001096 return OK;
1097 }
1098 // FALLTHROUGH
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001099 default: to_string_error(tv->v_type);
1100 return FAIL;
1101 }
1102 }
Bram Moolenaar34453202021-01-31 13:08:38 +01001103 str = typval_tostring(tv, TRUE);
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001104 clear_tv(tv);
1105 tv->v_type = VAR_STRING;
1106 tv->vval.v_string = str;
1107 }
1108 return OK;
1109}
1110
1111/*
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001112 * When the value of "sv" is a null list of dict, allocate it.
1113 */
1114 static void
1115allocate_if_null(typval_T *tv)
1116{
1117 switch (tv->v_type)
1118 {
1119 case VAR_LIST:
1120 if (tv->vval.v_list == NULL)
Bram Moolenaarfef80642021-02-03 20:01:19 +01001121 (void)rettv_list_alloc(tv);
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001122 break;
1123 case VAR_DICT:
1124 if (tv->vval.v_dict == NULL)
Bram Moolenaarfef80642021-02-03 20:01:19 +01001125 (void)rettv_dict_alloc(tv);
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001126 break;
Bram Moolenaarb7c21af2021-04-18 14:12:31 +02001127 case VAR_BLOB:
1128 if (tv->vval.v_blob == NULL)
1129 (void)rettv_blob_alloc(tv);
1130 break;
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001131 default:
1132 break;
1133 }
1134}
Bram Moolenaard3aac292020-04-19 14:32:17 +02001135
Bram Moolenaare7525c52021-01-09 13:20:37 +01001136/*
Bram Moolenaar0289a092021-03-14 18:40:19 +01001137 * Return the character "str[index]" where "index" is the character index,
1138 * including composing characters.
1139 * If "index" is out of range NULL is returned.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001140 */
1141 char_u *
1142char_from_string(char_u *str, varnumber_T index)
1143{
1144 size_t nbyte = 0;
1145 varnumber_T nchar = index;
1146 size_t slen;
1147
1148 if (str == NULL)
1149 return NULL;
1150 slen = STRLEN(str);
1151
Bram Moolenaarff871402021-03-26 13:34:05 +01001152 // Do the same as for a list: a negative index counts from the end.
1153 // Optimization to check the first byte to be below 0x80 (and no composing
1154 // character follows) makes this a lot faster.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001155 if (index < 0)
1156 {
1157 int clen = 0;
1158
1159 for (nbyte = 0; nbyte < slen; ++clen)
Bram Moolenaarff871402021-03-26 13:34:05 +01001160 {
1161 if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
1162 ++nbyte;
1163 else if (enc_utf8)
1164 nbyte += utfc_ptr2len(str + nbyte);
1165 else
1166 nbyte += mb_ptr2len(str + nbyte);
1167 }
Bram Moolenaare7525c52021-01-09 13:20:37 +01001168 nchar = clen + index;
1169 if (nchar < 0)
1170 // unlike list: index out of range results in empty string
1171 return NULL;
1172 }
1173
1174 for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar)
Bram Moolenaarff871402021-03-26 13:34:05 +01001175 {
1176 if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
1177 ++nbyte;
1178 else if (enc_utf8)
1179 nbyte += utfc_ptr2len(str + nbyte);
1180 else
1181 nbyte += mb_ptr2len(str + nbyte);
1182 }
Bram Moolenaare7525c52021-01-09 13:20:37 +01001183 if (nbyte >= slen)
1184 return NULL;
Bram Moolenaar0289a092021-03-14 18:40:19 +01001185 return vim_strnsave(str + nbyte, mb_ptr2len(str + nbyte));
Bram Moolenaare7525c52021-01-09 13:20:37 +01001186}
1187
1188/*
1189 * Get the byte index for character index "idx" in string "str" with length
Bram Moolenaar0289a092021-03-14 18:40:19 +01001190 * "str_len". Composing characters are included.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001191 * If going over the end return "str_len".
1192 * If "idx" is negative count from the end, -1 is the last character.
1193 * When going over the start return -1.
1194 */
1195 static long
1196char_idx2byte(char_u *str, size_t str_len, varnumber_T idx)
1197{
1198 varnumber_T nchar = idx;
1199 size_t nbyte = 0;
1200
1201 if (nchar >= 0)
1202 {
1203 while (nchar > 0 && nbyte < str_len)
1204 {
Bram Moolenaar0289a092021-03-14 18:40:19 +01001205 nbyte += mb_ptr2len(str + nbyte);
Bram Moolenaare7525c52021-01-09 13:20:37 +01001206 --nchar;
1207 }
1208 }
1209 else
1210 {
1211 nbyte = str_len;
1212 while (nchar < 0 && nbyte > 0)
1213 {
1214 --nbyte;
1215 nbyte -= mb_head_off(str, str + nbyte);
1216 ++nchar;
1217 }
1218 if (nchar < 0)
1219 return -1;
1220 }
1221 return (long)nbyte;
1222}
1223
1224/*
Bram Moolenaar0289a092021-03-14 18:40:19 +01001225 * Return the slice "str[first : last]" using character indexes. Composing
1226 * characters are included.
Bram Moolenaar6601b622021-01-13 21:47:15 +01001227 * "exclusive" is TRUE for slice().
Bram Moolenaare7525c52021-01-09 13:20:37 +01001228 * Return NULL when the result is empty.
1229 */
1230 char_u *
Bram Moolenaar6601b622021-01-13 21:47:15 +01001231string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001232{
1233 long start_byte, end_byte;
1234 size_t slen;
1235
1236 if (str == NULL)
1237 return NULL;
1238 slen = STRLEN(str);
1239 start_byte = char_idx2byte(str, slen, first);
1240 if (start_byte < 0)
1241 start_byte = 0; // first index very negative: use zero
Bram Moolenaar6601b622021-01-13 21:47:15 +01001242 if ((last == -1 && !exclusive) || last == VARNUM_MAX)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001243 end_byte = (long)slen;
1244 else
1245 {
1246 end_byte = char_idx2byte(str, slen, last);
Bram Moolenaar6601b622021-01-13 21:47:15 +01001247 if (!exclusive && end_byte >= 0 && end_byte < (long)slen)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001248 // end index is inclusive
Bram Moolenaar0289a092021-03-14 18:40:19 +01001249 end_byte += mb_ptr2len(str + end_byte);
Bram Moolenaare7525c52021-01-09 13:20:37 +01001250 }
1251
1252 if (start_byte >= (long)slen || end_byte <= start_byte)
1253 return NULL;
1254 return vim_strnsave(str + start_byte, end_byte - start_byte);
1255}
1256
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001257/*
1258 * Get a script variable for ISN_STORESCRIPT and ISN_LOADSCRIPT.
1259 * When "dfunc_idx" is negative don't give an error.
1260 * Returns NULL for an error.
1261 */
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001262 static svar_T *
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001263get_script_svar(scriptref_T *sref, int dfunc_idx)
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001264{
1265 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001266 dfunc_T *dfunc = dfunc_idx < 0 ? NULL
1267 : ((dfunc_T *)def_functions.ga_data) + dfunc_idx;
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001268 svar_T *sv;
1269
1270 if (sref->sref_seq != si->sn_script_seq)
1271 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001272 // The script was reloaded after the function was compiled, the
1273 // script_idx may not be valid.
1274 if (dfunc != NULL)
1275 semsg(_(e_script_variable_invalid_after_reload_in_function_str),
1276 printable_func_name(dfunc->df_ufunc));
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001277 return NULL;
1278 }
1279 sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx;
Bram Moolenaar60dc8272021-07-29 22:48:54 +02001280 if (!equal_type(sv->sv_type, sref->sref_type, 0))
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001281 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001282 if (dfunc != NULL)
1283 emsg(_(e_script_variable_type_changed));
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001284 return NULL;
1285 }
1286 return sv;
1287}
1288
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001289/*
Bram Moolenaar20677332021-06-06 17:02:53 +02001290 * Function passed to do_cmdline() for splitting a script joined by NL
1291 * characters.
1292 */
1293 static char_u *
1294get_split_sourceline(
1295 int c UNUSED,
1296 void *cookie,
1297 int indent UNUSED,
1298 getline_opt_T options UNUSED)
1299{
1300 source_cookie_T *sp = (source_cookie_T *)cookie;
1301 char_u *p;
1302 char_u *line;
1303
1304 if (*sp->nextline == NUL)
1305 return NULL;
1306 p = vim_strchr(sp->nextline, '\n');
1307 if (p == NULL)
1308 {
1309 line = vim_strsave(sp->nextline);
1310 sp->nextline += STRLEN(sp->nextline);
1311 }
1312 else
1313 {
1314 line = vim_strnsave(sp->nextline, p - sp->nextline);
1315 sp->nextline = p + 1;
1316 }
1317 return line;
1318}
1319
1320/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001321 * Execute a function by "name".
1322 * This can be a builtin function, user function or a funcref.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001323 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001324 */
1325 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001326call_eval_func(
1327 char_u *name,
1328 int argcount,
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001329 ectx_T *ectx,
1330 isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001331{
Bram Moolenaared677f52020-08-12 16:38:10 +02001332 int called_emsg_before = called_emsg;
1333 int res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001334
Bram Moolenaar4c137212021-04-19 16:48:48 +02001335 res = call_by_name(name, argcount, ectx, iptr);
Bram Moolenaared677f52020-08-12 16:38:10 +02001336 if (res == FAIL && called_emsg == called_emsg_before)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001337 {
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001338 dictitem_T *v;
1339
1340 v = find_var(name, NULL, FALSE);
1341 if (v == NULL)
1342 {
1343 semsg(_(e_unknownfunc), name);
1344 return FAIL;
1345 }
1346 if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC)
1347 {
1348 semsg(_(e_unknownfunc), name);
1349 return FAIL;
1350 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02001351 return call_partial(&v->di_tv, argcount, ectx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001352 }
Bram Moolenaared677f52020-08-12 16:38:10 +02001353 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001354}
1355
1356/*
Bram Moolenaarf112f302020-12-20 17:47:52 +01001357 * When a function reference is used, fill a partial with the information
1358 * needed, especially when it is used as a closure.
1359 */
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01001360 int
Bram Moolenaarf112f302020-12-20 17:47:52 +01001361fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
1362{
1363 pt->pt_func = ufunc;
1364 pt->pt_refcount = 1;
1365
Bram Moolenaar0d3de8c2021-01-22 20:46:27 +01001366 if (ufunc->uf_flags & FC_CLOSURE)
Bram Moolenaarf112f302020-12-20 17:47:52 +01001367 {
1368 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1369 + ectx->ec_dfunc_idx;
1370
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001371 // The closure may need to find arguments and local variables in the
1372 // current stack.
Bram Moolenaar0186e582021-01-10 18:33:11 +01001373 pt->pt_outer.out_stack = &ectx->ec_stack;
1374 pt->pt_outer.out_frame_idx = ectx->ec_frame_idx;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001375 if (ectx->ec_outer_ref != NULL)
1376 {
1377 // The current context already has a context, link to that one.
1378 pt->pt_outer.out_up = ectx->ec_outer_ref->or_outer;
1379 if (ectx->ec_outer_ref->or_partial != NULL)
1380 {
1381 pt->pt_outer.out_up_partial = ectx->ec_outer_ref->or_partial;
1382 ++pt->pt_outer.out_up_partial->pt_refcount;
1383 }
1384 }
Bram Moolenaarf112f302020-12-20 17:47:52 +01001385
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001386 // If this function returns and the closure is still being used, we
1387 // need to make a copy of the context (arguments and local variables).
1388 // Store a reference to the partial so we can handle that.
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001389 if (unlikely(ga_grow(&ectx->ec_funcrefs, 1) == FAIL))
Bram Moolenaarf112f302020-12-20 17:47:52 +01001390 {
1391 vim_free(pt);
1392 return FAIL;
1393 }
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001394 // Extra variable keeps the count of closures created in the current
1395 // function call.
Bram Moolenaarf112f302020-12-20 17:47:52 +01001396 ++(((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx
1397 + STACK_FRAME_SIZE + dfunc->df_varcount)->vval.v_number;
1398
1399 ((partial_T **)ectx->ec_funcrefs.ga_data)
1400 [ectx->ec_funcrefs.ga_len] = pt;
1401 ++pt->pt_refcount;
1402 ++ectx->ec_funcrefs.ga_len;
1403 }
Bram Moolenaar0d3de8c2021-01-22 20:46:27 +01001404 ++ufunc->uf_refcount;
Bram Moolenaarf112f302020-12-20 17:47:52 +01001405 return OK;
1406}
1407
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001408// used for v_instr of typval of VAR_INSTR
1409struct instr_S {
1410 ectx_T *instr_ectx;
1411 isn_T *instr_instr;
1412};
1413
Bram Moolenaar4c137212021-04-19 16:48:48 +02001414// used for substitute_instr
1415typedef struct subs_expr_S {
1416 ectx_T *subs_ectx;
1417 isn_T *subs_instr;
1418 int subs_status;
1419} subs_expr_T;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001420
1421// Get pointer to item in the stack.
Bram Moolenaar4c137212021-04-19 16:48:48 +02001422#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001423
1424// Get pointer to item at the bottom of the stack, -1 is the bottom.
1425#undef STACK_TV_BOT
Bram Moolenaar4c137212021-04-19 16:48:48 +02001426#define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001427
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001428// Get pointer to a local variable on the stack. Negative for arguments.
Bram Moolenaar4c137212021-04-19 16:48:48 +02001429#define STACK_TV_VAR(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx + STACK_FRAME_SIZE + idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001430
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001431// Set when calling do_debug().
1432static ectx_T *debug_context = NULL;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001433static int debug_var_count;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001434
1435/*
1436 * When debugging lookup "name" and return the typeval.
1437 * When not found return NULL.
1438 */
1439 typval_T *
1440lookup_debug_var(char_u *name)
1441{
1442 int idx;
1443 dfunc_T *dfunc;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001444 ufunc_T *ufunc;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001445 ectx_T *ectx = debug_context;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001446 int varargs_off;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001447
1448 if (ectx == NULL)
1449 return NULL;
1450 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
1451
1452 // Go through the local variable names, from last to first.
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001453 for (idx = debug_var_count - 1; idx >= 0; --idx)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001454 {
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001455 if (STRCMP(((char_u **)dfunc->df_var_names.ga_data)[idx], name) == 0)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001456 return STACK_TV_VAR(idx);
1457 }
1458
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001459 // Go through argument names.
1460 ufunc = dfunc->df_ufunc;
1461 varargs_off = ufunc->uf_va_name == NULL ? 0 : 1;
1462 for (idx = 0; idx < ufunc->uf_args.ga_len; ++idx)
1463 if (STRCMP(((char_u **)(ufunc->uf_args.ga_data))[idx], name) == 0)
1464 return STACK_TV(ectx->ec_frame_idx - ufunc->uf_args.ga_len
1465 - varargs_off + idx);
1466 if (ufunc->uf_va_name != NULL && STRCMP(ufunc->uf_va_name, name) == 0)
1467 return STACK_TV(ectx->ec_frame_idx - 1);
1468
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001469 return NULL;
1470}
1471
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001472 static void
1473handle_debug(isn_T *iptr, ectx_T *ectx)
1474{
1475 char_u *line;
1476 ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
1477 + ectx->ec_dfunc_idx)->df_ufunc;
1478 isn_T *ni;
1479 int end_lnum = iptr->isn_lnum;
1480 garray_T ga;
1481 int lnum;
1482
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001483 if (ex_nesting_level > debug_break_level)
1484 {
1485 linenr_T breakpoint;
1486
1487 if (!ufunc->uf_has_breakpoint)
1488 return;
1489
1490 // check for the next breakpoint if needed
1491 breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name,
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001492 iptr->isn_arg.debug.dbg_break_lnum);
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001493 if (breakpoint <= 0 || breakpoint > iptr->isn_lnum)
1494 return;
1495 }
1496
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001497 SOURCING_LNUM = iptr->isn_lnum;
1498 debug_context = ectx;
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001499 debug_var_count = iptr->isn_arg.debug.dbg_var_names_len;
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001500
1501 for (ni = iptr + 1; ni->isn_type != ISN_FINISH; ++ni)
1502 if (ni->isn_type == ISN_DEBUG
1503 || ni->isn_type == ISN_RETURN
1504 || ni->isn_type == ISN_RETURN_VOID)
1505 {
1506 end_lnum = ni->isn_lnum;
1507 break;
1508 }
1509
1510 if (end_lnum > iptr->isn_lnum)
1511 {
1512 ga_init2(&ga, sizeof(char_u *), 10);
1513 for (lnum = iptr->isn_lnum; lnum < end_lnum; ++lnum)
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001514 {
Bram Moolenaar303215d2021-07-07 20:10:43 +02001515 char_u *p = ((char_u **)ufunc->uf_lines.ga_data)[lnum - 1];
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001516
Bram Moolenaar303215d2021-07-07 20:10:43 +02001517 if (p == NULL)
1518 continue; // left over from continuation line
1519 p = skipwhite(p);
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001520 if (*p == '#')
1521 break;
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001522 if (likely(ga_grow(&ga, 1) == OK))
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001523 ((char_u **)(ga.ga_data))[ga.ga_len++] = p;
1524 if (STRNCMP(p, "def ", 4) == 0)
1525 break;
1526 }
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001527 line = ga_concat_strings(&ga, " ");
1528 vim_free(ga.ga_data);
1529 }
1530 else
1531 line = ((char_u **)ufunc->uf_lines.ga_data)[iptr->isn_lnum - 1];
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001532
Dominique Pelle6e969552021-06-17 13:53:41 +02001533 do_debug(line == NULL ? (char_u *)"[empty]" : line);
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001534 debug_context = NULL;
1535
1536 if (end_lnum > iptr->isn_lnum)
1537 vim_free(line);
1538}
1539
Bram Moolenaar4c137212021-04-19 16:48:48 +02001540/*
1541 * Execute instructions in execution context "ectx".
1542 * Return OK or FAIL;
1543 */
1544 static int
1545exec_instructions(ectx_T *ectx)
1546{
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001547 int ret = FAIL;
1548 int save_trylevel_at_start = ectx->ec_trylevel_at_start;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01001549
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02001550 // Start execution at the first instruction.
Bram Moolenaar4c137212021-04-19 16:48:48 +02001551 ectx->ec_iidx = 0;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001552
Bram Moolenaarff652882021-05-16 15:24:49 +02001553 // Only catch exceptions in this instruction list.
1554 ectx->ec_trylevel_at_start = trylevel;
1555
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001556 for (;;)
1557 {
Bram Moolenaara7490192021-07-22 12:26:14 +02001558 static int breakcheck_count = 0; // using "static" makes it faster
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001559 isn_T *iptr;
Bram Moolenaara7490192021-07-22 12:26:14 +02001560 typval_T *tv;
Bram Moolenaar20431c92020-03-20 18:39:46 +01001561
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001562 if (unlikely(++breakcheck_count >= 100))
Bram Moolenaar270d0382020-05-15 21:42:53 +02001563 {
1564 line_breakcheck();
1565 breakcheck_count = 0;
1566 }
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001567 if (unlikely(got_int))
Bram Moolenaar20431c92020-03-20 18:39:46 +01001568 {
1569 // Turn CTRL-C into an exception.
1570 got_int = FALSE;
Bram Moolenaar97acfc72020-03-22 13:44:28 +01001571 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001572 goto theend;
Bram Moolenaar20431c92020-03-20 18:39:46 +01001573 did_throw = TRUE;
1574 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001575
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001576 if (unlikely(did_emsg && msg_list != NULL && *msg_list != NULL))
Bram Moolenaara26b9702020-04-18 19:53:28 +02001577 {
1578 // Turn an error message into an exception.
1579 did_emsg = FALSE;
1580 if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001581 goto theend;
Bram Moolenaara26b9702020-04-18 19:53:28 +02001582 did_throw = TRUE;
1583 *msg_list = NULL;
1584 }
1585
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001586 if (unlikely(did_throw))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001587 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02001588 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01001589 trycmd_T *trycmd = NULL;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02001590 int index = trystack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001591
1592 // An exception jumps to the first catch, finally, or returns from
1593 // the current function.
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02001594 while (index > 0)
1595 {
1596 trycmd = ((trycmd_T *)trystack->ga_data) + index - 1;
Bram Moolenaar834193a2021-06-30 20:39:15 +02001597 if (!trycmd->tcd_in_catch || trycmd->tcd_finally_idx != 0)
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02001598 break;
1599 // In the catch and finally block of this try we have to go up
1600 // one level.
1601 --index;
1602 trycmd = NULL;
1603 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02001604 if (trycmd != NULL && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001605 {
Bram Moolenaar834193a2021-06-30 20:39:15 +02001606 if (trycmd->tcd_in_catch)
1607 {
1608 // exception inside ":catch", jump to ":finally" once
1609 ectx->ec_iidx = trycmd->tcd_finally_idx;
1610 trycmd->tcd_finally_idx = 0;
1611 }
1612 else
1613 // jump to first ":catch"
1614 ectx->ec_iidx = trycmd->tcd_catch_idx;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02001615 trycmd->tcd_in_catch = TRUE;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02001616 did_throw = FALSE; // don't come back here until :endtry
1617 trycmd->tcd_did_throw = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001618 }
1619 else
1620 {
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02001621 // Not inside try or need to return from current functions.
1622 // Push a dummy return value.
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001623 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001624 goto theend;
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02001625 tv = STACK_TV_BOT(0);
1626 tv->v_type = VAR_NUMBER;
1627 tv->vval.v_number = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02001628 ++ectx->ec_stack.ga_len;
1629 if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001630 {
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02001631 // At the toplevel we are done.
Bram Moolenaar257cc5e2020-02-19 17:06:11 +01001632 need_rethrow = TRUE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02001633 if (handle_closure_in_use(ectx, FALSE) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001634 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001635 goto done;
1636 }
1637
Bram Moolenaar4c137212021-04-19 16:48:48 +02001638 if (func_return(ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001639 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001640 }
1641 continue;
1642 }
1643
Bram Moolenaar4c137212021-04-19 16:48:48 +02001644 iptr = &ectx->ec_instr[ectx->ec_iidx++];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001645 switch (iptr->isn_type)
1646 {
1647 // execute Ex command line
1648 case ISN_EXEC:
Bram Moolenaar631e8f92020-11-04 15:07:16 +01001649 {
Bram Moolenaar9567efa2021-01-11 22:16:30 +01001650 source_cookie_T cookie;
1651
Bram Moolenaar631e8f92020-11-04 15:07:16 +01001652 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar9567efa2021-01-11 22:16:30 +01001653 // Pass getsourceline to get an error for a missing ":end"
1654 // command.
1655 CLEAR_FIELD(cookie);
1656 cookie.sourcing_lnum = iptr->isn_lnum - 1;
1657 if (do_cmdline(iptr->isn_arg.string,
1658 getsourceline, &cookie,
1659 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED)
1660 == FAIL
1661 || did_emsg)
Bram Moolenaareeece9e2020-11-20 19:26:48 +01001662 goto on_error;
Bram Moolenaar631e8f92020-11-04 15:07:16 +01001663 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001664 break;
1665
Bram Moolenaar20677332021-06-06 17:02:53 +02001666 // execute Ex command line split at NL characters.
1667 case ISN_EXEC_SPLIT:
1668 {
1669 source_cookie_T cookie;
Bram Moolenaar518df272021-06-06 17:34:13 +02001670 char_u *line;
Bram Moolenaar20677332021-06-06 17:02:53 +02001671
1672 SOURCING_LNUM = iptr->isn_lnum;
1673 CLEAR_FIELD(cookie);
1674 cookie.sourcing_lnum = iptr->isn_lnum - 1;
1675 cookie.nextline = iptr->isn_arg.string;
Bram Moolenaar518df272021-06-06 17:34:13 +02001676 line = get_split_sourceline(0, &cookie, 0, 0);
1677 if (do_cmdline(line,
Bram Moolenaar20677332021-06-06 17:02:53 +02001678 get_split_sourceline, &cookie,
1679 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED)
1680 == FAIL
1681 || did_emsg)
Bram Moolenaar518df272021-06-06 17:34:13 +02001682 {
1683 vim_free(line);
Bram Moolenaar20677332021-06-06 17:02:53 +02001684 goto on_error;
Bram Moolenaar518df272021-06-06 17:34:13 +02001685 }
1686 vim_free(line);
Bram Moolenaar20677332021-06-06 17:02:53 +02001687 }
1688 break;
1689
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02001690 // Evaluate an expression with legacy syntax, push it onto the
1691 // stack.
1692 case ISN_LEGACY_EVAL:
1693 {
1694 char_u *arg = iptr->isn_arg.string;
1695 int res;
1696 int save_flags = cmdmod.cmod_flags;
1697
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001698 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001699 goto theend;
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02001700 tv = STACK_TV_BOT(0);
1701 init_tv(tv);
1702 cmdmod.cmod_flags |= CMOD_LEGACY;
1703 res = eval0(arg, tv, NULL, &EVALARG_EVALUATE);
1704 cmdmod.cmod_flags = save_flags;
1705 if (res == FAIL)
1706 goto on_error;
1707 ++ectx->ec_stack.ga_len;
1708 }
1709 break;
1710
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001711 // push typeval VAR_INSTR with instructions to be executed
1712 case ISN_INSTR:
1713 {
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001714 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001715 goto theend;
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001716 tv = STACK_TV_BOT(0);
1717 tv->vval.v_instr = ALLOC_ONE(instr_T);
1718 if (tv->vval.v_instr == NULL)
1719 goto on_error;
1720 ++ectx->ec_stack.ga_len;
1721
1722 tv->v_type = VAR_INSTR;
1723 tv->vval.v_instr->instr_ectx = ectx;
1724 tv->vval.v_instr->instr_instr = iptr->isn_arg.instr;
1725 }
1726 break;
1727
Bram Moolenaar4c137212021-04-19 16:48:48 +02001728 // execute :substitute with an expression
1729 case ISN_SUBSTITUTE:
1730 {
1731 subs_T *subs = &iptr->isn_arg.subs;
1732 source_cookie_T cookie;
1733 struct subs_expr_S *save_instr = substitute_instr;
1734 struct subs_expr_S subs_instr;
1735 int res;
1736
1737 subs_instr.subs_ectx = ectx;
1738 subs_instr.subs_instr = subs->subs_instr;
1739 subs_instr.subs_status = OK;
1740 substitute_instr = &subs_instr;
1741
1742 SOURCING_LNUM = iptr->isn_lnum;
1743 // This is very much like ISN_EXEC
1744 CLEAR_FIELD(cookie);
1745 cookie.sourcing_lnum = iptr->isn_lnum - 1;
1746 res = do_cmdline(subs->subs_cmd,
1747 getsourceline, &cookie,
1748 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
1749 substitute_instr = save_instr;
1750
1751 if (res == FAIL || did_emsg
1752 || subs_instr.subs_status == FAIL)
1753 goto on_error;
1754 }
1755 break;
1756
1757 case ISN_FINISH:
1758 goto done;
1759
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02001760 case ISN_REDIRSTART:
1761 // create a dummy entry for var_redir_str()
1762 if (alloc_redir_lval() == FAIL)
1763 goto on_error;
1764
1765 // The output is stored in growarray "redir_ga" until
1766 // redirection ends.
1767 init_redir_ga();
1768 redir_vname = 1;
1769 break;
1770
1771 case ISN_REDIREND:
1772 {
1773 char_u *res = get_clear_redir_ga();
1774
1775 // End redirection, put redirected text on the stack.
1776 clear_redir_lval();
1777 redir_vname = 0;
1778
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001779 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02001780 {
1781 vim_free(res);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001782 goto theend;
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02001783 }
1784 tv = STACK_TV_BOT(0);
1785 tv->v_type = VAR_STRING;
1786 tv->vval.v_string = res;
1787 ++ectx->ec_stack.ga_len;
1788 }
1789 break;
1790
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02001791 case ISN_CEXPR_AUCMD:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02001792#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02001793 if (trigger_cexpr_autocmd(iptr->isn_arg.number) == FAIL)
1794 goto on_error;
Bram Moolenaarb7c97812021-05-05 22:51:39 +02001795#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02001796 break;
1797
1798 case ISN_CEXPR_CORE:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02001799#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02001800 {
1801 exarg_T ea;
1802 int res;
1803
1804 CLEAR_FIELD(ea);
1805 ea.cmdidx = iptr->isn_arg.cexpr.cexpr_ref->cer_cmdidx;
1806 ea.forceit = iptr->isn_arg.cexpr.cexpr_ref->cer_forceit;
1807 ea.cmdlinep = &iptr->isn_arg.cexpr.cexpr_ref->cer_cmdline;
1808 --ectx->ec_stack.ga_len;
1809 tv = STACK_TV_BOT(0);
1810 res = cexpr_core(&ea, tv);
1811 clear_tv(tv);
1812 if (res == FAIL)
1813 goto on_error;
1814 }
Bram Moolenaarb7c97812021-05-05 22:51:39 +02001815#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02001816 break;
1817
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001818 // execute Ex command from pieces on the stack
1819 case ISN_EXECCONCAT:
1820 {
1821 int count = iptr->isn_arg.number;
Bram Moolenaar7f6f56f2020-04-30 20:21:43 +02001822 size_t len = 0;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001823 int pass;
1824 int i;
1825 char_u *cmd = NULL;
1826 char_u *str;
1827
1828 for (pass = 1; pass <= 2; ++pass)
1829 {
1830 for (i = 0; i < count; ++i)
1831 {
1832 tv = STACK_TV_BOT(i - count);
1833 str = tv->vval.v_string;
1834 if (str != NULL && *str != NUL)
1835 {
1836 if (pass == 2)
1837 STRCPY(cmd + len, str);
1838 len += STRLEN(str);
1839 }
1840 if (pass == 2)
1841 clear_tv(tv);
1842 }
1843 if (pass == 1)
1844 {
1845 cmd = alloc(len + 1);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001846 if (unlikely(cmd == NULL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001847 goto theend;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001848 len = 0;
1849 }
1850 }
1851
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02001852 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001853 do_cmdline_cmd(cmd);
1854 vim_free(cmd);
1855 }
1856 break;
1857
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001858 // execute :echo {string} ...
1859 case ISN_ECHO:
1860 {
1861 int count = iptr->isn_arg.echo.echo_count;
1862 int atstart = TRUE;
1863 int needclr = TRUE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02001864 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001865
1866 for (idx = 0; idx < count; ++idx)
1867 {
1868 tv = STACK_TV_BOT(idx - count);
1869 echo_one(tv, iptr->isn_arg.echo.echo_with_white,
1870 &atstart, &needclr);
1871 clear_tv(tv);
1872 }
Bram Moolenaare0807ea2020-02-20 22:18:06 +01001873 if (needclr)
1874 msg_clr_eos();
Bram Moolenaar4c137212021-04-19 16:48:48 +02001875 ectx->ec_stack.ga_len -= count;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001876 }
1877 break;
1878
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001879 // :execute {string} ...
1880 // :echomsg {string} ...
1881 // :echoerr {string} ...
Bram Moolenaarad39c092020-02-26 18:23:43 +01001882 case ISN_EXECUTE:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001883 case ISN_ECHOMSG:
1884 case ISN_ECHOERR:
Bram Moolenaarad39c092020-02-26 18:23:43 +01001885 {
1886 int count = iptr->isn_arg.number;
1887 garray_T ga;
1888 char_u buf[NUMBUFLEN];
1889 char_u *p;
1890 int len;
1891 int failed = FALSE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02001892 int idx;
Bram Moolenaarad39c092020-02-26 18:23:43 +01001893
1894 ga_init2(&ga, 1, 80);
1895 for (idx = 0; idx < count; ++idx)
1896 {
1897 tv = STACK_TV_BOT(idx - count);
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001898 if (iptr->isn_type == ISN_EXECUTE)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001899 {
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001900 if (tv->v_type == VAR_CHANNEL
1901 || tv->v_type == VAR_JOB)
1902 {
1903 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar68db9962021-05-09 23:19:22 +02001904 semsg(_(e_using_invalid_value_as_string_str),
1905 vartype_name(tv->v_type));
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001906 break;
1907 }
1908 else
1909 p = tv_get_string_buf(tv, buf);
Bram Moolenaarad39c092020-02-26 18:23:43 +01001910 }
1911 else
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001912 p = tv_stringify(tv, buf);
Bram Moolenaarad39c092020-02-26 18:23:43 +01001913
1914 len = (int)STRLEN(p);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001915 if (unlikely(ga_grow(&ga, len + 2) == FAIL))
Bram Moolenaarad39c092020-02-26 18:23:43 +01001916 failed = TRUE;
1917 else
1918 {
1919 if (ga.ga_len > 0)
1920 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
1921 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
1922 ga.ga_len += len;
1923 }
1924 clear_tv(tv);
1925 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02001926 ectx->ec_stack.ga_len -= count;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001927 if (failed)
Bram Moolenaarc71ee822020-11-21 11:45:50 +01001928 {
1929 ga_clear(&ga);
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001930 goto on_error;
Bram Moolenaarc71ee822020-11-21 11:45:50 +01001931 }
Bram Moolenaarad39c092020-02-26 18:23:43 +01001932
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001933 if (ga.ga_data != NULL)
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001934 {
1935 if (iptr->isn_type == ISN_EXECUTE)
Bram Moolenaar430deb12020-08-23 16:29:11 +02001936 {
1937 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001938 do_cmdline_cmd((char_u *)ga.ga_data);
Bram Moolenaareeece9e2020-11-20 19:26:48 +01001939 if (did_emsg)
Bram Moolenaarc71ee822020-11-21 11:45:50 +01001940 {
1941 ga_clear(&ga);
Bram Moolenaareeece9e2020-11-20 19:26:48 +01001942 goto on_error;
Bram Moolenaarc71ee822020-11-21 11:45:50 +01001943 }
Bram Moolenaar430deb12020-08-23 16:29:11 +02001944 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001945 else
1946 {
1947 msg_sb_eol();
1948 if (iptr->isn_type == ISN_ECHOMSG)
1949 {
1950 msg_attr(ga.ga_data, echo_attr);
1951 out_flush();
1952 }
1953 else
1954 {
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001955 SOURCING_LNUM = iptr->isn_lnum;
1956 emsg(ga.ga_data);
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001957 }
1958 }
1959 }
Bram Moolenaarad39c092020-02-26 18:23:43 +01001960 ga_clear(&ga);
1961 }
1962 break;
1963
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001964 // load local variable or argument
1965 case ISN_LOAD:
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001966 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001967 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001968 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02001969 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001970 break;
1971
1972 // load v: variable
1973 case ISN_LOADV:
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001974 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001975 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001976 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02001977 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001978 break;
1979
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001980 // load s: variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001981 case ISN_LOADSCRIPT:
1982 {
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01001983 scriptref_T *sref = iptr->isn_arg.script.scriptref;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001984 svar_T *sv;
1985
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001986 sv = get_script_svar(sref, ectx->ec_dfunc_idx);
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001987 if (sv == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001988 goto theend;
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001989 allocate_if_null(sv->sv_tv);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02001990 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02001991 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001992 copy_tv(sv->sv_tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02001993 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001994 }
1995 break;
1996
1997 // load s: variable in old script
1998 case ISN_LOADS:
1999 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002000 hashtab_T *ht = &SCRIPT_VARS(
2001 iptr->isn_arg.loadstore.ls_sid);
2002 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002003 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002004
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002005 if (di == NULL)
2006 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002007 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002008 semsg(_(e_undefined_variable_str), name);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002009 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002010 }
2011 else
2012 {
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002013 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002014 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002015 copy_tv(&di->di_tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02002016 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002017 }
2018 }
2019 break;
2020
Bram Moolenaard3aac292020-04-19 14:32:17 +02002021 // load g:/b:/w:/t: variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002022 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02002023 case ISN_LOADB:
2024 case ISN_LOADW:
2025 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002026 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002027 dictitem_T *di = NULL;
2028 hashtab_T *ht = NULL;
2029 char namespace;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002030
Bram Moolenaard3aac292020-04-19 14:32:17 +02002031 switch (iptr->isn_type)
2032 {
2033 case ISN_LOADG:
2034 ht = get_globvar_ht();
2035 namespace = 'g';
2036 break;
2037 case ISN_LOADB:
2038 ht = &curbuf->b_vars->dv_hashtab;
2039 namespace = 'b';
2040 break;
2041 case ISN_LOADW:
2042 ht = &curwin->w_vars->dv_hashtab;
2043 namespace = 'w';
2044 break;
2045 case ISN_LOADT:
2046 ht = &curtab->tp_vars->dv_hashtab;
2047 namespace = 't';
2048 break;
2049 default: // Cannot reach here
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002050 goto theend;
Bram Moolenaard3aac292020-04-19 14:32:17 +02002051 }
2052 di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002053
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002054 if (di == NULL)
2055 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002056 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002057 semsg(_(e_undefined_variable_char_str),
Bram Moolenaard3aac292020-04-19 14:32:17 +02002058 namespace, iptr->isn_arg.string);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002059 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002060 }
2061 else
2062 {
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002063 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002064 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002065 copy_tv(&di->di_tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02002066 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002067 }
2068 }
2069 break;
2070
Bram Moolenaar03290b82020-12-19 16:30:44 +01002071 // load autoload variable
2072 case ISN_LOADAUTO:
2073 {
2074 char_u *name = iptr->isn_arg.string;
2075
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002076 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002077 goto theend;
Bram Moolenaar03290b82020-12-19 16:30:44 +01002078 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar38a434f2021-01-02 12:45:45 +01002079 if (eval_variable(name, (int)STRLEN(name),
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01002080 STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL)
Bram Moolenaar03290b82020-12-19 16:30:44 +01002081 goto on_error;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002082 ++ectx->ec_stack.ga_len;
Bram Moolenaar03290b82020-12-19 16:30:44 +01002083 }
2084 break;
2085
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002086 // load g:/b:/w:/t: namespace
2087 case ISN_LOADGDICT:
2088 case ISN_LOADBDICT:
2089 case ISN_LOADWDICT:
2090 case ISN_LOADTDICT:
2091 {
2092 dict_T *d = NULL;
2093
2094 switch (iptr->isn_type)
2095 {
Bram Moolenaar682d0a12020-07-19 20:48:59 +02002096 case ISN_LOADGDICT: d = get_globvar_dict(); break;
2097 case ISN_LOADBDICT: d = curbuf->b_vars; break;
2098 case ISN_LOADWDICT: d = curwin->w_vars; break;
2099 case ISN_LOADTDICT: d = curtab->tp_vars; break;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002100 default: // Cannot reach here
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002101 goto theend;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002102 }
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002103 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002104 goto theend;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002105 tv = STACK_TV_BOT(0);
2106 tv->v_type = VAR_DICT;
2107 tv->v_lock = 0;
2108 tv->vval.v_dict = d;
Bram Moolenaar1bd3cb22021-02-24 12:27:31 +01002109 ++d->dv_refcount;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002110 ++ectx->ec_stack.ga_len;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002111 }
2112 break;
2113
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002114 // load &option
2115 case ISN_LOADOPT:
2116 {
2117 typval_T optval;
2118 char_u *name = iptr->isn_arg.string;
2119
Bram Moolenaara8c17702020-04-01 21:17:24 +02002120 // This is not expected to fail, name is checked during
2121 // compilation: don't set SOURCING_LNUM.
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002122 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002123 goto theend;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002124 if (eval_option(&name, &optval, TRUE) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002125 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002126 *STACK_TV_BOT(0) = optval;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002127 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002128 }
2129 break;
2130
2131 // load $ENV
2132 case ISN_LOADENV:
2133 {
2134 typval_T optval;
2135 char_u *name = iptr->isn_arg.string;
2136
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002137 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002138 goto theend;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002139 // name is always valid, checked when compiling
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002140 (void)eval_env_var(&name, &optval, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002141 *STACK_TV_BOT(0) = optval;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002142 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002143 }
2144 break;
2145
2146 // load @register
2147 case ISN_LOADREG:
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002148 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002149 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002150 tv = STACK_TV_BOT(0);
2151 tv->v_type = VAR_STRING;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002152 tv->v_lock = 0;
Bram Moolenaar1e021e62020-10-16 20:25:23 +02002153 // This may result in NULL, which should be equivalent to an
2154 // empty string.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002155 tv->vval.v_string = get_reg_contents(
2156 iptr->isn_arg.number, GREG_EXPR_SRC);
Bram Moolenaar4c137212021-04-19 16:48:48 +02002157 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002158 break;
2159
2160 // store local variable
2161 case ISN_STORE:
Bram Moolenaar4c137212021-04-19 16:48:48 +02002162 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002163 tv = STACK_TV_VAR(iptr->isn_arg.number);
2164 clear_tv(tv);
2165 *tv = *STACK_TV_BOT(0);
2166 break;
2167
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002168 // store s: variable in old script
2169 case ISN_STORES:
2170 {
2171 hashtab_T *ht = &SCRIPT_VARS(
2172 iptr->isn_arg.loadstore.ls_sid);
2173 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002174 dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002175
Bram Moolenaar4c137212021-04-19 16:48:48 +02002176 --ectx->ec_stack.ga_len;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002177 if (di == NULL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002178 store_var(name, STACK_TV_BOT(0));
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002179 else
2180 {
Bram Moolenaardcf29ac2021-04-02 14:44:02 +02002181 SOURCING_LNUM = iptr->isn_lnum;
2182 if (var_check_permission(di, name) == FAIL)
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02002183 {
2184 clear_tv(STACK_TV_BOT(0));
Bram Moolenaardcf29ac2021-04-02 14:44:02 +02002185 goto on_error;
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02002186 }
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002187 clear_tv(&di->di_tv);
2188 di->di_tv = *STACK_TV_BOT(0);
2189 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002190 }
2191 break;
2192
2193 // store script-local variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002194 case ISN_STORESCRIPT:
2195 {
Bram Moolenaar07a65d22020-12-26 20:09:15 +01002196 scriptref_T *sref = iptr->isn_arg.script.scriptref;
2197 svar_T *sv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002198
Bram Moolenaar6db660b2021-08-01 14:08:54 +02002199 sv = get_script_svar(sref, ectx->ec_dfunc_idx);
Bram Moolenaar07a65d22020-12-26 20:09:15 +01002200 if (sv == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002201 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002202 --ectx->ec_stack.ga_len;
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02002203
2204 // "const" and "final" are checked at compile time, locking
2205 // the value needs to be checked here.
2206 SOURCING_LNUM = iptr->isn_lnum;
2207 if (value_check_lock(sv->sv_tv->v_lock, sv->sv_name, FALSE))
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02002208 {
2209 clear_tv(STACK_TV_BOT(0));
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02002210 goto on_error;
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02002211 }
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02002212
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002213 clear_tv(sv->sv_tv);
2214 *sv->sv_tv = *STACK_TV_BOT(0);
2215 }
2216 break;
2217
2218 // store option
2219 case ISN_STOREOPT:
2220 {
2221 long n = 0;
2222 char_u *s = NULL;
2223 char *msg;
2224
Bram Moolenaar4c137212021-04-19 16:48:48 +02002225 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002226 tv = STACK_TV_BOT(0);
2227 if (tv->v_type == VAR_STRING)
Bram Moolenaar97a2af32020-01-28 22:52:48 +01002228 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002229 s = tv->vval.v_string;
Bram Moolenaar97a2af32020-01-28 22:52:48 +01002230 if (s == NULL)
2231 s = (char_u *)"";
2232 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002233 else
Bram Moolenaara6e67e42020-05-15 23:36:40 +02002234 // must be VAR_NUMBER, CHECKTYPE makes sure
2235 n = tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002236 msg = set_option_value(iptr->isn_arg.storeopt.so_name,
2237 n, s, iptr->isn_arg.storeopt.so_flags);
Bram Moolenaare75ba262020-05-16 15:43:31 +02002238 clear_tv(tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002239 if (msg != NULL)
2240 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002241 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002242 emsg(_(msg));
Bram Moolenaare8593122020-07-18 15:17:02 +02002243 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002244 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002245 }
2246 break;
2247
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002248 // store $ENV
2249 case ISN_STOREENV:
Bram Moolenaar4c137212021-04-19 16:48:48 +02002250 --ectx->ec_stack.ga_len;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002251 tv = STACK_TV_BOT(0);
2252 vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
2253 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002254 break;
2255
2256 // store @r
2257 case ISN_STOREREG:
2258 {
2259 int reg = iptr->isn_arg.number;
2260
Bram Moolenaar4c137212021-04-19 16:48:48 +02002261 --ectx->ec_stack.ga_len;
Bram Moolenaar401d9ff2020-02-19 18:14:44 +01002262 tv = STACK_TV_BOT(0);
Bram Moolenaar74f4a962021-06-17 21:03:07 +02002263 write_reg_contents(reg, tv_get_string(tv), -1, FALSE);
Bram Moolenaar401d9ff2020-02-19 18:14:44 +01002264 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002265 }
2266 break;
2267
2268 // store v: variable
2269 case ISN_STOREV:
Bram Moolenaar4c137212021-04-19 16:48:48 +02002270 --ectx->ec_stack.ga_len;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002271 if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
2272 == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02002273 // should not happen, type is checked when compiling
2274 goto on_error;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002275 break;
2276
Bram Moolenaard3aac292020-04-19 14:32:17 +02002277 // store g:/b:/w:/t: variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002278 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02002279 case ISN_STOREB:
2280 case ISN_STOREW:
2281 case ISN_STORET:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002282 {
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01002283 dictitem_T *di;
2284 hashtab_T *ht;
2285 char_u *name = iptr->isn_arg.string + 2;
2286
Bram Moolenaard3aac292020-04-19 14:32:17 +02002287 switch (iptr->isn_type)
2288 {
2289 case ISN_STOREG:
2290 ht = get_globvar_ht();
2291 break;
2292 case ISN_STOREB:
2293 ht = &curbuf->b_vars->dv_hashtab;
2294 break;
2295 case ISN_STOREW:
2296 ht = &curwin->w_vars->dv_hashtab;
2297 break;
2298 case ISN_STORET:
2299 ht = &curtab->tp_vars->dv_hashtab;
2300 break;
2301 default: // Cannot reach here
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002302 goto theend;
Bram Moolenaard3aac292020-04-19 14:32:17 +02002303 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002304
Bram Moolenaar4c137212021-04-19 16:48:48 +02002305 --ectx->ec_stack.ga_len;
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01002306 di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002307 if (di == NULL)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002308 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002309 else
2310 {
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01002311 SOURCING_LNUM = iptr->isn_lnum;
2312 if (var_check_permission(di, name) == FAIL)
2313 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002314 clear_tv(&di->di_tv);
2315 di->di_tv = *STACK_TV_BOT(0);
2316 }
2317 }
2318 break;
2319
Bram Moolenaar03290b82020-12-19 16:30:44 +01002320 // store an autoload variable
2321 case ISN_STOREAUTO:
2322 SOURCING_LNUM = iptr->isn_lnum;
2323 set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE);
2324 clear_tv(STACK_TV_BOT(-1));
Bram Moolenaar4c137212021-04-19 16:48:48 +02002325 --ectx->ec_stack.ga_len;
Bram Moolenaar03290b82020-12-19 16:30:44 +01002326 break;
2327
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002328 // store number in local variable
2329 case ISN_STORENR:
Bram Moolenaara471eea2020-03-04 22:20:26 +01002330 tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002331 clear_tv(tv);
2332 tv->v_type = VAR_NUMBER;
Bram Moolenaara471eea2020-03-04 22:20:26 +01002333 tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002334 break;
2335
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002336 // store value in list or dict variable
2337 case ISN_STOREINDEX:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002338 {
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002339 vartype_T dest_type = iptr->isn_arg.vartype;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002340 typval_T *tv_idx = STACK_TV_BOT(-2);
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002341 typval_T *tv_dest = STACK_TV_BOT(-1);
2342 int status = OK;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002343
Bram Moolenaar752fc692021-01-04 21:57:11 +01002344 // Stack contains:
2345 // -3 value to be stored
2346 // -2 index
2347 // -1 dict or list
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002348 tv = STACK_TV_BOT(-3);
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002349 SOURCING_LNUM = iptr->isn_lnum;
2350 if (dest_type == VAR_ANY)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002351 {
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002352 dest_type = tv_dest->v_type;
2353 if (dest_type == VAR_DICT)
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02002354 status = do_2string(tv_idx, TRUE, FALSE);
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002355 else if (dest_type == VAR_LIST
2356 && tv_idx->v_type != VAR_NUMBER)
2357 {
Bram Moolenaare29a27f2021-07-20 21:07:36 +02002358 emsg(_(e_number_expected));
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002359 status = FAIL;
2360 }
2361 }
2362 else if (dest_type != tv_dest->v_type)
2363 {
2364 // just in case, should be OK
2365 semsg(_(e_expected_str_but_got_str),
2366 vartype_name(dest_type),
2367 vartype_name(tv_dest->v_type));
2368 status = FAIL;
2369 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002370
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002371 if (status == OK && dest_type == VAR_LIST)
2372 {
Bram Moolenaar239f8d92021-01-17 13:21:20 +01002373 long lidx = (long)tv_idx->vval.v_number;
2374 list_T *list = tv_dest->vval.v_list;
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002375
2376 if (list == NULL)
2377 {
2378 emsg(_(e_list_not_set));
2379 goto on_error;
2380 }
2381 if (lidx < 0 && list->lv_len + lidx >= 0)
2382 // negative index is relative to the end
2383 lidx = list->lv_len + lidx;
2384 if (lidx < 0 || lidx > list->lv_len)
2385 {
2386 semsg(_(e_listidx), lidx);
2387 goto on_error;
2388 }
2389 if (lidx < list->lv_len)
2390 {
2391 listitem_T *li = list_find(list, lidx);
2392
2393 if (error_if_locked(li->li_tv.v_lock,
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02002394 e_cannot_change_list_item))
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002395 goto on_error;
2396 // overwrite existing list item
2397 clear_tv(&li->li_tv);
2398 li->li_tv = *tv;
2399 }
2400 else
2401 {
2402 if (error_if_locked(list->lv_lock,
2403 e_cannot_change_list))
2404 goto on_error;
2405 // append to list, only fails when out of memory
2406 if (list_append_tv(list, tv) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002407 goto theend;
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002408 clear_tv(tv);
2409 }
2410 }
2411 else if (status == OK && dest_type == VAR_DICT)
2412 {
2413 char_u *key = tv_idx->vval.v_string;
2414 dict_T *dict = tv_dest->vval.v_dict;
2415 dictitem_T *di;
2416
2417 SOURCING_LNUM = iptr->isn_lnum;
2418 if (dict == NULL)
2419 {
2420 emsg(_(e_dictionary_not_set));
2421 goto on_error;
2422 }
2423 if (key == NULL)
2424 key = (char_u *)"";
2425 di = dict_find(dict, key, -1);
2426 if (di != NULL)
2427 {
2428 if (error_if_locked(di->di_tv.v_lock,
2429 e_cannot_change_dict_item))
2430 goto on_error;
2431 // overwrite existing value
2432 clear_tv(&di->di_tv);
2433 di->di_tv = *tv;
2434 }
2435 else
2436 {
2437 if (error_if_locked(dict->dv_lock,
2438 e_cannot_change_dict))
2439 goto on_error;
2440 // add to dict, only fails when out of memory
2441 if (dict_add_tv(dict, (char *)key, tv) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002442 goto theend;
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002443 clear_tv(tv);
2444 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002445 }
Bram Moolenaar68452172021-04-12 21:21:02 +02002446 else if (status == OK && dest_type == VAR_BLOB)
2447 {
Bram Moolenaar51e93322021-04-17 20:44:56 +02002448 long lidx = (long)tv_idx->vval.v_number;
2449 blob_T *blob = tv_dest->vval.v_blob;
2450 varnumber_T nr;
2451 int error = FALSE;
2452 int len;
2453
2454 if (blob == NULL)
2455 {
2456 emsg(_(e_blob_not_set));
2457 goto on_error;
2458 }
2459 len = blob_len(blob);
2460 if (lidx < 0 && len + lidx >= 0)
2461 // negative index is relative to the end
2462 lidx = len + lidx;
2463
2464 // Can add one byte at the end.
2465 if (lidx < 0 || lidx > len)
2466 {
2467 semsg(_(e_blobidx), lidx);
2468 goto on_error;
2469 }
2470 if (value_check_lock(blob->bv_lock,
2471 (char_u *)"blob", FALSE))
2472 goto on_error;
2473 nr = tv_get_number_chk(tv, &error);
2474 if (error)
2475 goto on_error;
2476 blob_set_append(blob, lidx, nr);
Bram Moolenaar68452172021-04-12 21:21:02 +02002477 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002478 else
2479 {
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002480 status = FAIL;
2481 semsg(_(e_cannot_index_str), vartype_name(dest_type));
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002482 }
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002483
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002484 clear_tv(tv_idx);
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002485 clear_tv(tv_dest);
Bram Moolenaar4c137212021-04-19 16:48:48 +02002486 ectx->ec_stack.ga_len -= 3;
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002487 if (status == FAIL)
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02002488 {
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01002489 clear_tv(tv);
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02002490 goto on_error;
2491 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002492 }
2493 break;
2494
Bram Moolenaar68452172021-04-12 21:21:02 +02002495 // store value in blob range
2496 case ISN_STORERANGE:
2497 {
2498 typval_T *tv_idx1 = STACK_TV_BOT(-3);
2499 typval_T *tv_idx2 = STACK_TV_BOT(-2);
2500 typval_T *tv_dest = STACK_TV_BOT(-1);
2501 int status = OK;
2502
2503 // Stack contains:
2504 // -4 value to be stored
2505 // -3 first index or "none"
2506 // -2 second index or "none"
2507 // -1 destination blob
2508 tv = STACK_TV_BOT(-4);
2509 if (tv_dest->v_type != VAR_BLOB)
2510 {
2511 status = FAIL;
2512 emsg(_(e_blob_required));
2513 }
2514 else
2515 {
2516 varnumber_T n1;
2517 varnumber_T n2;
2518 int error = FALSE;
2519
2520 n1 = tv_get_number_chk(tv_idx1, &error);
2521 if (error)
2522 status = FAIL;
2523 else
2524 {
2525 if (tv_idx2->v_type == VAR_SPECIAL
2526 && tv_idx2->vval.v_number == VVAL_NONE)
2527 n2 = blob_len(tv_dest->vval.v_blob) - 1;
2528 else
2529 n2 = tv_get_number_chk(tv_idx2, &error);
2530 if (error)
2531 status = FAIL;
2532 else
Bram Moolenaar0e3ff192021-04-14 20:35:23 +02002533 {
2534 long bloblen = blob_len(tv_dest->vval.v_blob);
2535
2536 if (check_blob_index(bloblen,
Bram Moolenaarbd6406f2021-04-14 21:30:06 +02002537 n1, FALSE) == FAIL
Bram Moolenaar0e3ff192021-04-14 20:35:23 +02002538 || check_blob_range(bloblen,
2539 n1, n2, FALSE) == FAIL)
2540 status = FAIL;
2541 else
2542 status = blob_set_range(
2543 tv_dest->vval.v_blob, n1, n2, tv);
2544 }
Bram Moolenaar68452172021-04-12 21:21:02 +02002545 }
2546 }
2547
2548 clear_tv(tv_idx1);
2549 clear_tv(tv_idx2);
2550 clear_tv(tv_dest);
Bram Moolenaar4c137212021-04-19 16:48:48 +02002551 ectx->ec_stack.ga_len -= 4;
Bram Moolenaar68452172021-04-12 21:21:02 +02002552 clear_tv(tv);
2553
2554 if (status == FAIL)
2555 goto on_error;
2556 }
2557 break;
2558
Bram Moolenaar0186e582021-01-10 18:33:11 +01002559 // load or store variable or argument from outer scope
2560 case ISN_LOADOUTER:
2561 case ISN_STOREOUTER:
2562 {
2563 int depth = iptr->isn_arg.outer.outer_depth;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02002564 outer_T *outer = ectx->ec_outer_ref == NULL ? NULL
2565 : ectx->ec_outer_ref->or_outer;
Bram Moolenaar0186e582021-01-10 18:33:11 +01002566
2567 while (depth > 1 && outer != NULL)
2568 {
2569 outer = outer->out_up;
2570 --depth;
2571 }
2572 if (outer == NULL)
2573 {
2574 SOURCING_LNUM = iptr->isn_lnum;
2575 iemsg("LOADOUTER depth more than scope levels");
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002576 goto theend;
Bram Moolenaar0186e582021-01-10 18:33:11 +01002577 }
2578 tv = ((typval_T *)outer->out_stack->ga_data)
2579 + outer->out_frame_idx + STACK_FRAME_SIZE
2580 + iptr->isn_arg.outer.outer_idx;
2581 if (iptr->isn_type == ISN_LOADOUTER)
2582 {
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002583 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002584 goto theend;
Bram Moolenaar0186e582021-01-10 18:33:11 +01002585 copy_tv(tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02002586 ++ectx->ec_stack.ga_len;
Bram Moolenaar0186e582021-01-10 18:33:11 +01002587 }
2588 else
2589 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02002590 --ectx->ec_stack.ga_len;
Bram Moolenaar0186e582021-01-10 18:33:11 +01002591 clear_tv(tv);
2592 *tv = *STACK_TV_BOT(0);
2593 }
2594 }
2595 break;
2596
Bram Moolenaar752fc692021-01-04 21:57:11 +01002597 // unlet item in list or dict variable
2598 case ISN_UNLETINDEX:
2599 {
2600 typval_T *tv_idx = STACK_TV_BOT(-2);
2601 typval_T *tv_dest = STACK_TV_BOT(-1);
2602 int status = OK;
2603
2604 // Stack contains:
2605 // -2 index
2606 // -1 dict or list
2607 if (tv_dest->v_type == VAR_DICT)
2608 {
2609 // unlet a dict item, index must be a string
2610 if (tv_idx->v_type != VAR_STRING)
2611 {
Bram Moolenaar0acbf5a2021-01-05 20:58:25 +01002612 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar752fc692021-01-04 21:57:11 +01002613 semsg(_(e_expected_str_but_got_str),
2614 vartype_name(VAR_STRING),
2615 vartype_name(tv_idx->v_type));
2616 status = FAIL;
2617 }
2618 else
2619 {
2620 dict_T *d = tv_dest->vval.v_dict;
2621 char_u *key = tv_idx->vval.v_string;
2622 dictitem_T *di = NULL;
2623
2624 if (key == NULL)
2625 key = (char_u *)"";
2626 if (d != NULL)
2627 di = dict_find(d, key, (int)STRLEN(key));
2628 if (di == NULL)
2629 {
2630 // NULL dict is equivalent to empty dict
Bram Moolenaar0acbf5a2021-01-05 20:58:25 +01002631 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar752fc692021-01-04 21:57:11 +01002632 semsg(_(e_dictkey), key);
2633 status = FAIL;
2634 }
2635 else
2636 {
2637 // TODO: check for dict or item locked
2638 dictitem_remove(d, di);
2639 }
2640 }
2641 }
2642 else if (tv_dest->v_type == VAR_LIST)
2643 {
2644 // unlet a List item, index must be a number
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01002645 SOURCING_LNUM = iptr->isn_lnum;
2646 if (check_for_number(tv_idx) == FAIL)
Bram Moolenaar752fc692021-01-04 21:57:11 +01002647 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01002648 status = FAIL;
2649 }
2650 else
2651 {
2652 list_T *l = tv_dest->vval.v_list;
Bram Moolenaar239f8d92021-01-17 13:21:20 +01002653 long n = (long)tv_idx->vval.v_number;
Bram Moolenaar752fc692021-01-04 21:57:11 +01002654 listitem_T *li = NULL;
2655
2656 li = list_find(l, n);
2657 if (li == NULL)
2658 {
Bram Moolenaar0acbf5a2021-01-05 20:58:25 +01002659 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar752fc692021-01-04 21:57:11 +01002660 semsg(_(e_listidx), n);
2661 status = FAIL;
2662 }
2663 else
2664 // TODO: check for list or item locked
2665 listitem_remove(l, li);
2666 }
2667 }
2668 else
2669 {
2670 status = FAIL;
2671 semsg(_(e_cannot_index_str),
2672 vartype_name(tv_dest->v_type));
2673 }
2674
2675 clear_tv(tv_idx);
2676 clear_tv(tv_dest);
Bram Moolenaar4c137212021-04-19 16:48:48 +02002677 ectx->ec_stack.ga_len -= 2;
Bram Moolenaar752fc692021-01-04 21:57:11 +01002678 if (status == FAIL)
2679 goto on_error;
2680 }
2681 break;
2682
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01002683 // unlet range of items in list variable
2684 case ISN_UNLETRANGE:
2685 {
2686 // Stack contains:
2687 // -3 index1
2688 // -2 index2
2689 // -1 dict or list
2690 typval_T *tv_idx1 = STACK_TV_BOT(-3);
2691 typval_T *tv_idx2 = STACK_TV_BOT(-2);
2692 typval_T *tv_dest = STACK_TV_BOT(-1);
2693 int status = OK;
2694
2695 if (tv_dest->v_type == VAR_LIST)
2696 {
2697 // indexes must be a number
2698 SOURCING_LNUM = iptr->isn_lnum;
2699 if (check_for_number(tv_idx1) == FAIL
Bram Moolenaar63cb6562021-07-20 22:21:59 +02002700 || (tv_idx2->v_type != VAR_SPECIAL
2701 && check_for_number(tv_idx2) == FAIL))
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01002702 {
2703 status = FAIL;
2704 }
2705 else
2706 {
2707 list_T *l = tv_dest->vval.v_list;
2708 long n1 = (long)tv_idx1->vval.v_number;
Bram Moolenaar63cb6562021-07-20 22:21:59 +02002709 long n2 = tv_idx2->v_type == VAR_SPECIAL
2710 ? 0 : (long)tv_idx2->vval.v_number;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01002711 listitem_T *li;
2712
2713 li = list_find_index(l, &n1);
Bram Moolenaar63cb6562021-07-20 22:21:59 +02002714 if (li == NULL)
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01002715 status = FAIL;
Bram Moolenaar63cb6562021-07-20 22:21:59 +02002716 else
2717 {
2718 if (n1 < 0)
2719 n1 = list_idx_of_item(l, li);
2720 if (n2 < 0)
2721 {
2722 listitem_T *li2 = list_find(l, n2);
2723
2724 if (li2 == NULL)
2725 status = FAIL;
2726 else
2727 n2 = list_idx_of_item(l, li2);
2728 }
2729 if (status != FAIL
Bram Moolenaar5dd839c2021-07-22 18:48:53 +02002730 && tv_idx2->v_type != VAR_SPECIAL
2731 && n2 < n1)
2732 {
2733 semsg(_(e_listidx), n2);
2734 status = FAIL;
2735 }
2736 if (status != FAIL
Bram Moolenaar63cb6562021-07-20 22:21:59 +02002737 && list_unlet_range(l, li, NULL, n1,
2738 tv_idx2->v_type != VAR_SPECIAL, n2)
2739 == FAIL)
2740 status = FAIL;
2741 }
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01002742 }
2743 }
2744 else
2745 {
2746 status = FAIL;
2747 SOURCING_LNUM = iptr->isn_lnum;
2748 semsg(_(e_cannot_index_str),
2749 vartype_name(tv_dest->v_type));
2750 }
2751
2752 clear_tv(tv_idx1);
2753 clear_tv(tv_idx2);
2754 clear_tv(tv_dest);
Bram Moolenaar4c137212021-04-19 16:48:48 +02002755 ectx->ec_stack.ga_len -= 3;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01002756 if (status == FAIL)
2757 goto on_error;
2758 }
2759 break;
2760
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002761 // push constant
2762 case ISN_PUSHNR:
2763 case ISN_PUSHBOOL:
2764 case ISN_PUSHSPEC:
2765 case ISN_PUSHF:
2766 case ISN_PUSHS:
2767 case ISN_PUSHBLOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01002768 case ISN_PUSHFUNC:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01002769 case ISN_PUSHCHANNEL:
2770 case ISN_PUSHJOB:
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002771 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002772 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002773 tv = STACK_TV_BOT(0);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002774 tv->v_lock = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002775 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002776 switch (iptr->isn_type)
2777 {
2778 case ISN_PUSHNR:
2779 tv->v_type = VAR_NUMBER;
2780 tv->vval.v_number = iptr->isn_arg.number;
2781 break;
2782 case ISN_PUSHBOOL:
2783 tv->v_type = VAR_BOOL;
2784 tv->vval.v_number = iptr->isn_arg.number;
2785 break;
2786 case ISN_PUSHSPEC:
2787 tv->v_type = VAR_SPECIAL;
2788 tv->vval.v_number = iptr->isn_arg.number;
2789 break;
2790#ifdef FEAT_FLOAT
2791 case ISN_PUSHF:
2792 tv->v_type = VAR_FLOAT;
2793 tv->vval.v_float = iptr->isn_arg.fnumber;
2794 break;
2795#endif
2796 case ISN_PUSHBLOB:
2797 blob_copy(iptr->isn_arg.blob, tv);
2798 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01002799 case ISN_PUSHFUNC:
2800 tv->v_type = VAR_FUNC;
Bram Moolenaar087d2e12020-03-01 15:36:42 +01002801 if (iptr->isn_arg.string == NULL)
2802 tv->vval.v_string = NULL;
2803 else
2804 tv->vval.v_string =
2805 vim_strsave(iptr->isn_arg.string);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01002806 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01002807 case ISN_PUSHCHANNEL:
2808#ifdef FEAT_JOB_CHANNEL
2809 tv->v_type = VAR_CHANNEL;
2810 tv->vval.v_channel = iptr->isn_arg.channel;
2811 if (tv->vval.v_channel != NULL)
2812 ++tv->vval.v_channel->ch_refcount;
2813#endif
2814 break;
2815 case ISN_PUSHJOB:
2816#ifdef FEAT_JOB_CHANNEL
2817 tv->v_type = VAR_JOB;
2818 tv->vval.v_job = iptr->isn_arg.job;
2819 if (tv->vval.v_job != NULL)
2820 ++tv->vval.v_job->jv_refcount;
2821#endif
2822 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002823 default:
2824 tv->v_type = VAR_STRING;
Bram Moolenaare69f6d02020-04-01 22:11:01 +02002825 tv->vval.v_string = vim_strsave(
2826 iptr->isn_arg.string == NULL
2827 ? (char_u *)"" : iptr->isn_arg.string);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002828 }
2829 break;
2830
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02002831 case ISN_UNLET:
2832 if (do_unlet(iptr->isn_arg.unlet.ul_name,
2833 iptr->isn_arg.unlet.ul_forceit) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02002834 goto on_error;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02002835 break;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02002836 case ISN_UNLETENV:
2837 vim_unsetenv(iptr->isn_arg.unlet.ul_name);
2838 break;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02002839
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02002840 case ISN_LOCKCONST:
2841 item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE);
2842 break;
2843
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002844 // create a list from items on the stack; uses a single allocation
2845 // for the list header and the items
2846 case ISN_NEWLIST:
Bram Moolenaar4c137212021-04-19 16:48:48 +02002847 if (exe_newlist(iptr->isn_arg.number, ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002848 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002849 break;
2850
2851 // create a dict from items on the stack
2852 case ISN_NEWDICT:
2853 {
Bram Moolenaare8593122020-07-18 15:17:02 +02002854 int count = iptr->isn_arg.number;
2855 dict_T *dict = dict_alloc();
2856 dictitem_T *item;
Bram Moolenaarc7f7f6d2020-11-04 13:38:28 +01002857 char_u *key;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002858 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002859
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002860 if (unlikely(dict == NULL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002861 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002862 for (idx = 0; idx < count; ++idx)
2863 {
Bram Moolenaare8593122020-07-18 15:17:02 +02002864 // have already checked key type is VAR_STRING
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002865 tv = STACK_TV_BOT(2 * (idx - count));
Bram Moolenaare8593122020-07-18 15:17:02 +02002866 // check key is unique
Bram Moolenaarc7f7f6d2020-11-04 13:38:28 +01002867 key = tv->vval.v_string == NULL
2868 ? (char_u *)"" : tv->vval.v_string;
2869 item = dict_find(dict, key, -1);
Bram Moolenaare8593122020-07-18 15:17:02 +02002870 if (item != NULL)
2871 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002872 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarc7f7f6d2020-11-04 13:38:28 +01002873 semsg(_(e_duplicate_key), key);
Bram Moolenaare8593122020-07-18 15:17:02 +02002874 dict_unref(dict);
2875 goto on_error;
2876 }
Bram Moolenaarc7f7f6d2020-11-04 13:38:28 +01002877 item = dictitem_alloc(key);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002878 clear_tv(tv);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002879 if (unlikely(item == NULL))
Bram Moolenaare8593122020-07-18 15:17:02 +02002880 {
2881 dict_unref(dict);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002882 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02002883 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002884 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
2885 item->di_tv.v_lock = 0;
2886 if (dict_add(dict, item) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02002887 {
Bram Moolenaard032f342020-07-18 18:13:02 +02002888 // can this ever happen?
Bram Moolenaare8593122020-07-18 15:17:02 +02002889 dict_unref(dict);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002890 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02002891 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002892 }
2893
2894 if (count > 0)
Bram Moolenaar4c137212021-04-19 16:48:48 +02002895 ectx->ec_stack.ga_len -= 2 * count - 1;
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002896 else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002897 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002898 else
Bram Moolenaar4c137212021-04-19 16:48:48 +02002899 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002900 tv = STACK_TV_BOT(-1);
2901 tv->v_type = VAR_DICT;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002902 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002903 tv->vval.v_dict = dict;
2904 ++dict->dv_refcount;
2905 }
2906 break;
2907
2908 // call a :def function
2909 case ISN_DCALL:
Bram Moolenaardfa3d552020-09-10 22:05:08 +02002910 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01002911 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
2912 NULL,
2913 iptr->isn_arg.dfunc.cdf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02002914 ectx) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02002915 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002916 break;
2917
2918 // call a builtin function
2919 case ISN_BCALL:
2920 SOURCING_LNUM = iptr->isn_lnum;
2921 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
2922 iptr->isn_arg.bfunc.cbf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02002923 ectx) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02002924 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002925 break;
2926
2927 // call a funcref or partial
2928 case ISN_PCALL:
2929 {
2930 cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
2931 int r;
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02002932 typval_T partial_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002933
2934 SOURCING_LNUM = iptr->isn_lnum;
2935 if (pfunc->cpf_top)
2936 {
2937 // funcref is above the arguments
2938 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
2939 }
2940 else
2941 {
2942 // Get the funcref from the stack.
Bram Moolenaar4c137212021-04-19 16:48:48 +02002943 --ectx->ec_stack.ga_len;
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02002944 partial_tv = *STACK_TV_BOT(0);
2945 tv = &partial_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002946 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02002947 r = call_partial(tv, pfunc->cpf_argcount, ectx);
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02002948 if (tv == &partial_tv)
2949 clear_tv(&partial_tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002950 if (r == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02002951 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002952 }
2953 break;
2954
Bram Moolenaarbd5da372020-03-31 23:13:10 +02002955 case ISN_PCALL_END:
2956 // PCALL finished, arguments have been consumed and replaced by
2957 // the return value. Now clear the funcref from the stack,
2958 // and move the return value in its place.
Bram Moolenaar4c137212021-04-19 16:48:48 +02002959 --ectx->ec_stack.ga_len;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02002960 clear_tv(STACK_TV_BOT(-1));
2961 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
2962 break;
2963
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002964 // call a user defined function or funcref/partial
2965 case ISN_UCALL:
2966 {
2967 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
2968
2969 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01002970 if (call_eval_func(cufunc->cuf_name, cufunc->cuf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02002971 ectx, iptr) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02002972 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002973 }
2974 break;
2975
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02002976 // return from a :def function call without a value
2977 case ISN_RETURN_VOID:
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002978 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002979 goto theend;
Bram Moolenaar299f3032021-01-08 20:53:09 +01002980 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02002981 ++ectx->ec_stack.ga_len;
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02002982 tv->v_type = VAR_VOID;
Bram Moolenaar299f3032021-01-08 20:53:09 +01002983 tv->vval.v_number = 0;
2984 tv->v_lock = 0;
2985 // FALLTHROUGH
2986
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02002987 // return from a :def function call with what is on the stack
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002988 case ISN_RETURN:
2989 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02002990 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002991 trycmd_T *trycmd = NULL;
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01002992
2993 if (trystack->ga_len > 0)
2994 trycmd = ((trycmd_T *)trystack->ga_data)
2995 + trystack->ga_len - 1;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02002996 if (trycmd != NULL
Bram Moolenaar4c137212021-04-19 16:48:48 +02002997 && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002998 {
Bram Moolenaar9cb577a2021-02-22 22:45:10 +01002999 // jump to ":finally" or ":endtry"
3000 if (trycmd->tcd_finally_idx != 0)
Bram Moolenaar4c137212021-04-19 16:48:48 +02003001 ectx->ec_iidx = trycmd->tcd_finally_idx;
Bram Moolenaar9cb577a2021-02-22 22:45:10 +01003002 else
Bram Moolenaar4c137212021-04-19 16:48:48 +02003003 ectx->ec_iidx = trycmd->tcd_endtry_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003004 trycmd->tcd_return = TRUE;
3005 }
3006 else
Bram Moolenaard032f342020-07-18 18:13:02 +02003007 goto func_return;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003008 }
3009 break;
3010
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02003011 // push a partial, a reference to a compiled function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003012 case ISN_FUNCREF:
3013 {
Bram Moolenaarf112f302020-12-20 17:47:52 +01003014 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
3015 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data)
3016 + iptr->isn_arg.funcref.fr_func;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003017
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003018 if (pt == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003019 goto theend;
Dominique Pelle5a9e5842021-07-24 19:32:12 +02003020 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003021 {
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02003022 vim_free(pt);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003023 goto theend;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02003024 }
Bram Moolenaarf112f302020-12-20 17:47:52 +01003025 if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc,
Bram Moolenaar4c137212021-04-19 16:48:48 +02003026 ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003027 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003028 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003029 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003030 tv->vval.v_partial = pt;
3031 tv->v_type = VAR_PARTIAL;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003032 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003033 }
3034 break;
3035
Bram Moolenaar38ddf332020-07-31 22:05:04 +02003036 // Create a global function from a lambda.
3037 case ISN_NEWFUNC:
3038 {
3039 newfunc_T *newfunc = &iptr->isn_arg.newfunc;
3040
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01003041 if (copy_func(newfunc->nf_lambda, newfunc->nf_global,
Bram Moolenaar4c137212021-04-19 16:48:48 +02003042 ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003043 goto theend;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02003044 }
3045 break;
3046
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01003047 // List functions
3048 case ISN_DEF:
3049 if (iptr->isn_arg.string == NULL)
3050 list_functions(NULL);
3051 else
3052 {
3053 exarg_T ea;
3054
3055 CLEAR_FIELD(ea);
3056 ea.cmd = ea.arg = iptr->isn_arg.string;
3057 define_function(&ea, NULL);
3058 }
3059 break;
3060
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003061 // jump if a condition is met
3062 case ISN_JUMP:
3063 {
3064 jumpwhen_T when = iptr->isn_arg.jump.jump_when;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003065 int error = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003066 int jump = TRUE;
3067
3068 if (when != JUMP_ALWAYS)
3069 {
3070 tv = STACK_TV_BOT(-1);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003071 if (when == JUMP_IF_COND_FALSE
Bram Moolenaar13106602020-10-04 16:06:05 +02003072 || when == JUMP_IF_FALSE
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003073 || when == JUMP_IF_COND_TRUE)
3074 {
3075 SOURCING_LNUM = iptr->isn_lnum;
3076 jump = tv_get_bool_chk(tv, &error);
3077 if (error)
3078 goto on_error;
3079 }
3080 else
3081 jump = tv2bool(tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003082 if (when == JUMP_IF_FALSE
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003083 || when == JUMP_AND_KEEP_IF_FALSE
3084 || when == JUMP_IF_COND_FALSE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003085 jump = !jump;
Bram Moolenaar777770f2020-02-06 21:27:08 +01003086 if (when == JUMP_IF_FALSE || !jump)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003087 {
3088 // drop the value from the stack
3089 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003090 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003091 }
3092 }
3093 if (jump)
Bram Moolenaar4c137212021-04-19 16:48:48 +02003094 ectx->ec_iidx = iptr->isn_arg.jump.jump_where;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003095 }
3096 break;
3097
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02003098 // Jump if an argument with a default value was already set and not
3099 // v:none.
3100 case ISN_JUMP_IF_ARG_SET:
3101 tv = STACK_TV_VAR(iptr->isn_arg.jumparg.jump_arg_off);
3102 if (tv->v_type != VAR_UNKNOWN
3103 && !(tv->v_type == VAR_SPECIAL
3104 && tv->vval.v_number == VVAL_NONE))
Bram Moolenaar4c137212021-04-19 16:48:48 +02003105 ectx->ec_iidx = iptr->isn_arg.jumparg.jump_where;
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02003106 break;
3107
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003108 // top of a for loop
3109 case ISN_FOR:
3110 {
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003111 typval_T *ltv = STACK_TV_BOT(-1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003112 typval_T *idxtv =
3113 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);
3114
Dominique Pelle5a9e5842021-07-24 19:32:12 +02003115 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003116 goto theend;
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003117 if (ltv->v_type == VAR_LIST)
Bram Moolenaara91a7132021-03-25 21:12:15 +01003118 {
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003119 list_T *list = ltv->vval.v_list;
3120
3121 // push the next item from the list
3122 ++idxtv->vval.v_number;
3123 if (list == NULL
3124 || idxtv->vval.v_number >= list->lv_len)
3125 {
3126 // past the end of the list, jump to "endfor"
Bram Moolenaar4c137212021-04-19 16:48:48 +02003127 ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
3128 may_restore_cmdmod(&ectx->ec_funclocal);
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003129 }
3130 else if (list->lv_first == &range_list_item)
3131 {
3132 // non-materialized range() list
3133 tv = STACK_TV_BOT(0);
3134 tv->v_type = VAR_NUMBER;
3135 tv->v_lock = 0;
3136 tv->vval.v_number = list_find_nr(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003137 list, idxtv->vval.v_number, NULL);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003138 ++ectx->ec_stack.ga_len;
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003139 }
3140 else
3141 {
3142 listitem_T *li = list_find(list,
3143 idxtv->vval.v_number);
3144
3145 copy_tv(&li->li_tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003146 ++ectx->ec_stack.ga_len;
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003147 }
3148 }
3149 else if (ltv->v_type == VAR_STRING)
3150 {
3151 char_u *str = ltv->vval.v_string;
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003152
Bram Moolenaard551d6c2021-04-18 13:15:58 +02003153 // The index is for the last byte of the previous
3154 // character.
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003155 ++idxtv->vval.v_number;
Bram Moolenaar175a41c2021-04-08 18:05:03 +02003156 if (str == NULL || str[idxtv->vval.v_number] == NUL)
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003157 {
3158 // past the end of the string, jump to "endfor"
Bram Moolenaar4c137212021-04-19 16:48:48 +02003159 ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
3160 may_restore_cmdmod(&ectx->ec_funclocal);
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003161 }
3162 else
3163 {
3164 int clen = mb_ptr2len(str + idxtv->vval.v_number);
3165
Bram Moolenaard551d6c2021-04-18 13:15:58 +02003166 // Push the next character from the string.
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003167 tv = STACK_TV_BOT(0);
3168 tv->v_type = VAR_STRING;
3169 tv->vval.v_string = vim_strnsave(
3170 str + idxtv->vval.v_number, clen);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003171 ++ectx->ec_stack.ga_len;
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003172 idxtv->vval.v_number += clen - 1;
3173 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003174 }
Bram Moolenaard551d6c2021-04-18 13:15:58 +02003175 else if (ltv->v_type == VAR_BLOB)
3176 {
3177 blob_T *blob = ltv->vval.v_blob;
3178
3179 // When we get here the first time make a copy of the
3180 // blob, so that the iteration still works when it is
3181 // changed.
3182 if (idxtv->vval.v_number == -1 && blob != NULL)
3183 {
3184 blob_copy(blob, ltv);
3185 blob_unref(blob);
3186 blob = ltv->vval.v_blob;
3187 }
3188
3189 // The index is for the previous byte.
3190 ++idxtv->vval.v_number;
3191 if (blob == NULL
3192 || idxtv->vval.v_number >= blob_len(blob))
3193 {
3194 // past the end of the blob, jump to "endfor"
Bram Moolenaar4c137212021-04-19 16:48:48 +02003195 ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
3196 may_restore_cmdmod(&ectx->ec_funclocal);
Bram Moolenaard551d6c2021-04-18 13:15:58 +02003197 }
3198 else
3199 {
3200 // Push the next byte from the blob.
3201 tv = STACK_TV_BOT(0);
3202 tv->v_type = VAR_NUMBER;
3203 tv->vval.v_number = blob_get(blob,
3204 idxtv->vval.v_number);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003205 ++ectx->ec_stack.ga_len;
Bram Moolenaard551d6c2021-04-18 13:15:58 +02003206 }
3207 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003208 else
3209 {
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01003210 semsg(_(e_for_loop_on_str_not_supported),
3211 vartype_name(ltv->v_type));
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003212 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003213 }
3214 }
3215 break;
3216
3217 // start of ":try" block
3218 case ISN_TRY:
3219 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01003220 trycmd_T *trycmd = NULL;
3221
Dominique Pelle5a9e5842021-07-24 19:32:12 +02003222 if (unlikely(GA_GROW(&ectx->ec_trystack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003223 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003224 trycmd = ((trycmd_T *)ectx->ec_trystack.ga_data)
3225 + ectx->ec_trystack.ga_len;
3226 ++ectx->ec_trystack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003227 ++trylevel;
Bram Moolenaar8d4be892021-02-13 18:33:02 +01003228 CLEAR_POINTER(trycmd);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003229 trycmd->tcd_frame_idx = ectx->ec_frame_idx;
3230 trycmd->tcd_stack_len = ectx->ec_stack.ga_len;
Bram Moolenaara91a7132021-03-25 21:12:15 +01003231 trycmd->tcd_catch_idx =
3232 iptr->isn_arg.try.try_ref->try_catch;
3233 trycmd->tcd_finally_idx =
3234 iptr->isn_arg.try.try_ref->try_finally;
3235 trycmd->tcd_endtry_idx =
3236 iptr->isn_arg.try.try_ref->try_endtry;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003237 }
3238 break;
3239
3240 case ISN_PUSHEXC:
3241 if (current_exception == NULL)
3242 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003243 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003244 iemsg("Evaluating catch while current_exception is NULL");
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003245 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003246 }
Dominique Pelle5a9e5842021-07-24 19:32:12 +02003247 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003248 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003249 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003250 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003251 tv->v_type = VAR_STRING;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003252 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003253 tv->vval.v_string = vim_strsave(
3254 (char_u *)current_exception->value);
3255 break;
3256
3257 case ISN_CATCH:
3258 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003259 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003260
Bram Moolenaar4c137212021-04-19 16:48:48 +02003261 may_restore_cmdmod(&ectx->ec_funclocal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003262 if (trystack->ga_len > 0)
3263 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01003264 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003265 + trystack->ga_len - 1;
3266 trycmd->tcd_caught = TRUE;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02003267 trycmd->tcd_did_throw = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003268 }
3269 did_emsg = got_int = did_throw = FALSE;
Bram Moolenaar1430cee2021-01-17 19:20:32 +01003270 force_abort = need_rethrow = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003271 catch_exception(current_exception);
3272 }
3273 break;
3274
Bram Moolenaarc150c092021-02-13 15:02:46 +01003275 case ISN_TRYCONT:
3276 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003277 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaarc150c092021-02-13 15:02:46 +01003278 trycont_T *trycont = &iptr->isn_arg.trycont;
3279 int i;
3280 trycmd_T *trycmd;
3281 int iidx = trycont->tct_where;
3282
3283 if (trystack->ga_len < trycont->tct_levels)
3284 {
3285 siemsg("TRYCONT: expected %d levels, found %d",
3286 trycont->tct_levels, trystack->ga_len);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003287 goto theend;
Bram Moolenaarc150c092021-02-13 15:02:46 +01003288 }
3289 // Make :endtry jump to any outer try block and the last
3290 // :endtry inside the loop to the loop start.
3291 for (i = trycont->tct_levels; i > 0; --i)
3292 {
3293 trycmd = ((trycmd_T *)trystack->ga_data)
3294 + trystack->ga_len - i;
Bram Moolenaar2e34c342021-03-14 12:13:33 +01003295 // Add one to tcd_cont to be able to jump to
3296 // instruction with index zero.
3297 trycmd->tcd_cont = iidx + 1;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01003298 iidx = trycmd->tcd_finally_idx == 0
3299 ? trycmd->tcd_endtry_idx : trycmd->tcd_finally_idx;
Bram Moolenaarc150c092021-02-13 15:02:46 +01003300 }
3301 // jump to :finally or :endtry of current try statement
Bram Moolenaar4c137212021-04-19 16:48:48 +02003302 ectx->ec_iidx = iidx;
Bram Moolenaarc150c092021-02-13 15:02:46 +01003303 }
3304 break;
3305
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01003306 case ISN_FINALLY:
3307 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003308 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01003309 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
3310 + trystack->ga_len - 1;
3311
3312 // Reset the index to avoid a return statement jumps here
3313 // again.
3314 trycmd->tcd_finally_idx = 0;
3315 break;
3316 }
3317
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003318 // end of ":try" block
3319 case ISN_ENDTRY:
3320 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003321 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003322
3323 if (trystack->ga_len > 0)
3324 {
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003325 trycmd_T *trycmd;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003326
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003327 --trystack->ga_len;
3328 --trylevel;
3329 trycmd = ((trycmd_T *)trystack->ga_data)
3330 + trystack->ga_len;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02003331 if (trycmd->tcd_did_throw)
3332 did_throw = TRUE;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01003333 if (trycmd->tcd_caught && current_exception != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003334 {
3335 // discard the exception
3336 if (caught_stack == current_exception)
3337 caught_stack = caught_stack->caught;
3338 discard_current_exception();
3339 }
3340
3341 if (trycmd->tcd_return)
Bram Moolenaard032f342020-07-18 18:13:02 +02003342 goto func_return;
Bram Moolenaard9d77892021-02-12 21:32:47 +01003343
Bram Moolenaar4c137212021-04-19 16:48:48 +02003344 while (ectx->ec_stack.ga_len > trycmd->tcd_stack_len)
Bram Moolenaard9d77892021-02-12 21:32:47 +01003345 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003346 --ectx->ec_stack.ga_len;
Bram Moolenaard9d77892021-02-12 21:32:47 +01003347 clear_tv(STACK_TV_BOT(0));
3348 }
Bram Moolenaar8d4be892021-02-13 18:33:02 +01003349 if (trycmd->tcd_cont != 0)
Bram Moolenaarc150c092021-02-13 15:02:46 +01003350 // handling :continue: jump to outer try block or
3351 // start of the loop
Bram Moolenaar4c137212021-04-19 16:48:48 +02003352 ectx->ec_iidx = trycmd->tcd_cont - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003353 }
3354 }
3355 break;
3356
3357 case ISN_THROW:
Bram Moolenaar8f81b222021-01-14 21:47:06 +01003358 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003359 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar1e021e62020-10-16 20:25:23 +02003360
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003361 if (trystack->ga_len == 0 && trylevel == 0 && emsg_silent)
3362 {
3363 // throwing an exception while using "silent!" causes
3364 // the function to abort but not display an error.
3365 tv = STACK_TV_BOT(-1);
3366 clear_tv(tv);
3367 tv->v_type = VAR_NUMBER;
3368 tv->vval.v_number = 0;
3369 goto done;
3370 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02003371 --ectx->ec_stack.ga_len;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003372 tv = STACK_TV_BOT(0);
3373 if (tv->vval.v_string == NULL
3374 || *skipwhite(tv->vval.v_string) == NUL)
3375 {
3376 vim_free(tv->vval.v_string);
3377 SOURCING_LNUM = iptr->isn_lnum;
3378 emsg(_(e_throw_with_empty_string));
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003379 goto theend;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003380 }
3381
3382 // Inside a "catch" we need to first discard the caught
3383 // exception.
3384 if (trystack->ga_len > 0)
3385 {
3386 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
3387 + trystack->ga_len - 1;
3388 if (trycmd->tcd_caught && current_exception != NULL)
3389 {
3390 // discard the exception
3391 if (caught_stack == current_exception)
3392 caught_stack = caught_stack->caught;
3393 discard_current_exception();
3394 trycmd->tcd_caught = FALSE;
3395 }
3396 }
3397
3398 if (throw_exception(tv->vval.v_string, ET_USER, NULL)
3399 == FAIL)
3400 {
3401 vim_free(tv->vval.v_string);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003402 goto theend;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003403 }
3404 did_throw = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003405 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003406 break;
3407
3408 // compare with special values
3409 case ISN_COMPAREBOOL:
3410 case ISN_COMPARESPECIAL:
3411 {
3412 typval_T *tv1 = STACK_TV_BOT(-2);
3413 typval_T *tv2 = STACK_TV_BOT(-1);
3414 varnumber_T arg1 = tv1->vval.v_number;
3415 varnumber_T arg2 = tv2->vval.v_number;
3416 int res;
3417
3418 switch (iptr->isn_arg.op.op_type)
3419 {
3420 case EXPR_EQUAL: res = arg1 == arg2; break;
3421 case EXPR_NEQUAL: res = arg1 != arg2; break;
3422 default: res = 0; break;
3423 }
3424
Bram Moolenaar4c137212021-04-19 16:48:48 +02003425 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003426 tv1->v_type = VAR_BOOL;
3427 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
3428 }
3429 break;
3430
3431 // Operation with two number arguments
3432 case ISN_OPNR:
3433 case ISN_COMPARENR:
3434 {
3435 typval_T *tv1 = STACK_TV_BOT(-2);
3436 typval_T *tv2 = STACK_TV_BOT(-1);
3437 varnumber_T arg1 = tv1->vval.v_number;
3438 varnumber_T arg2 = tv2->vval.v_number;
3439 varnumber_T res;
3440
3441 switch (iptr->isn_arg.op.op_type)
3442 {
3443 case EXPR_MULT: res = arg1 * arg2; break;
3444 case EXPR_DIV: res = arg1 / arg2; break;
3445 case EXPR_REM: res = arg1 % arg2; break;
3446 case EXPR_SUB: res = arg1 - arg2; break;
3447 case EXPR_ADD: res = arg1 + arg2; break;
3448
3449 case EXPR_EQUAL: res = arg1 == arg2; break;
3450 case EXPR_NEQUAL: res = arg1 != arg2; break;
3451 case EXPR_GREATER: res = arg1 > arg2; break;
3452 case EXPR_GEQUAL: res = arg1 >= arg2; break;
3453 case EXPR_SMALLER: res = arg1 < arg2; break;
3454 case EXPR_SEQUAL: res = arg1 <= arg2; break;
3455 default: res = 0; break;
3456 }
3457
Bram Moolenaar4c137212021-04-19 16:48:48 +02003458 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003459 if (iptr->isn_type == ISN_COMPARENR)
3460 {
3461 tv1->v_type = VAR_BOOL;
3462 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
3463 }
3464 else
3465 tv1->vval.v_number = res;
3466 }
3467 break;
3468
3469 // Computation with two float arguments
3470 case ISN_OPFLOAT:
3471 case ISN_COMPAREFLOAT:
Bram Moolenaara5d59532020-01-26 21:42:03 +01003472#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003473 {
3474 typval_T *tv1 = STACK_TV_BOT(-2);
3475 typval_T *tv2 = STACK_TV_BOT(-1);
3476 float_T arg1 = tv1->vval.v_float;
3477 float_T arg2 = tv2->vval.v_float;
3478 float_T res = 0;
3479 int cmp = FALSE;
3480
3481 switch (iptr->isn_arg.op.op_type)
3482 {
3483 case EXPR_MULT: res = arg1 * arg2; break;
3484 case EXPR_DIV: res = arg1 / arg2; break;
3485 case EXPR_SUB: res = arg1 - arg2; break;
3486 case EXPR_ADD: res = arg1 + arg2; break;
3487
3488 case EXPR_EQUAL: cmp = arg1 == arg2; break;
3489 case EXPR_NEQUAL: cmp = arg1 != arg2; break;
3490 case EXPR_GREATER: cmp = arg1 > arg2; break;
3491 case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
3492 case EXPR_SMALLER: cmp = arg1 < arg2; break;
3493 case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
3494 default: cmp = 0; break;
3495 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02003496 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003497 if (iptr->isn_type == ISN_COMPAREFLOAT)
3498 {
3499 tv1->v_type = VAR_BOOL;
3500 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
3501 }
3502 else
3503 tv1->vval.v_float = res;
3504 }
Bram Moolenaara5d59532020-01-26 21:42:03 +01003505#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003506 break;
3507
3508 case ISN_COMPARELIST:
3509 {
3510 typval_T *tv1 = STACK_TV_BOT(-2);
3511 typval_T *tv2 = STACK_TV_BOT(-1);
3512 list_T *arg1 = tv1->vval.v_list;
3513 list_T *arg2 = tv2->vval.v_list;
3514 int cmp = FALSE;
3515 int ic = iptr->isn_arg.op.op_ic;
3516
3517 switch (iptr->isn_arg.op.op_type)
3518 {
3519 case EXPR_EQUAL: cmp =
3520 list_equal(arg1, arg2, ic, FALSE); break;
3521 case EXPR_NEQUAL: cmp =
3522 !list_equal(arg1, arg2, ic, FALSE); break;
3523 case EXPR_IS: cmp = arg1 == arg2; break;
3524 case EXPR_ISNOT: cmp = arg1 != arg2; break;
3525 default: cmp = 0; break;
3526 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02003527 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003528 clear_tv(tv1);
3529 clear_tv(tv2);
3530 tv1->v_type = VAR_BOOL;
3531 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
3532 }
3533 break;
3534
3535 case ISN_COMPAREBLOB:
3536 {
3537 typval_T *tv1 = STACK_TV_BOT(-2);
3538 typval_T *tv2 = STACK_TV_BOT(-1);
3539 blob_T *arg1 = tv1->vval.v_blob;
3540 blob_T *arg2 = tv2->vval.v_blob;
3541 int cmp = FALSE;
3542
3543 switch (iptr->isn_arg.op.op_type)
3544 {
3545 case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break;
3546 case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break;
3547 case EXPR_IS: cmp = arg1 == arg2; break;
3548 case EXPR_ISNOT: cmp = arg1 != arg2; break;
3549 default: cmp = 0; break;
3550 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02003551 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003552 clear_tv(tv1);
3553 clear_tv(tv2);
3554 tv1->v_type = VAR_BOOL;
3555 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
3556 }
3557 break;
3558
3559 // TODO: handle separately
3560 case ISN_COMPARESTRING:
3561 case ISN_COMPAREDICT:
3562 case ISN_COMPAREFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003563 case ISN_COMPAREANY:
3564 {
3565 typval_T *tv1 = STACK_TV_BOT(-2);
3566 typval_T *tv2 = STACK_TV_BOT(-1);
Bram Moolenaar657137c2021-01-09 15:45:23 +01003567 exprtype_T exprtype = iptr->isn_arg.op.op_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003568 int ic = iptr->isn_arg.op.op_ic;
3569
Bram Moolenaareb26f432020-09-14 16:50:05 +02003570 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar657137c2021-01-09 15:45:23 +01003571 typval_compare(tv1, tv2, exprtype, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003572 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003573 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003574 }
3575 break;
3576
3577 case ISN_ADDLIST:
3578 case ISN_ADDBLOB:
3579 {
3580 typval_T *tv1 = STACK_TV_BOT(-2);
3581 typval_T *tv2 = STACK_TV_BOT(-1);
3582
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003583 // add two lists or blobs
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003584 if (iptr->isn_type == ISN_ADDLIST)
3585 eval_addlist(tv1, tv2);
3586 else
3587 eval_addblob(tv1, tv2);
3588 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003589 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003590 }
3591 break;
3592
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003593 case ISN_LISTAPPEND:
3594 {
3595 typval_T *tv1 = STACK_TV_BOT(-2);
3596 typval_T *tv2 = STACK_TV_BOT(-1);
3597 list_T *l = tv1->vval.v_list;
3598
3599 // add an item to a list
3600 if (l == NULL)
3601 {
3602 SOURCING_LNUM = iptr->isn_lnum;
3603 emsg(_(e_cannot_add_to_null_list));
3604 goto on_error;
3605 }
3606 if (list_append_tv(l, tv2) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003607 goto theend;
Bram Moolenaar955347c2020-10-19 23:01:46 +02003608 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003609 --ectx->ec_stack.ga_len;
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003610 }
3611 break;
3612
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02003613 case ISN_BLOBAPPEND:
3614 {
3615 typval_T *tv1 = STACK_TV_BOT(-2);
3616 typval_T *tv2 = STACK_TV_BOT(-1);
3617 blob_T *b = tv1->vval.v_blob;
3618 int error = FALSE;
3619 varnumber_T n;
3620
3621 // add a number to a blob
3622 if (b == NULL)
3623 {
3624 SOURCING_LNUM = iptr->isn_lnum;
3625 emsg(_(e_cannot_add_to_null_blob));
3626 goto on_error;
3627 }
3628 n = tv_get_number_chk(tv2, &error);
3629 if (error)
3630 goto on_error;
3631 ga_append(&b->bv_ga, (int)n);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003632 --ectx->ec_stack.ga_len;
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02003633 }
3634 break;
3635
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003636 // Computation with two arguments of unknown type
3637 case ISN_OPANY:
3638 {
3639 typval_T *tv1 = STACK_TV_BOT(-2);
3640 typval_T *tv2 = STACK_TV_BOT(-1);
3641 varnumber_T n1, n2;
3642#ifdef FEAT_FLOAT
3643 float_T f1 = 0, f2 = 0;
3644#endif
3645 int error = FALSE;
3646
3647 if (iptr->isn_arg.op.op_type == EXPR_ADD)
3648 {
3649 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
3650 {
3651 eval_addlist(tv1, tv2);
3652 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003653 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003654 break;
3655 }
3656 else if (tv1->v_type == VAR_BLOB
3657 && tv2->v_type == VAR_BLOB)
3658 {
3659 eval_addblob(tv1, tv2);
3660 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003661 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003662 break;
3663 }
3664 }
3665#ifdef FEAT_FLOAT
3666 if (tv1->v_type == VAR_FLOAT)
3667 {
3668 f1 = tv1->vval.v_float;
3669 n1 = 0;
3670 }
3671 else
3672#endif
3673 {
Bram Moolenaarf665e972020-12-05 19:17:16 +01003674 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003675 n1 = tv_get_number_chk(tv1, &error);
3676 if (error)
Bram Moolenaard032f342020-07-18 18:13:02 +02003677 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003678#ifdef FEAT_FLOAT
3679 if (tv2->v_type == VAR_FLOAT)
3680 f1 = n1;
3681#endif
3682 }
3683#ifdef FEAT_FLOAT
3684 if (tv2->v_type == VAR_FLOAT)
3685 {
3686 f2 = tv2->vval.v_float;
3687 n2 = 0;
3688 }
3689 else
3690#endif
3691 {
3692 n2 = tv_get_number_chk(tv2, &error);
3693 if (error)
Bram Moolenaard032f342020-07-18 18:13:02 +02003694 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003695#ifdef FEAT_FLOAT
3696 if (tv1->v_type == VAR_FLOAT)
3697 f2 = n2;
3698#endif
3699 }
3700#ifdef FEAT_FLOAT
3701 // if there is a float on either side the result is a float
3702 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
3703 {
3704 switch (iptr->isn_arg.op.op_type)
3705 {
3706 case EXPR_MULT: f1 = f1 * f2; break;
3707 case EXPR_DIV: f1 = f1 / f2; break;
3708 case EXPR_SUB: f1 = f1 - f2; break;
3709 case EXPR_ADD: f1 = f1 + f2; break;
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003710 default: SOURCING_LNUM = iptr->isn_lnum;
3711 emsg(_(e_modulus));
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02003712 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003713 }
3714 clear_tv(tv1);
3715 clear_tv(tv2);
3716 tv1->v_type = VAR_FLOAT;
3717 tv1->vval.v_float = f1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003718 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003719 }
3720 else
3721#endif
3722 {
Bram Moolenaarb1f28572021-01-21 13:03:20 +01003723 int failed = FALSE;
3724
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003725 switch (iptr->isn_arg.op.op_type)
3726 {
3727 case EXPR_MULT: n1 = n1 * n2; break;
Bram Moolenaarb1f28572021-01-21 13:03:20 +01003728 case EXPR_DIV: n1 = num_divide(n1, n2, &failed);
3729 if (failed)
Bram Moolenaar99880f92021-01-20 21:23:14 +01003730 goto on_error;
3731 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003732 case EXPR_SUB: n1 = n1 - n2; break;
3733 case EXPR_ADD: n1 = n1 + n2; break;
Bram Moolenaarb1f28572021-01-21 13:03:20 +01003734 default: n1 = num_modulus(n1, n2, &failed);
3735 if (failed)
Bram Moolenaar99880f92021-01-20 21:23:14 +01003736 goto on_error;
3737 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003738 }
3739 clear_tv(tv1);
3740 clear_tv(tv2);
3741 tv1->v_type = VAR_NUMBER;
3742 tv1->vval.v_number = n1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003743 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003744 }
3745 }
3746 break;
3747
3748 case ISN_CONCAT:
3749 {
3750 char_u *str1 = STACK_TV_BOT(-2)->vval.v_string;
3751 char_u *str2 = STACK_TV_BOT(-1)->vval.v_string;
3752 char_u *res;
3753
3754 res = concat_str(str1, str2);
3755 clear_tv(STACK_TV_BOT(-2));
3756 clear_tv(STACK_TV_BOT(-1));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003757 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003758 STACK_TV_BOT(-1)->vval.v_string = res;
3759 }
3760 break;
3761
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003762 case ISN_STRINDEX:
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003763 case ISN_STRSLICE:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003764 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003765 int is_slice = iptr->isn_type == ISN_STRSLICE;
3766 varnumber_T n1 = 0, n2;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003767 char_u *res;
3768
3769 // string index: string is at stack-2, index at stack-1
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003770 // string slice: string is at stack-3, first index at
3771 // stack-2, second index at stack-1
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003772 if (is_slice)
3773 {
3774 tv = STACK_TV_BOT(-2);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003775 n1 = tv->vval.v_number;
3776 }
3777
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003778 tv = STACK_TV_BOT(-1);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003779 n2 = tv->vval.v_number;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003780
Bram Moolenaar4c137212021-04-19 16:48:48 +02003781 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003782 tv = STACK_TV_BOT(-1);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003783 if (is_slice)
3784 // Slice: Select the characters from the string
Bram Moolenaar6601b622021-01-13 21:47:15 +01003785 res = string_slice(tv->vval.v_string, n1, n2, FALSE);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003786 else
3787 // Index: The resulting variable is a string of a
Bram Moolenaar0289a092021-03-14 18:40:19 +01003788 // single character (including composing characters).
3789 // If the index is too big or negative the result is
3790 // empty.
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003791 res = char_from_string(tv->vval.v_string, n2);
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003792 vim_free(tv->vval.v_string);
3793 tv->vval.v_string = res;
3794 }
3795 break;
3796
3797 case ISN_LISTINDEX:
Bram Moolenaared591872020-08-15 22:14:53 +02003798 case ISN_LISTSLICE:
Bram Moolenaarcfc30232021-04-11 20:26:34 +02003799 case ISN_BLOBINDEX:
3800 case ISN_BLOBSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003801 {
Bram Moolenaarcfc30232021-04-11 20:26:34 +02003802 int is_slice = iptr->isn_type == ISN_LISTSLICE
3803 || iptr->isn_type == ISN_BLOBSLICE;
3804 int is_blob = iptr->isn_type == ISN_BLOBINDEX
3805 || iptr->isn_type == ISN_BLOBSLICE;
Bram Moolenaared591872020-08-15 22:14:53 +02003806 varnumber_T n1, n2;
Bram Moolenaarcfc30232021-04-11 20:26:34 +02003807 typval_T *val_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003808
3809 // list index: list is at stack-2, index at stack-1
Bram Moolenaared591872020-08-15 22:14:53 +02003810 // list slice: list is at stack-3, indexes at stack-2 and
3811 // stack-1
Bram Moolenaarcfc30232021-04-11 20:26:34 +02003812 // Same for blob.
3813 val_tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003814
3815 tv = STACK_TV_BOT(-1);
Bram Moolenaared591872020-08-15 22:14:53 +02003816 n1 = n2 = tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003817 clear_tv(tv);
Bram Moolenaared591872020-08-15 22:14:53 +02003818
3819 if (is_slice)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003820 {
Bram Moolenaared591872020-08-15 22:14:53 +02003821 tv = STACK_TV_BOT(-2);
Bram Moolenaared591872020-08-15 22:14:53 +02003822 n1 = tv->vval.v_number;
3823 clear_tv(tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003824 }
Bram Moolenaared591872020-08-15 22:14:53 +02003825
Bram Moolenaar4c137212021-04-19 16:48:48 +02003826 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaar435d8972020-07-05 16:42:13 +02003827 tv = STACK_TV_BOT(-1);
Bram Moolenaar1d634542020-08-18 13:41:50 +02003828 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcfc30232021-04-11 20:26:34 +02003829 if (is_blob)
3830 {
3831 if (blob_slice_or_index(val_tv->vval.v_blob, is_slice,
3832 n1, n2, FALSE, tv) == FAIL)
3833 goto on_error;
3834 }
3835 else
3836 {
3837 if (list_slice_or_index(val_tv->vval.v_list, is_slice,
3838 n1, n2, FALSE, tv, TRUE) == FAIL)
3839 goto on_error;
3840 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003841 }
3842 break;
3843
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003844 case ISN_ANYINDEX:
3845 case ISN_ANYSLICE:
3846 {
3847 int is_slice = iptr->isn_type == ISN_ANYSLICE;
3848 typval_T *var1, *var2;
3849 int res;
3850
3851 // index: composite is at stack-2, index at stack-1
3852 // slice: composite is at stack-3, indexes at stack-2 and
3853 // stack-1
3854 tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
Bram Moolenaar3affe7a2020-08-18 20:34:13 +02003855 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003856 if (check_can_index(tv, TRUE, TRUE) == FAIL)
3857 goto on_error;
3858 var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1);
3859 var2 = is_slice ? STACK_TV_BOT(-1) : NULL;
Bram Moolenaar6601b622021-01-13 21:47:15 +01003860 res = eval_index_inner(tv, is_slice, var1, var2,
3861 FALSE, NULL, -1, TRUE);
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003862 clear_tv(var1);
3863 if (is_slice)
3864 clear_tv(var2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003865 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003866 if (res == FAIL)
3867 goto on_error;
3868 }
3869 break;
3870
Bram Moolenaar9af78762020-06-16 11:34:42 +02003871 case ISN_SLICE:
3872 {
3873 list_T *list;
3874 int count = iptr->isn_arg.number;
3875
Bram Moolenaarc5b1c202020-06-18 22:43:27 +02003876 // type will have been checked to be a list
Bram Moolenaar9af78762020-06-16 11:34:42 +02003877 tv = STACK_TV_BOT(-1);
Bram Moolenaar9af78762020-06-16 11:34:42 +02003878 list = tv->vval.v_list;
3879
3880 // no error for short list, expect it to be checked earlier
3881 if (list != NULL && list->lv_len >= count)
3882 {
3883 list_T *newlist = list_slice(list,
3884 count, list->lv_len - 1);
3885
3886 if (newlist != NULL)
3887 {
3888 list_unref(list);
3889 tv->vval.v_list = newlist;
3890 ++newlist->lv_refcount;
3891 }
3892 }
3893 }
3894 break;
3895
Bram Moolenaar47a519a2020-06-14 23:05:10 +02003896 case ISN_GETITEM:
3897 {
3898 listitem_T *li;
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02003899 getitem_T *gi = &iptr->isn_arg.getitem;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02003900
Bram Moolenaarc785b9a2020-06-19 18:34:15 +02003901 // Get list item: list is at stack-1, push item.
3902 // List type and length is checked for when compiling.
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02003903 tv = STACK_TV_BOT(-1 - gi->gi_with_op);
3904 li = list_find(tv->vval.v_list, gi->gi_index);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02003905
Dominique Pelle5a9e5842021-07-24 19:32:12 +02003906 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003907 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003908 ++ectx->ec_stack.ga_len;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02003909 copy_tv(&li->li_tv, STACK_TV_BOT(-1));
Bram Moolenaarf785aa12021-02-11 21:19:34 +01003910
3911 // Useful when used in unpack assignment. Reset at
3912 // ISN_DROP.
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02003913 ectx->ec_where.wt_index = gi->gi_index + 1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003914 ectx->ec_where.wt_variable = TRUE;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02003915 }
3916 break;
3917
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003918 case ISN_MEMBER:
3919 {
3920 dict_T *dict;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003921 char_u *key;
3922 dictitem_T *di;
Bram Moolenaar50788ef2020-07-05 16:51:26 +02003923 typval_T temp_tv;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003924
3925 // dict member: dict is at stack-2, key at stack-1
3926 tv = STACK_TV_BOT(-2);
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02003927 // no need to check for VAR_DICT, CHECKTYPE will check.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003928 dict = tv->vval.v_dict;
3929
3930 tv = STACK_TV_BOT(-1);
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02003931 // no need to check for VAR_STRING, 2STRING will check.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003932 key = tv->vval.v_string;
Bram Moolenaar086fc9a2020-10-30 18:33:02 +01003933 if (key == NULL)
3934 key = (char_u *)"";
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02003935
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003936 if ((di = dict_find(dict, key, -1)) == NULL)
3937 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003938 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003939 semsg(_(e_dictkey), key);
Bram Moolenaar4029cab2020-12-05 18:13:27 +01003940
3941 // If :silent! is used we will continue, make sure the
3942 // stack contents makes sense.
3943 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003944 --ectx->ec_stack.ga_len;
Bram Moolenaar4029cab2020-12-05 18:13:27 +01003945 tv = STACK_TV_BOT(-1);
3946 clear_tv(tv);
3947 tv->v_type = VAR_NUMBER;
3948 tv->vval.v_number = 0;
Bram Moolenaaraf0df472020-12-02 20:51:22 +01003949 goto on_fatal_error;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003950 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003951 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003952 --ectx->ec_stack.ga_len;
Bram Moolenaaraf0df472020-12-02 20:51:22 +01003953 // Clear the dict only after getting the item, to avoid
3954 // that it makes the item invalid.
Bram Moolenaar50788ef2020-07-05 16:51:26 +02003955 tv = STACK_TV_BOT(-1);
3956 temp_tv = *tv;
3957 copy_tv(&di->di_tv, tv);
3958 clear_tv(&temp_tv);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003959 }
3960 break;
3961
3962 // dict member with string key
3963 case ISN_STRINGMEMBER:
3964 {
3965 dict_T *dict;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003966 dictitem_T *di;
Bram Moolenaarfb9d5c52020-07-04 19:19:43 +02003967 typval_T temp_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003968
3969 tv = STACK_TV_BOT(-1);
3970 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
3971 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003972 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003973 emsg(_(e_dictreq));
Bram Moolenaard032f342020-07-18 18:13:02 +02003974 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003975 }
3976 dict = tv->vval.v_dict;
3977
3978 if ((di = dict_find(dict, iptr->isn_arg.string, -1))
3979 == NULL)
3980 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003981 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003982 semsg(_(e_dictkey), iptr->isn_arg.string);
Bram Moolenaard032f342020-07-18 18:13:02 +02003983 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003984 }
Bram Moolenaarfb9d5c52020-07-04 19:19:43 +02003985 // Clear the dict after getting the item, to avoid that it
3986 // make the item invalid.
3987 temp_tv = *tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003988 copy_tv(&di->di_tv, tv);
Bram Moolenaarfb9d5c52020-07-04 19:19:43 +02003989 clear_tv(&temp_tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003990 }
3991 break;
3992
3993 case ISN_NEGATENR:
3994 tv = STACK_TV_BOT(-1);
Bram Moolenaarc58164c2020-03-29 18:40:30 +02003995 if (tv->v_type != VAR_NUMBER
3996#ifdef FEAT_FLOAT
3997 && tv->v_type != VAR_FLOAT
3998#endif
3999 )
4000 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004001 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaare29a27f2021-07-20 21:07:36 +02004002 emsg(_(e_number_expected));
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004003 goto on_error;
Bram Moolenaarc58164c2020-03-29 18:40:30 +02004004 }
4005#ifdef FEAT_FLOAT
4006 if (tv->v_type == VAR_FLOAT)
4007 tv->vval.v_float = -tv->vval.v_float;
4008 else
4009#endif
4010 tv->vval.v_number = -tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004011 break;
4012
4013 case ISN_CHECKNR:
4014 {
4015 int error = FALSE;
4016
4017 tv = STACK_TV_BOT(-1);
Bram Moolenaar3affe7a2020-08-18 20:34:13 +02004018 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004019 if (check_not_string(tv) == FAIL)
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004020 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004021 (void)tv_get_number_chk(tv, &error);
4022 if (error)
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004023 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004024 }
4025 break;
4026
4027 case ISN_CHECKTYPE:
4028 {
4029 checktype_T *ct = &iptr->isn_arg.type;
4030
Bram Moolenaarb3005ce2021-01-22 17:51:06 +01004031 tv = STACK_TV_BOT((int)ct->ct_off);
Bram Moolenaar5e654232020-09-16 15:22:00 +02004032 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004033 if (!ectx->ec_where.wt_variable)
4034 ectx->ec_where.wt_index = ct->ct_arg_idx;
4035 if (check_typval_type(ct->ct_type, tv, ectx->ec_where)
4036 == FAIL)
Bram Moolenaar5e654232020-09-16 15:22:00 +02004037 goto on_error;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004038 if (!ectx->ec_where.wt_variable)
4039 ectx->ec_where.wt_index = 0;
Bram Moolenaar5e654232020-09-16 15:22:00 +02004040
4041 // number 0 is FALSE, number 1 is TRUE
4042 if (tv->v_type == VAR_NUMBER
4043 && ct->ct_type->tt_type == VAR_BOOL
4044 && (tv->vval.v_number == 0
4045 || tv->vval.v_number == 1))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004046 {
Bram Moolenaar5e654232020-09-16 15:22:00 +02004047 tv->v_type = VAR_BOOL;
4048 tv->vval.v_number = tv->vval.v_number
Bram Moolenaardadaddd2020-09-12 19:11:23 +02004049 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004050 }
4051 }
4052 break;
4053
Bram Moolenaar9af78762020-06-16 11:34:42 +02004054 case ISN_CHECKLEN:
4055 {
4056 int min_len = iptr->isn_arg.checklen.cl_min_len;
4057 list_T *list = NULL;
4058
4059 tv = STACK_TV_BOT(-1);
4060 if (tv->v_type == VAR_LIST)
4061 list = tv->vval.v_list;
4062 if (list == NULL || list->lv_len < min_len
4063 || (list->lv_len > min_len
4064 && !iptr->isn_arg.checklen.cl_more_OK))
4065 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004066 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004067 semsg(_(e_expected_nr_items_but_got_nr),
Bram Moolenaar9af78762020-06-16 11:34:42 +02004068 min_len, list == NULL ? 0 : list->lv_len);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004069 goto on_error;
Bram Moolenaar9af78762020-06-16 11:34:42 +02004070 }
4071 }
4072 break;
4073
Bram Moolenaaraa210a32021-01-02 15:41:03 +01004074 case ISN_SETTYPE:
4075 {
4076 checktype_T *ct = &iptr->isn_arg.type;
4077
4078 tv = STACK_TV_BOT(-1);
4079 if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
4080 {
4081 free_type(tv->vval.v_dict->dv_type);
4082 tv->vval.v_dict->dv_type = alloc_type(ct->ct_type);
4083 }
4084 else if (tv->v_type == VAR_LIST && tv->vval.v_list != NULL)
4085 {
4086 free_type(tv->vval.v_list->lv_type);
4087 tv->vval.v_list->lv_type = alloc_type(ct->ct_type);
4088 }
4089 }
4090 break;
4091
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004092 case ISN_2BOOL:
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004093 case ISN_COND2BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004094 {
4095 int n;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004096 int error = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004097
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004098 if (iptr->isn_type == ISN_2BOOL)
4099 {
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02004100 tv = STACK_TV_BOT(iptr->isn_arg.tobool.offset);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004101 n = tv2bool(tv);
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02004102 if (iptr->isn_arg.tobool.invert)
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004103 n = !n;
4104 }
4105 else
4106 {
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02004107 tv = STACK_TV_BOT(-1);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004108 SOURCING_LNUM = iptr->isn_lnum;
4109 n = tv_get_bool_chk(tv, &error);
4110 if (error)
4111 goto on_error;
4112 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004113 clear_tv(tv);
4114 tv->v_type = VAR_BOOL;
4115 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
4116 }
4117 break;
4118
4119 case ISN_2STRING:
Bram Moolenaar418f1df2020-08-12 21:34:49 +02004120 case ISN_2STRING_ANY:
Bram Moolenaar0acbf5a2021-01-05 20:58:25 +01004121 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02004122 if (do_2string(STACK_TV_BOT(iptr->isn_arg.tostring.offset),
4123 iptr->isn_type == ISN_2STRING_ANY,
4124 iptr->isn_arg.tostring.tolerant) == FAIL)
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01004125 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004126 break;
4127
Bram Moolenaar08597872020-12-10 19:43:40 +01004128 case ISN_RANGE:
4129 {
4130 exarg_T ea;
4131 char *errormsg;
4132
Bram Moolenaarece0b872021-01-08 20:40:45 +01004133 ea.line2 = 0;
Bram Moolenaard1510ee2021-01-04 16:15:58 +01004134 ea.addr_count = 0;
Bram Moolenaar08597872020-12-10 19:43:40 +01004135 ea.addr_type = ADDR_LINES;
4136 ea.cmd = iptr->isn_arg.string;
Bram Moolenaarece0b872021-01-08 20:40:45 +01004137 ea.skip = FALSE;
Bram Moolenaar08597872020-12-10 19:43:40 +01004138 if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
Bram Moolenaarece0b872021-01-08 20:40:45 +01004139 goto on_error;
Bram Moolenaara28639e2021-01-19 22:48:09 +01004140
Dominique Pelle5a9e5842021-07-24 19:32:12 +02004141 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004142 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004143 ++ectx->ec_stack.ga_len;
Bram Moolenaara28639e2021-01-19 22:48:09 +01004144 tv = STACK_TV_BOT(-1);
4145 tv->v_type = VAR_NUMBER;
4146 tv->v_lock = 0;
Bram Moolenaar08597872020-12-10 19:43:40 +01004147 if (ea.addr_count == 0)
4148 tv->vval.v_number = curwin->w_cursor.lnum;
4149 else
4150 tv->vval.v_number = ea.line2;
4151 }
4152 break;
4153
Bram Moolenaarc3516f72020-09-08 22:45:35 +02004154 case ISN_PUT:
4155 {
4156 int regname = iptr->isn_arg.put.put_regname;
4157 linenr_T lnum = iptr->isn_arg.put.put_lnum;
4158 char_u *expr = NULL;
4159 int dir = FORWARD;
4160
Bram Moolenaar08597872020-12-10 19:43:40 +01004161 if (lnum < -2)
4162 {
4163 // line number was put on the stack by ISN_RANGE
4164 tv = STACK_TV_BOT(-1);
4165 curwin->w_cursor.lnum = tv->vval.v_number;
4166 if (lnum == LNUM_VARIABLE_RANGE_ABOVE)
4167 dir = BACKWARD;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004168 --ectx->ec_stack.ga_len;
Bram Moolenaar08597872020-12-10 19:43:40 +01004169 }
4170 else if (lnum == -2)
Bram Moolenaarc3516f72020-09-08 22:45:35 +02004171 // :put! above cursor
4172 dir = BACKWARD;
4173 else if (lnum >= 0)
4174 curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum;
Bram Moolenaara28639e2021-01-19 22:48:09 +01004175
4176 if (regname == '=')
4177 {
4178 tv = STACK_TV_BOT(-1);
4179 if (tv->v_type == VAR_STRING)
4180 expr = tv->vval.v_string;
4181 else
4182 {
4183 expr = typval2string(tv, TRUE); // allocates value
4184 clear_tv(tv);
4185 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004186 --ectx->ec_stack.ga_len;
Bram Moolenaara28639e2021-01-19 22:48:09 +01004187 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02004188 check_cursor();
4189 do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
4190 vim_free(expr);
4191 }
4192 break;
4193
Bram Moolenaar02194d22020-10-24 23:08:38 +02004194 case ISN_CMDMOD:
Bram Moolenaar4c137212021-04-19 16:48:48 +02004195 ectx->ec_funclocal.floc_save_cmdmod = cmdmod;
4196 ectx->ec_funclocal.floc_restore_cmdmod = TRUE;
4197 ectx->ec_funclocal.floc_restore_cmdmod_stacklen =
4198 ectx->ec_stack.ga_len;
Bram Moolenaar02194d22020-10-24 23:08:38 +02004199 cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod;
4200 apply_cmdmod(&cmdmod);
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02004201 break;
4202
Bram Moolenaar02194d22020-10-24 23:08:38 +02004203 case ISN_CMDMOD_REV:
4204 // filter regprog is owned by the instruction, don't free it
4205 cmdmod.cmod_filter_regmatch.regprog = NULL;
4206 undo_cmdmod(&cmdmod);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004207 cmdmod = ectx->ec_funclocal.floc_save_cmdmod;
4208 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02004209 break;
4210
Bram Moolenaar792f7862020-11-23 08:31:18 +01004211 case ISN_UNPACK:
4212 {
4213 int count = iptr->isn_arg.unpack.unp_count;
4214 int semicolon = iptr->isn_arg.unpack.unp_semicolon;
4215 list_T *l;
4216 listitem_T *li;
4217 int i;
4218
4219 // Check there is a valid list to unpack.
4220 tv = STACK_TV_BOT(-1);
4221 if (tv->v_type != VAR_LIST)
4222 {
4223 SOURCING_LNUM = iptr->isn_lnum;
4224 emsg(_(e_for_argument_must_be_sequence_of_lists));
4225 goto on_error;
4226 }
4227 l = tv->vval.v_list;
4228 if (l == NULL
4229 || l->lv_len < (semicolon ? count - 1 : count))
4230 {
4231 SOURCING_LNUM = iptr->isn_lnum;
4232 emsg(_(e_list_value_does_not_have_enough_items));
4233 goto on_error;
4234 }
4235 else if (!semicolon && l->lv_len > count)
4236 {
4237 SOURCING_LNUM = iptr->isn_lnum;
4238 emsg(_(e_list_value_has_more_items_than_targets));
4239 goto on_error;
4240 }
4241
4242 CHECK_LIST_MATERIALIZE(l);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02004243 if (unlikely(GA_GROW(&ectx->ec_stack, count - 1) == FAIL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004244 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004245 ectx->ec_stack.ga_len += count - 1;
Bram Moolenaar792f7862020-11-23 08:31:18 +01004246
4247 // Variable after semicolon gets a list with the remaining
4248 // items.
4249 if (semicolon)
4250 {
4251 list_T *rem_list =
4252 list_alloc_with_items(l->lv_len - count + 1);
4253
4254 if (rem_list == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004255 goto theend;
Bram Moolenaar792f7862020-11-23 08:31:18 +01004256 tv = STACK_TV_BOT(-count);
4257 tv->vval.v_list = rem_list;
4258 ++rem_list->lv_refcount;
4259 tv->v_lock = 0;
4260 li = l->lv_first;
4261 for (i = 0; i < count - 1; ++i)
4262 li = li->li_next;
4263 for (i = 0; li != NULL; ++i)
4264 {
4265 list_set_item(rem_list, i, &li->li_tv);
4266 li = li->li_next;
4267 }
4268 --count;
4269 }
4270
4271 // Produce the values in reverse order, first item last.
4272 li = l->lv_first;
4273 for (i = 0; i < count; ++i)
4274 {
4275 tv = STACK_TV_BOT(-i - 1);
4276 copy_tv(&li->li_tv, tv);
4277 li = li->li_next;
4278 }
4279
4280 list_unref(l);
4281 }
4282 break;
4283
Bram Moolenaarb2049902021-01-24 12:53:53 +01004284 case ISN_PROF_START:
4285 case ISN_PROF_END:
4286 {
Bram Moolenaarf002a412021-01-24 13:34:18 +01004287#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01004288 funccall_T cookie;
4289 ufunc_T *cur_ufunc =
4290 (((dfunc_T *)def_functions.ga_data)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02004291 + ectx->ec_dfunc_idx)->df_ufunc;
Bram Moolenaarb2049902021-01-24 12:53:53 +01004292
4293 cookie.func = cur_ufunc;
4294 if (iptr->isn_type == ISN_PROF_START)
4295 {
4296 func_line_start(&cookie, iptr->isn_lnum);
4297 // if we get here the instruction is executed
4298 func_line_exec(&cookie);
4299 }
4300 else
4301 func_line_end(&cookie);
Bram Moolenaarf002a412021-01-24 13:34:18 +01004302#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01004303 }
4304 break;
4305
Bram Moolenaare99d4222021-06-13 14:01:26 +02004306 case ISN_DEBUG:
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02004307 handle_debug(iptr, ectx);
Bram Moolenaare99d4222021-06-13 14:01:26 +02004308 break;
4309
Bram Moolenaar389df252020-07-09 21:20:47 +02004310 case ISN_SHUFFLE:
4311 {
Bram Moolenaar792f7862020-11-23 08:31:18 +01004312 typval_T tmp_tv;
4313 int item = iptr->isn_arg.shuffle.shfl_item;
4314 int up = iptr->isn_arg.shuffle.shfl_up;
Bram Moolenaar389df252020-07-09 21:20:47 +02004315
4316 tmp_tv = *STACK_TV_BOT(-item);
4317 for ( ; up > 0 && item > 1; --up)
4318 {
4319 *STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1);
4320 --item;
4321 }
4322 *STACK_TV_BOT(-item) = tmp_tv;
4323 }
4324 break;
4325
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004326 case ISN_DROP:
Bram Moolenaar4c137212021-04-19 16:48:48 +02004327 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004328 clear_tv(STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02004329 ectx->ec_where.wt_index = 0;
4330 ectx->ec_where.wt_variable = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004331 break;
4332 }
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004333 continue;
4334
Bram Moolenaard032f342020-07-18 18:13:02 +02004335func_return:
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02004336 // Restore previous function. If the frame pointer is where we started
4337 // then there is none and we are done.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004338 if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
Bram Moolenaard032f342020-07-18 18:13:02 +02004339 goto done;
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02004340
Bram Moolenaar4c137212021-04-19 16:48:48 +02004341 if (func_return(ectx) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02004342 // only fails when out of memory
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004343 goto theend;
Bram Moolenaarc7db5772020-07-21 20:55:50 +02004344 continue;
Bram Moolenaard032f342020-07-18 18:13:02 +02004345
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004346on_error:
Bram Moolenaaraf0df472020-12-02 20:51:22 +01004347 // Jump here for an error that does not require aborting execution.
Bram Moolenaar56602ba2020-12-05 21:22:08 +01004348 // If "emsg_silent" is set then ignore the error, unless it was set
4349 // when calling the function.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004350 if (did_emsg_cumul + did_emsg == ectx->ec_did_emsg_before
Bram Moolenaar56602ba2020-12-05 21:22:08 +01004351 && emsg_silent && did_emsg_def == 0)
Bram Moolenaarf9041332021-01-21 19:41:16 +01004352 {
4353 // If a sequence of instructions causes an error while ":silent!"
4354 // was used, restore the stack length and jump ahead to restoring
4355 // the cmdmod.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004356 if (ectx->ec_funclocal.floc_restore_cmdmod)
Bram Moolenaarf9041332021-01-21 19:41:16 +01004357 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004358 while (ectx->ec_stack.ga_len
4359 > ectx->ec_funclocal.floc_restore_cmdmod_stacklen)
Bram Moolenaarf9041332021-01-21 19:41:16 +01004360 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004361 --ectx->ec_stack.ga_len;
Bram Moolenaarf9041332021-01-21 19:41:16 +01004362 clear_tv(STACK_TV_BOT(0));
4363 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004364 while (ectx->ec_instr[ectx->ec_iidx].isn_type != ISN_CMDMOD_REV)
4365 ++ectx->ec_iidx;
Bram Moolenaarf9041332021-01-21 19:41:16 +01004366 }
Bram Moolenaarcd030c42020-10-30 21:49:40 +01004367 continue;
Bram Moolenaarf9041332021-01-21 19:41:16 +01004368 }
Bram Moolenaaraf0df472020-12-02 20:51:22 +01004369on_fatal_error:
4370 // Jump here for an error that messes up the stack.
Bram Moolenaar171fb922020-10-28 16:54:47 +01004371 // If we are not inside a try-catch started here, abort execution.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004372 if (trylevel <= ectx->ec_trylevel_at_start)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004373 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004374 }
4375
4376done:
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004377 ret = OK;
4378theend:
4379 ectx->ec_trylevel_at_start = save_trylevel_at_start;
4380 return ret;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004381}
4382
4383/*
Bram Moolenaarf18332f2021-05-07 17:55:55 +02004384 * Execute the instructions from a VAR_INSTR typeval and put the result in
4385 * "rettv".
4386 * Return OK or FAIL.
4387 */
4388 int
4389exe_typval_instr(typval_T *tv, typval_T *rettv)
4390{
4391 ectx_T *ectx = tv->vval.v_instr->instr_ectx;
4392 isn_T *save_instr = ectx->ec_instr;
4393 int save_iidx = ectx->ec_iidx;
4394 int res;
4395
4396 ectx->ec_instr = tv->vval.v_instr->instr_instr;
4397 res = exec_instructions(ectx);
4398 if (res == OK)
4399 {
4400 *rettv = *STACK_TV_BOT(-1);
4401 --ectx->ec_stack.ga_len;
4402 }
4403
4404 ectx->ec_instr = save_instr;
4405 ectx->ec_iidx = save_iidx;
4406
4407 return res;
4408}
4409
4410/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02004411 * Execute the instructions from an ISN_SUBSTITUTE command, which are in
4412 * "substitute_instr".
4413 */
4414 char_u *
4415exe_substitute_instr(void)
4416{
4417 ectx_T *ectx = substitute_instr->subs_ectx;
4418 isn_T *save_instr = ectx->ec_instr;
4419 int save_iidx = ectx->ec_iidx;
4420 char_u *res;
4421
4422 ectx->ec_instr = substitute_instr->subs_instr;
4423 if (exec_instructions(ectx) == OK)
Bram Moolenaar90193e62021-04-04 20:49:50 +02004424 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004425 typval_T *tv = STACK_TV_BOT(-1);
4426
Bram Moolenaar27523602021-06-05 21:36:19 +02004427 res = typval2string(tv, TRUE);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004428 --ectx->ec_stack.ga_len;
4429 clear_tv(tv);
Bram Moolenaar90193e62021-04-04 20:49:50 +02004430 }
4431 else
4432 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004433 substitute_instr->subs_status = FAIL;
4434 res = vim_strsave((char_u *)"");
Bram Moolenaar90193e62021-04-04 20:49:50 +02004435 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004436
Bram Moolenaar4c137212021-04-19 16:48:48 +02004437 ectx->ec_instr = save_instr;
4438 ectx->ec_iidx = save_iidx;
4439
4440 return res;
4441}
4442
4443/*
4444 * Call a "def" function from old Vim script.
4445 * Return OK or FAIL.
4446 */
4447 int
4448call_def_function(
4449 ufunc_T *ufunc,
4450 int argc_arg, // nr of arguments
4451 typval_T *argv, // arguments
4452 partial_T *partial, // optional partial for context
4453 typval_T *rettv) // return value
4454{
4455 ectx_T ectx; // execution context
4456 int argc = argc_arg;
4457 typval_T *tv;
4458 int idx;
4459 int ret = FAIL;
4460 int defcount = ufunc->uf_args.ga_len - argc;
4461 sctx_T save_current_sctx = current_sctx;
4462 int did_emsg_before = did_emsg_cumul + did_emsg;
4463 int save_suppress_errthrow = suppress_errthrow;
4464 msglist_T **saved_msg_list = NULL;
4465 msglist_T *private_msg_list = NULL;
4466 int save_emsg_silent_def = emsg_silent_def;
4467 int save_did_emsg_def = did_emsg_def;
4468 int orig_funcdepth;
Bram Moolenaare99d4222021-06-13 14:01:26 +02004469 int orig_nesting_level = ex_nesting_level;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004470
4471// Get pointer to item in the stack.
4472#undef STACK_TV
4473#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
4474
4475// Get pointer to item at the bottom of the stack, -1 is the bottom.
4476#undef STACK_TV_BOT
4477#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
4478
4479// Get pointer to a local variable on the stack. Negative for arguments.
4480#undef STACK_TV_VAR
4481#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
4482
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02004483 // Update uf_has_breakpoint if needed.
4484 update_has_breakpoint(ufunc);
4485
Bram Moolenaar4c137212021-04-19 16:48:48 +02004486 if (ufunc->uf_def_status == UF_NOT_COMPILED
4487 || ufunc->uf_def_status == UF_COMPILE_ERROR
Bram Moolenaare99d4222021-06-13 14:01:26 +02004488 || (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
4489 && compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02004490 == FAIL))
4491 {
4492 if (did_emsg_cumul + did_emsg == did_emsg_before)
4493 semsg(_(e_function_is_not_compiled_str),
4494 printable_func_name(ufunc));
4495 return FAIL;
4496 }
4497
4498 {
4499 // Check the function was really compiled.
4500 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
4501 + ufunc->uf_dfunc_idx;
4502 if (INSTRUCTIONS(dfunc) == NULL)
4503 {
4504 iemsg("using call_def_function() on not compiled function");
4505 return FAIL;
4506 }
4507 }
4508
4509 // If depth of calling is getting too high, don't execute the function.
4510 orig_funcdepth = funcdepth_get();
4511 if (funcdepth_increment() == FAIL)
4512 return FAIL;
4513
4514 CLEAR_FIELD(ectx);
4515 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
4516 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02004517 if (unlikely(ga_grow(&ectx.ec_stack, 20) == FAIL))
Bram Moolenaar4c137212021-04-19 16:48:48 +02004518 {
4519 funcdepth_decrement();
4520 return FAIL;
4521 }
4522 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
4523 ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
4524 ectx.ec_did_emsg_before = did_emsg_before;
Bram Moolenaare99d4222021-06-13 14:01:26 +02004525 ++ex_nesting_level;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004526
4527 idx = argc - ufunc->uf_args.ga_len;
4528 if (idx > 0 && ufunc->uf_va_name == NULL)
4529 {
4530 if (idx == 1)
4531 emsg(_(e_one_argument_too_many));
4532 else
4533 semsg(_(e_nr_arguments_too_many), idx);
4534 goto failed_early;
4535 }
Bram Moolenaarc6d71532021-06-05 18:49:38 +02004536 idx = argc - ufunc->uf_args.ga_len + ufunc->uf_def_args.ga_len;
4537 if (idx < 0)
Bram Moolenaar8da6d6d2021-06-05 18:15:09 +02004538 {
4539 if (idx == -1)
4540 emsg(_(e_one_argument_too_few));
4541 else
4542 semsg(_(e_nr_arguments_too_few), -idx);
4543 goto failed_early;
4544 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004545
4546 // Put arguments on the stack, but no more than what the function expects.
4547 // A lambda can be called with more arguments than it uses.
4548 for (idx = 0; idx < argc
4549 && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len);
4550 ++idx)
4551 {
4552 if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len
4553 && argv[idx].v_type == VAR_SPECIAL
4554 && argv[idx].vval.v_number == VVAL_NONE)
4555 {
4556 // Use the default value.
4557 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
4558 }
4559 else
4560 {
4561 if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
4562 && check_typval_arg_type(
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02004563 ufunc->uf_arg_types[idx], &argv[idx],
4564 NULL, idx + 1) == FAIL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02004565 goto failed_early;
4566 copy_tv(&argv[idx], STACK_TV_BOT(0));
4567 }
4568 ++ectx.ec_stack.ga_len;
4569 }
4570
4571 // Turn varargs into a list. Empty list if no args.
4572 if (ufunc->uf_va_name != NULL)
4573 {
4574 int vararg_count = argc - ufunc->uf_args.ga_len;
4575
4576 if (vararg_count < 0)
4577 vararg_count = 0;
4578 else
4579 argc -= vararg_count;
4580 if (exe_newlist(vararg_count, &ectx) == FAIL)
4581 goto failed_early;
4582
4583 // Check the type of the list items.
4584 tv = STACK_TV_BOT(-1);
4585 if (ufunc->uf_va_type != NULL
4586 && ufunc->uf_va_type != &t_list_any
4587 && ufunc->uf_va_type->tt_member != &t_any
4588 && tv->vval.v_list != NULL)
4589 {
4590 type_T *expected = ufunc->uf_va_type->tt_member;
4591 listitem_T *li = tv->vval.v_list->lv_first;
4592
4593 for (idx = 0; idx < vararg_count; ++idx)
4594 {
4595 if (check_typval_arg_type(expected, &li->li_tv,
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02004596 NULL, argc + idx + 1) == FAIL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02004597 goto failed_early;
4598 li = li->li_next;
4599 }
4600 }
4601
4602 if (defcount > 0)
4603 // Move varargs list to below missing default arguments.
4604 *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1);
4605 --ectx.ec_stack.ga_len;
4606 }
4607
4608 // Make space for omitted arguments, will store default value below.
4609 // Any varargs list goes after them.
4610 if (defcount > 0)
4611 for (idx = 0; idx < defcount; ++idx)
4612 {
4613 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
4614 ++ectx.ec_stack.ga_len;
4615 }
4616 if (ufunc->uf_va_name != NULL)
4617 ++ectx.ec_stack.ga_len;
4618
4619 // Frame pointer points to just after arguments.
4620 ectx.ec_frame_idx = ectx.ec_stack.ga_len;
4621 ectx.ec_initial_frame_idx = ectx.ec_frame_idx;
4622
4623 {
4624 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
4625 + ufunc->uf_dfunc_idx;
4626 ufunc_T *base_ufunc = dfunc->df_ufunc;
4627
4628 // "uf_partial" is on the ufunc that "df_ufunc" points to, as is done
4629 // by copy_func().
4630 if (partial != NULL || base_ufunc->uf_partial != NULL)
4631 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02004632 ectx.ec_outer_ref = ALLOC_CLEAR_ONE(outer_ref_T);
4633 if (ectx.ec_outer_ref == NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02004634 goto failed_early;
4635 if (partial != NULL)
4636 {
4637 if (partial->pt_outer.out_stack == NULL && current_ectx != NULL)
4638 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02004639 if (current_ectx->ec_outer_ref != NULL
4640 && current_ectx->ec_outer_ref->or_outer != NULL)
4641 ectx.ec_outer_ref->or_outer =
4642 current_ectx->ec_outer_ref->or_outer;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004643 }
4644 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02004645 {
4646 ectx.ec_outer_ref->or_outer = &partial->pt_outer;
4647 ++partial->pt_refcount;
4648 ectx.ec_outer_ref->or_partial = partial;
4649 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004650 }
4651 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02004652 {
4653 ectx.ec_outer_ref->or_outer = &base_ufunc->uf_partial->pt_outer;
4654 ++base_ufunc->uf_partial->pt_refcount;
4655 ectx.ec_outer_ref->or_partial = base_ufunc->uf_partial;
4656 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004657 }
4658 }
4659
4660 // dummy frame entries
4661 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
4662 {
4663 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
4664 ++ectx.ec_stack.ga_len;
4665 }
4666
4667 {
4668 // Reserve space for local variables and any closure reference count.
4669 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
4670 + ufunc->uf_dfunc_idx;
4671
4672 for (idx = 0; idx < dfunc->df_varcount; ++idx)
4673 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
4674 ectx.ec_stack.ga_len += dfunc->df_varcount;
4675 if (dfunc->df_has_closure)
4676 {
4677 STACK_TV_VAR(idx)->v_type = VAR_NUMBER;
4678 STACK_TV_VAR(idx)->vval.v_number = 0;
4679 ++ectx.ec_stack.ga_len;
4680 }
4681
4682 ectx.ec_instr = INSTRUCTIONS(dfunc);
4683 }
4684
4685 // Following errors are in the function, not the caller.
4686 // Commands behave like vim9script.
4687 estack_push_ufunc(ufunc, 1);
4688 current_sctx = ufunc->uf_script_ctx;
4689 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
4690
4691 // Use a specific location for storing error messages to be converted to an
4692 // exception.
4693 saved_msg_list = msg_list;
4694 msg_list = &private_msg_list;
4695
4696 // Do turn errors into exceptions.
4697 suppress_errthrow = FALSE;
4698
4699 // Do not delete the function while executing it.
4700 ++ufunc->uf_calls;
4701
4702 // When ":silent!" was used before calling then we still abort the
4703 // function. If ":silent!" is used in the function then we don't.
4704 emsg_silent_def = emsg_silent;
4705 did_emsg_def = 0;
4706
4707 ectx.ec_where.wt_index = 0;
4708 ectx.ec_where.wt_variable = FALSE;
4709
4710 // Execute the instructions until done.
4711 ret = exec_instructions(&ectx);
4712 if (ret == OK)
4713 {
4714 // function finished, get result from the stack.
4715 if (ufunc->uf_ret_type == &t_void)
4716 {
4717 rettv->v_type = VAR_VOID;
4718 }
4719 else
4720 {
4721 tv = STACK_TV_BOT(-1);
4722 *rettv = *tv;
4723 tv->v_type = VAR_UNKNOWN;
4724 }
4725 }
4726
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01004727 // When failed need to unwind the call stack.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004728 while (ectx.ec_frame_idx != ectx.ec_initial_frame_idx)
4729 func_return(&ectx);
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02004730
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02004731 // Deal with any remaining closures, they may be in use somewhere.
4732 if (ectx.ec_funcrefs.ga_len > 0)
Bram Moolenaarf112f302020-12-20 17:47:52 +01004733 {
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02004734 handle_closure_in_use(&ectx, FALSE);
Bram Moolenaarf112f302020-12-20 17:47:52 +01004735 ga_clear(&ectx.ec_funcrefs); // TODO: should not be needed?
4736 }
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02004737
Bram Moolenaaree8580e2020-08-28 17:19:07 +02004738 estack_pop();
4739 current_sctx = save_current_sctx;
4740
Bram Moolenaarc970e422021-03-17 15:03:04 +01004741 // TODO: when is it safe to delete the function if it is no longer used?
4742 --ufunc->uf_calls;
4743
Bram Moolenaar352134b2020-10-17 22:04:08 +02004744 if (*msg_list != NULL && saved_msg_list != NULL)
4745 {
4746 msglist_T **plist = saved_msg_list;
4747
4748 // Append entries from the current msg_list (uncaught exceptions) to
4749 // the saved msg_list.
4750 while (*plist != NULL)
4751 plist = &(*plist)->next;
4752
4753 *plist = *msg_list;
4754 }
4755 msg_list = saved_msg_list;
4756
Bram Moolenaar4c137212021-04-19 16:48:48 +02004757 if (ectx.ec_funclocal.floc_restore_cmdmod)
Bram Moolenaar02194d22020-10-24 23:08:38 +02004758 {
4759 cmdmod.cmod_filter_regmatch.regprog = NULL;
4760 undo_cmdmod(&cmdmod);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004761 cmdmod = ectx.ec_funclocal.floc_save_cmdmod;
Bram Moolenaar02194d22020-10-24 23:08:38 +02004762 }
Bram Moolenaar56602ba2020-12-05 21:22:08 +01004763 emsg_silent_def = save_emsg_silent_def;
4764 did_emsg_def += save_did_emsg_def;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02004765
Bram Moolenaaree8580e2020-08-28 17:19:07 +02004766failed_early:
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02004767 // Free all local variables, but not arguments.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004768 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
4769 clear_tv(STACK_TV(idx));
Bram Moolenaare99d4222021-06-13 14:01:26 +02004770 ex_nesting_level = orig_nesting_level;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02004771
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004772 vim_free(ectx.ec_stack.ga_data);
Bram Moolenaar20431c92020-03-20 18:39:46 +01004773 vim_free(ectx.ec_trystack.ga_data);
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02004774 if (ectx.ec_outer_ref != NULL)
Bram Moolenaar0186e582021-01-10 18:33:11 +01004775 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02004776 if (ectx.ec_outer_ref->or_outer_allocated)
4777 vim_free(ectx.ec_outer_ref->or_outer);
4778 partial_unref(ectx.ec_outer_ref->or_partial);
4779 vim_free(ectx.ec_outer_ref);
Bram Moolenaar0186e582021-01-10 18:33:11 +01004780 }
4781
Bram Moolenaar77e5dcc2020-09-17 21:29:03 +02004782 // Not sure if this is necessary.
4783 suppress_errthrow = save_suppress_errthrow;
4784
Bram Moolenaarb5841b92021-07-15 18:09:53 +02004785 if (ret != OK && did_emsg_cumul + did_emsg == did_emsg_before
4786 && !need_rethrow)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004787 semsg(_(e_unknown_error_while_executing_str),
Bram Moolenaar682d0a12020-07-19 20:48:59 +02004788 printable_func_name(ufunc));
Bram Moolenaar0ba48e82020-11-17 18:23:19 +01004789 funcdepth_restore(orig_funcdepth);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004790 return ret;
4791}
4792
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004793/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02004794 * List instructions "instr" up to "instr_count" or until ISN_FINISH.
4795 * "ufunc" has the source lines, NULL for the instructions of ISN_SUBSTITUTE.
4796 * "pfx" is prefixed to every line.
4797 */
4798 static void
4799list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
4800{
4801 int line_idx = 0;
4802 int prev_current = 0;
4803 int current;
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02004804 int def_arg_idx = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004805
4806 for (current = 0; current < instr_count; ++current)
4807 {
4808 isn_T *iptr = &instr[current];
4809 char *line;
4810
4811 if (ufunc != NULL)
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02004812 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004813 while (line_idx < iptr->isn_lnum
4814 && line_idx < ufunc->uf_lines.ga_len)
4815 {
4816 if (current > prev_current)
4817 {
4818 msg_puts("\n\n");
4819 prev_current = current;
4820 }
4821 line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
4822 if (line != NULL)
4823 msg(line);
4824 }
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02004825 if (iptr->isn_type == ISN_JUMP_IF_ARG_SET)
4826 {
4827 int first_def_arg = ufunc->uf_args.ga_len
4828 - ufunc->uf_def_args.ga_len;
4829
4830 if (def_arg_idx > 0)
4831 msg_puts("\n\n");
4832 msg_start();
4833 msg_puts(" ");
4834 msg_puts(((char **)(ufunc->uf_args.ga_data))[
4835 first_def_arg + def_arg_idx]);
4836 msg_puts(" = ");
4837 msg_puts(((char **)(ufunc->uf_def_args.ga_data))[def_arg_idx++]);
4838 msg_clr_eos();
4839 msg_end();
4840 }
4841 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004842
4843 switch (iptr->isn_type)
4844 {
4845 case ISN_EXEC:
4846 smsg("%s%4d EXEC %s", pfx, current, iptr->isn_arg.string);
4847 break;
Bram Moolenaar20677332021-06-06 17:02:53 +02004848 case ISN_EXEC_SPLIT:
4849 smsg("%s%4d EXEC_SPLIT %s", pfx, current, iptr->isn_arg.string);
4850 break;
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02004851 case ISN_LEGACY_EVAL:
4852 smsg("%s%4d EVAL legacy %s", pfx, current,
4853 iptr->isn_arg.string);
4854 break;
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02004855 case ISN_REDIRSTART:
4856 smsg("%s%4d REDIR", pfx, current);
4857 break;
4858 case ISN_REDIREND:
4859 smsg("%s%4d REDIR END%s", pfx, current,
4860 iptr->isn_arg.number ? " append" : "");
4861 break;
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02004862 case ISN_CEXPR_AUCMD:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02004863#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02004864 smsg("%s%4d CEXPR pre %s", pfx, current,
4865 cexpr_get_auname(iptr->isn_arg.number));
Bram Moolenaarb7c97812021-05-05 22:51:39 +02004866#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02004867 break;
4868 case ISN_CEXPR_CORE:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02004869#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02004870 {
4871 cexprref_T *cer = iptr->isn_arg.cexpr.cexpr_ref;
4872
4873 smsg("%s%4d CEXPR core %s%s \"%s\"", pfx, current,
4874 cexpr_get_auname(cer->cer_cmdidx),
4875 cer->cer_forceit ? "!" : "",
4876 cer->cer_cmdline);
4877 }
Bram Moolenaarb7c97812021-05-05 22:51:39 +02004878#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02004879 break;
Bram Moolenaarf18332f2021-05-07 17:55:55 +02004880 case ISN_INSTR:
4881 {
4882 smsg("%s%4d INSTR", pfx, current);
4883 list_instructions(" ", iptr->isn_arg.instr,
4884 INT_MAX, NULL);
4885 msg(" -------------");
4886 }
4887 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004888 case ISN_SUBSTITUTE:
4889 {
4890 subs_T *subs = &iptr->isn_arg.subs;
4891
4892 smsg("%s%4d SUBSTITUTE %s", pfx, current, subs->subs_cmd);
4893 list_instructions(" ", subs->subs_instr, INT_MAX, NULL);
4894 msg(" -------------");
4895 }
4896 break;
4897 case ISN_EXECCONCAT:
4898 smsg("%s%4d EXECCONCAT %lld", pfx, current,
4899 (varnumber_T)iptr->isn_arg.number);
4900 break;
4901 case ISN_ECHO:
4902 {
4903 echo_T *echo = &iptr->isn_arg.echo;
4904
4905 smsg("%s%4d %s %d", pfx, current,
4906 echo->echo_with_white ? "ECHO" : "ECHON",
4907 echo->echo_count);
4908 }
4909 break;
4910 case ISN_EXECUTE:
4911 smsg("%s%4d EXECUTE %lld", pfx, current,
4912 (varnumber_T)(iptr->isn_arg.number));
4913 break;
4914 case ISN_ECHOMSG:
4915 smsg("%s%4d ECHOMSG %lld", pfx, current,
4916 (varnumber_T)(iptr->isn_arg.number));
4917 break;
4918 case ISN_ECHOERR:
4919 smsg("%s%4d ECHOERR %lld", pfx, current,
4920 (varnumber_T)(iptr->isn_arg.number));
4921 break;
4922 case ISN_LOAD:
4923 {
4924 if (iptr->isn_arg.number < 0)
4925 smsg("%s%4d LOAD arg[%lld]", pfx, current,
4926 (varnumber_T)(iptr->isn_arg.number
4927 + STACK_FRAME_SIZE));
4928 else
4929 smsg("%s%4d LOAD $%lld", pfx, current,
4930 (varnumber_T)(iptr->isn_arg.number));
4931 }
4932 break;
4933 case ISN_LOADOUTER:
4934 {
4935 if (iptr->isn_arg.number < 0)
4936 smsg("%s%4d LOADOUTER level %d arg[%d]", pfx, current,
4937 iptr->isn_arg.outer.outer_depth,
4938 iptr->isn_arg.outer.outer_idx
4939 + STACK_FRAME_SIZE);
4940 else
4941 smsg("%s%4d LOADOUTER level %d $%d", pfx, current,
4942 iptr->isn_arg.outer.outer_depth,
4943 iptr->isn_arg.outer.outer_idx);
4944 }
4945 break;
4946 case ISN_LOADV:
4947 smsg("%s%4d LOADV v:%s", pfx, current,
4948 get_vim_var_name(iptr->isn_arg.number));
4949 break;
4950 case ISN_LOADSCRIPT:
4951 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02004952 scriptref_T *sref = iptr->isn_arg.script.scriptref;
4953 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
4954 svar_T *sv;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004955
Bram Moolenaar6db660b2021-08-01 14:08:54 +02004956 sv = get_script_svar(sref, -1);
4957 if (sv == NULL)
4958 smsg("%s%4d LOADSCRIPT [deleted] from %s",
4959 pfx, current, si->sn_name);
4960 else
4961 smsg("%s%4d LOADSCRIPT %s-%d from %s", pfx, current,
Bram Moolenaar4c137212021-04-19 16:48:48 +02004962 sv->sv_name,
4963 sref->sref_idx,
4964 si->sn_name);
4965 }
4966 break;
4967 case ISN_LOADS:
4968 {
4969 scriptitem_T *si = SCRIPT_ITEM(
4970 iptr->isn_arg.loadstore.ls_sid);
4971
4972 smsg("%s%4d LOADS s:%s from %s", pfx, current,
4973 iptr->isn_arg.loadstore.ls_name, si->sn_name);
4974 }
4975 break;
4976 case ISN_LOADAUTO:
4977 smsg("%s%4d LOADAUTO %s", pfx, current, iptr->isn_arg.string);
4978 break;
4979 case ISN_LOADG:
4980 smsg("%s%4d LOADG g:%s", pfx, current, iptr->isn_arg.string);
4981 break;
4982 case ISN_LOADB:
4983 smsg("%s%4d LOADB b:%s", pfx, current, iptr->isn_arg.string);
4984 break;
4985 case ISN_LOADW:
4986 smsg("%s%4d LOADW w:%s", pfx, current, iptr->isn_arg.string);
4987 break;
4988 case ISN_LOADT:
4989 smsg("%s%4d LOADT t:%s", pfx, current, iptr->isn_arg.string);
4990 break;
4991 case ISN_LOADGDICT:
4992 smsg("%s%4d LOAD g:", pfx, current);
4993 break;
4994 case ISN_LOADBDICT:
4995 smsg("%s%4d LOAD b:", pfx, current);
4996 break;
4997 case ISN_LOADWDICT:
4998 smsg("%s%4d LOAD w:", pfx, current);
4999 break;
5000 case ISN_LOADTDICT:
5001 smsg("%s%4d LOAD t:", pfx, current);
5002 break;
5003 case ISN_LOADOPT:
5004 smsg("%s%4d LOADOPT %s", pfx, current, iptr->isn_arg.string);
5005 break;
5006 case ISN_LOADENV:
5007 smsg("%s%4d LOADENV %s", pfx, current, iptr->isn_arg.string);
5008 break;
5009 case ISN_LOADREG:
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005010 smsg("%s%4d LOADREG @%c", pfx, current,
5011 (int)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005012 break;
5013
5014 case ISN_STORE:
5015 if (iptr->isn_arg.number < 0)
5016 smsg("%s%4d STORE arg[%lld]", pfx, current,
5017 iptr->isn_arg.number + STACK_FRAME_SIZE);
5018 else
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005019 smsg("%s%4d STORE $%lld", pfx, current,
5020 iptr->isn_arg.number);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005021 break;
5022 case ISN_STOREOUTER:
5023 {
5024 if (iptr->isn_arg.number < 0)
5025 smsg("%s%4d STOREOUTEr level %d arg[%d]", pfx, current,
5026 iptr->isn_arg.outer.outer_depth,
5027 iptr->isn_arg.outer.outer_idx + STACK_FRAME_SIZE);
5028 else
5029 smsg("%s%4d STOREOUTER level %d $%d", pfx, current,
5030 iptr->isn_arg.outer.outer_depth,
5031 iptr->isn_arg.outer.outer_idx);
5032 }
5033 break;
5034 case ISN_STOREV:
5035 smsg("%s%4d STOREV v:%s", pfx, current,
5036 get_vim_var_name(iptr->isn_arg.number));
5037 break;
5038 case ISN_STOREAUTO:
5039 smsg("%s%4d STOREAUTO %s", pfx, current, iptr->isn_arg.string);
5040 break;
5041 case ISN_STOREG:
5042 smsg("%s%4d STOREG %s", pfx, current, iptr->isn_arg.string);
5043 break;
5044 case ISN_STOREB:
5045 smsg("%s%4d STOREB %s", pfx, current, iptr->isn_arg.string);
5046 break;
5047 case ISN_STOREW:
5048 smsg("%s%4d STOREW %s", pfx, current, iptr->isn_arg.string);
5049 break;
5050 case ISN_STORET:
5051 smsg("%s%4d STORET %s", pfx, current, iptr->isn_arg.string);
5052 break;
5053 case ISN_STORES:
5054 {
5055 scriptitem_T *si = SCRIPT_ITEM(
5056 iptr->isn_arg.loadstore.ls_sid);
5057
5058 smsg("%s%4d STORES %s in %s", pfx, current,
5059 iptr->isn_arg.loadstore.ls_name, si->sn_name);
5060 }
5061 break;
5062 case ISN_STORESCRIPT:
5063 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005064 scriptref_T *sref = iptr->isn_arg.script.scriptref;
5065 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
5066 svar_T *sv;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005067
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005068 sv = get_script_svar(sref, -1);
5069 if (sv == NULL)
5070 smsg("%s%4d STORESCRIPT [deleted] in %s",
5071 pfx, current, si->sn_name);
5072 else
5073 smsg("%s%4d STORESCRIPT %s-%d in %s", pfx, current,
Bram Moolenaar4c137212021-04-19 16:48:48 +02005074 sv->sv_name,
5075 sref->sref_idx,
5076 si->sn_name);
5077 }
5078 break;
5079 case ISN_STOREOPT:
5080 smsg("%s%4d STOREOPT &%s", pfx, current,
5081 iptr->isn_arg.storeopt.so_name);
5082 break;
5083 case ISN_STOREENV:
5084 smsg("%s%4d STOREENV $%s", pfx, current, iptr->isn_arg.string);
5085 break;
5086 case ISN_STOREREG:
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005087 smsg("%s%4d STOREREG @%c", pfx, current,
5088 (int)iptr->isn_arg.number);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005089 break;
5090 case ISN_STORENR:
5091 smsg("%s%4d STORE %lld in $%d", pfx, current,
5092 iptr->isn_arg.storenr.stnr_val,
5093 iptr->isn_arg.storenr.stnr_idx);
5094 break;
5095
5096 case ISN_STOREINDEX:
5097 smsg("%s%4d STOREINDEX %s", pfx, current,
5098 vartype_name(iptr->isn_arg.vartype));
5099 break;
5100
5101 case ISN_STORERANGE:
5102 smsg("%s%4d STORERANGE", pfx, current);
5103 break;
5104
5105 // constants
5106 case ISN_PUSHNR:
5107 smsg("%s%4d PUSHNR %lld", pfx, current,
5108 (varnumber_T)(iptr->isn_arg.number));
5109 break;
5110 case ISN_PUSHBOOL:
5111 case ISN_PUSHSPEC:
5112 smsg("%s%4d PUSH %s", pfx, current,
5113 get_var_special_name(iptr->isn_arg.number));
5114 break;
5115 case ISN_PUSHF:
5116#ifdef FEAT_FLOAT
5117 smsg("%s%4d PUSHF %g", pfx, current, iptr->isn_arg.fnumber);
5118#endif
5119 break;
5120 case ISN_PUSHS:
5121 smsg("%s%4d PUSHS \"%s\"", pfx, current, iptr->isn_arg.string);
5122 break;
5123 case ISN_PUSHBLOB:
5124 {
5125 char_u *r;
5126 char_u numbuf[NUMBUFLEN];
5127 char_u *tofree;
5128
5129 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
5130 smsg("%s%4d PUSHBLOB %s", pfx, current, r);
5131 vim_free(tofree);
5132 }
5133 break;
5134 case ISN_PUSHFUNC:
5135 {
5136 char *name = (char *)iptr->isn_arg.string;
5137
5138 smsg("%s%4d PUSHFUNC \"%s\"", pfx, current,
5139 name == NULL ? "[none]" : name);
5140 }
5141 break;
5142 case ISN_PUSHCHANNEL:
5143#ifdef FEAT_JOB_CHANNEL
5144 {
5145 channel_T *channel = iptr->isn_arg.channel;
5146
5147 smsg("%s%4d PUSHCHANNEL %d", pfx, current,
5148 channel == NULL ? 0 : channel->ch_id);
5149 }
5150#endif
5151 break;
5152 case ISN_PUSHJOB:
5153#ifdef FEAT_JOB_CHANNEL
5154 {
5155 typval_T tv;
5156 char_u *name;
Bram Moolenaar1328bde2021-06-05 20:51:38 +02005157 char_u buf[NUMBUFLEN];
Bram Moolenaar4c137212021-04-19 16:48:48 +02005158
5159 tv.v_type = VAR_JOB;
5160 tv.vval.v_job = iptr->isn_arg.job;
Bram Moolenaar1328bde2021-06-05 20:51:38 +02005161 name = job_to_string_buf(&tv, buf);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005162 smsg("%s%4d PUSHJOB \"%s\"", pfx, current, name);
5163 }
5164#endif
5165 break;
5166 case ISN_PUSHEXC:
5167 smsg("%s%4d PUSH v:exception", pfx, current);
5168 break;
5169 case ISN_UNLET:
5170 smsg("%s%4d UNLET%s %s", pfx, current,
5171 iptr->isn_arg.unlet.ul_forceit ? "!" : "",
5172 iptr->isn_arg.unlet.ul_name);
5173 break;
5174 case ISN_UNLETENV:
5175 smsg("%s%4d UNLETENV%s $%s", pfx, current,
5176 iptr->isn_arg.unlet.ul_forceit ? "!" : "",
5177 iptr->isn_arg.unlet.ul_name);
5178 break;
5179 case ISN_UNLETINDEX:
5180 smsg("%s%4d UNLETINDEX", pfx, current);
5181 break;
5182 case ISN_UNLETRANGE:
5183 smsg("%s%4d UNLETRANGE", pfx, current);
5184 break;
5185 case ISN_LOCKCONST:
5186 smsg("%s%4d LOCKCONST", pfx, current);
5187 break;
5188 case ISN_NEWLIST:
5189 smsg("%s%4d NEWLIST size %lld", pfx, current,
5190 (varnumber_T)(iptr->isn_arg.number));
5191 break;
5192 case ISN_NEWDICT:
5193 smsg("%s%4d NEWDICT size %lld", pfx, current,
5194 (varnumber_T)(iptr->isn_arg.number));
5195 break;
5196
5197 // function call
5198 case ISN_BCALL:
5199 {
5200 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc;
5201
5202 smsg("%s%4d BCALL %s(argc %d)", pfx, current,
5203 internal_func_name(cbfunc->cbf_idx),
5204 cbfunc->cbf_argcount);
5205 }
5206 break;
5207 case ISN_DCALL:
5208 {
5209 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc;
5210 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
5211 + cdfunc->cdf_idx;
5212
5213 smsg("%s%4d DCALL %s(argc %d)", pfx, current,
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005214 printable_func_name(df->df_ufunc),
5215 cdfunc->cdf_argcount);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005216 }
5217 break;
5218 case ISN_UCALL:
5219 {
5220 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
5221
5222 smsg("%s%4d UCALL %s(argc %d)", pfx, current,
5223 cufunc->cuf_name, cufunc->cuf_argcount);
5224 }
5225 break;
5226 case ISN_PCALL:
5227 {
5228 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc;
5229
5230 smsg("%s%4d PCALL%s (argc %d)", pfx, current,
5231 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
5232 }
5233 break;
5234 case ISN_PCALL_END:
5235 smsg("%s%4d PCALL end", pfx, current);
5236 break;
5237 case ISN_RETURN:
5238 smsg("%s%4d RETURN", pfx, current);
5239 break;
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02005240 case ISN_RETURN_VOID:
5241 smsg("%s%4d RETURN void", pfx, current);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005242 break;
5243 case ISN_FUNCREF:
5244 {
5245 funcref_T *funcref = &iptr->isn_arg.funcref;
5246 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
5247 + funcref->fr_func;
5248
5249 smsg("%s%4d FUNCREF %s", pfx, current, df->df_ufunc->uf_name);
5250 }
5251 break;
5252
5253 case ISN_NEWFUNC:
5254 {
5255 newfunc_T *newfunc = &iptr->isn_arg.newfunc;
5256
5257 smsg("%s%4d NEWFUNC %s %s", pfx, current,
5258 newfunc->nf_lambda, newfunc->nf_global);
5259 }
5260 break;
5261
5262 case ISN_DEF:
5263 {
5264 char_u *name = iptr->isn_arg.string;
5265
5266 smsg("%s%4d DEF %s", pfx, current,
5267 name == NULL ? (char_u *)"" : name);
5268 }
5269 break;
5270
5271 case ISN_JUMP:
5272 {
5273 char *when = "?";
5274
5275 switch (iptr->isn_arg.jump.jump_when)
5276 {
5277 case JUMP_ALWAYS:
5278 when = "JUMP";
5279 break;
5280 case JUMP_AND_KEEP_IF_TRUE:
5281 when = "JUMP_AND_KEEP_IF_TRUE";
5282 break;
5283 case JUMP_IF_FALSE:
5284 when = "JUMP_IF_FALSE";
5285 break;
5286 case JUMP_AND_KEEP_IF_FALSE:
5287 when = "JUMP_AND_KEEP_IF_FALSE";
5288 break;
5289 case JUMP_IF_COND_FALSE:
5290 when = "JUMP_IF_COND_FALSE";
5291 break;
5292 case JUMP_IF_COND_TRUE:
5293 when = "JUMP_IF_COND_TRUE";
5294 break;
5295 }
5296 smsg("%s%4d %s -> %d", pfx, current, when,
5297 iptr->isn_arg.jump.jump_where);
5298 }
5299 break;
5300
5301 case ISN_JUMP_IF_ARG_SET:
5302 smsg("%s%4d JUMP_IF_ARG_SET arg[%d] -> %d", pfx, current,
5303 iptr->isn_arg.jumparg.jump_arg_off + STACK_FRAME_SIZE,
5304 iptr->isn_arg.jump.jump_where);
5305 break;
5306
5307 case ISN_FOR:
5308 {
5309 forloop_T *forloop = &iptr->isn_arg.forloop;
5310
5311 smsg("%s%4d FOR $%d -> %d", pfx, current,
5312 forloop->for_idx, forloop->for_end);
5313 }
5314 break;
5315
5316 case ISN_TRY:
5317 {
5318 try_T *try = &iptr->isn_arg.try;
5319
5320 if (try->try_ref->try_finally == 0)
5321 smsg("%s%4d TRY catch -> %d, endtry -> %d",
5322 pfx, current,
5323 try->try_ref->try_catch,
5324 try->try_ref->try_endtry);
5325 else
5326 smsg("%s%4d TRY catch -> %d, finally -> %d, endtry -> %d",
5327 pfx, current,
5328 try->try_ref->try_catch,
5329 try->try_ref->try_finally,
5330 try->try_ref->try_endtry);
5331 }
5332 break;
5333 case ISN_CATCH:
5334 // TODO
5335 smsg("%s%4d CATCH", pfx, current);
5336 break;
5337 case ISN_TRYCONT:
5338 {
5339 trycont_T *trycont = &iptr->isn_arg.trycont;
5340
5341 smsg("%s%4d TRY-CONTINUE %d level%s -> %d", pfx, current,
5342 trycont->tct_levels,
5343 trycont->tct_levels == 1 ? "" : "s",
5344 trycont->tct_where);
5345 }
5346 break;
5347 case ISN_FINALLY:
5348 smsg("%s%4d FINALLY", pfx, current);
5349 break;
5350 case ISN_ENDTRY:
5351 smsg("%s%4d ENDTRY", pfx, current);
5352 break;
5353 case ISN_THROW:
5354 smsg("%s%4d THROW", pfx, current);
5355 break;
5356
5357 // expression operations on number
5358 case ISN_OPNR:
5359 case ISN_OPFLOAT:
5360 case ISN_OPANY:
5361 {
5362 char *what;
5363 char *ins;
5364
5365 switch (iptr->isn_arg.op.op_type)
5366 {
5367 case EXPR_MULT: what = "*"; break;
5368 case EXPR_DIV: what = "/"; break;
5369 case EXPR_REM: what = "%"; break;
5370 case EXPR_SUB: what = "-"; break;
5371 case EXPR_ADD: what = "+"; break;
5372 default: what = "???"; break;
5373 }
5374 switch (iptr->isn_type)
5375 {
5376 case ISN_OPNR: ins = "OPNR"; break;
5377 case ISN_OPFLOAT: ins = "OPFLOAT"; break;
5378 case ISN_OPANY: ins = "OPANY"; break;
5379 default: ins = "???"; break;
5380 }
5381 smsg("%s%4d %s %s", pfx, current, ins, what);
5382 }
5383 break;
5384
5385 case ISN_COMPAREBOOL:
5386 case ISN_COMPARESPECIAL:
5387 case ISN_COMPARENR:
5388 case ISN_COMPAREFLOAT:
5389 case ISN_COMPARESTRING:
5390 case ISN_COMPAREBLOB:
5391 case ISN_COMPARELIST:
5392 case ISN_COMPAREDICT:
5393 case ISN_COMPAREFUNC:
5394 case ISN_COMPAREANY:
5395 {
5396 char *p;
5397 char buf[10];
5398 char *type;
5399
5400 switch (iptr->isn_arg.op.op_type)
5401 {
5402 case EXPR_EQUAL: p = "=="; break;
5403 case EXPR_NEQUAL: p = "!="; break;
5404 case EXPR_GREATER: p = ">"; break;
5405 case EXPR_GEQUAL: p = ">="; break;
5406 case EXPR_SMALLER: p = "<"; break;
5407 case EXPR_SEQUAL: p = "<="; break;
5408 case EXPR_MATCH: p = "=~"; break;
5409 case EXPR_IS: p = "is"; break;
5410 case EXPR_ISNOT: p = "isnot"; break;
5411 case EXPR_NOMATCH: p = "!~"; break;
5412 default: p = "???"; break;
5413 }
5414 STRCPY(buf, p);
5415 if (iptr->isn_arg.op.op_ic == TRUE)
5416 strcat(buf, "?");
5417 switch(iptr->isn_type)
5418 {
5419 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
5420 case ISN_COMPARESPECIAL:
5421 type = "COMPARESPECIAL"; break;
5422 case ISN_COMPARENR: type = "COMPARENR"; break;
5423 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
5424 case ISN_COMPARESTRING:
5425 type = "COMPARESTRING"; break;
5426 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
5427 case ISN_COMPARELIST: type = "COMPARELIST"; break;
5428 case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
5429 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
5430 case ISN_COMPAREANY: type = "COMPAREANY"; break;
5431 default: type = "???"; break;
5432 }
5433
5434 smsg("%s%4d %s %s", pfx, current, type, buf);
5435 }
5436 break;
5437
5438 case ISN_ADDLIST: smsg("%s%4d ADDLIST", pfx, current); break;
5439 case ISN_ADDBLOB: smsg("%s%4d ADDBLOB", pfx, current); break;
5440
5441 // expression operations
5442 case ISN_CONCAT: smsg("%s%4d CONCAT", pfx, current); break;
5443 case ISN_STRINDEX: smsg("%s%4d STRINDEX", pfx, current); break;
5444 case ISN_STRSLICE: smsg("%s%4d STRSLICE", pfx, current); break;
5445 case ISN_BLOBINDEX: smsg("%s%4d BLOBINDEX", pfx, current); break;
5446 case ISN_BLOBSLICE: smsg("%s%4d BLOBSLICE", pfx, current); break;
5447 case ISN_LISTAPPEND: smsg("%s%4d LISTAPPEND", pfx, current); break;
5448 case ISN_BLOBAPPEND: smsg("%s%4d BLOBAPPEND", pfx, current); break;
5449 case ISN_LISTINDEX: smsg("%s%4d LISTINDEX", pfx, current); break;
5450 case ISN_LISTSLICE: smsg("%s%4d LISTSLICE", pfx, current); break;
5451 case ISN_ANYINDEX: smsg("%s%4d ANYINDEX", pfx, current); break;
5452 case ISN_ANYSLICE: smsg("%s%4d ANYSLICE", pfx, current); break;
5453 case ISN_SLICE: smsg("%s%4d SLICE %lld",
5454 pfx, current, iptr->isn_arg.number); break;
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02005455 case ISN_GETITEM: smsg("%s%4d ITEM %lld%s", pfx, current,
5456 iptr->isn_arg.getitem.gi_index,
5457 iptr->isn_arg.getitem.gi_with_op ?
5458 " with op" : ""); break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005459 case ISN_MEMBER: smsg("%s%4d MEMBER", pfx, current); break;
5460 case ISN_STRINGMEMBER: smsg("%s%4d MEMBER %s", pfx, current,
5461 iptr->isn_arg.string); break;
5462 case ISN_NEGATENR: smsg("%s%4d NEGATENR", pfx, current); break;
5463
5464 case ISN_CHECKNR: smsg("%s%4d CHECKNR", pfx, current); break;
5465 case ISN_CHECKTYPE:
5466 {
5467 checktype_T *ct = &iptr->isn_arg.type;
5468 char *tofree;
5469
5470 if (ct->ct_arg_idx == 0)
5471 smsg("%s%4d CHECKTYPE %s stack[%d]", pfx, current,
5472 type_name(ct->ct_type, &tofree),
5473 (int)ct->ct_off);
5474 else
5475 smsg("%s%4d CHECKTYPE %s stack[%d] arg %d", pfx, current,
5476 type_name(ct->ct_type, &tofree),
5477 (int)ct->ct_off,
5478 (int)ct->ct_arg_idx);
5479 vim_free(tofree);
5480 break;
5481 }
5482 case ISN_CHECKLEN: smsg("%s%4d CHECKLEN %s%d", pfx, current,
5483 iptr->isn_arg.checklen.cl_more_OK ? ">= " : "",
5484 iptr->isn_arg.checklen.cl_min_len);
5485 break;
5486 case ISN_SETTYPE:
5487 {
5488 char *tofree;
5489
5490 smsg("%s%4d SETTYPE %s", pfx, current,
5491 type_name(iptr->isn_arg.type.ct_type, &tofree));
5492 vim_free(tofree);
5493 break;
5494 }
5495 case ISN_COND2BOOL: smsg("%s%4d COND2BOOL", pfx, current); break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005496 case ISN_2BOOL: if (iptr->isn_arg.tobool.invert)
5497 smsg("%s%4d INVERT %d (!val)", pfx, current,
5498 iptr->isn_arg.tobool.offset);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005499 else
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005500 smsg("%s%4d 2BOOL %d (!!val)", pfx, current,
5501 iptr->isn_arg.tobool.offset);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005502 break;
5503 case ISN_2STRING: smsg("%s%4d 2STRING stack[%lld]", pfx, current,
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005504 (varnumber_T)(iptr->isn_arg.tostring.offset));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005505 break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005506 case ISN_2STRING_ANY: smsg("%s%4d 2STRING_ANY stack[%lld]",
5507 pfx, current,
5508 (varnumber_T)(iptr->isn_arg.tostring.offset));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005509 break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005510 case ISN_RANGE: smsg("%s%4d RANGE %s", pfx, current,
5511 iptr->isn_arg.string);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005512 break;
5513 case ISN_PUT:
5514 if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE_ABOVE)
5515 smsg("%s%4d PUT %c above range",
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005516 pfx, current, iptr->isn_arg.put.put_regname);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005517 else if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE)
5518 smsg("%s%4d PUT %c range",
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005519 pfx, current, iptr->isn_arg.put.put_regname);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005520 else
5521 smsg("%s%4d PUT %c %ld", pfx, current,
5522 iptr->isn_arg.put.put_regname,
5523 (long)iptr->isn_arg.put.put_lnum);
5524 break;
5525
5526 // TODO: summarize modifiers
5527 case ISN_CMDMOD:
5528 {
5529 char_u *buf;
5530 size_t len = produce_cmdmods(
5531 NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
5532
5533 buf = alloc(len + 1);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02005534 if (likely(buf != NULL))
Bram Moolenaar4c137212021-04-19 16:48:48 +02005535 {
5536 (void)produce_cmdmods(
5537 buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
5538 smsg("%s%4d CMDMOD %s", pfx, current, buf);
5539 vim_free(buf);
5540 }
5541 break;
5542 }
5543 case ISN_CMDMOD_REV: smsg("%s%4d CMDMOD_REV", pfx, current); break;
5544
5545 case ISN_PROF_START:
Bram Moolenaare99d4222021-06-13 14:01:26 +02005546 smsg("%s%4d PROFILE START line %d", pfx, current,
5547 iptr->isn_lnum);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005548 break;
5549
5550 case ISN_PROF_END:
5551 smsg("%s%4d PROFILE END", pfx, current);
5552 break;
5553
Bram Moolenaare99d4222021-06-13 14:01:26 +02005554 case ISN_DEBUG:
Bram Moolenaar8cec9272021-06-23 20:20:53 +02005555 smsg("%s%4d DEBUG line %d-%d varcount %lld", pfx, current,
5556 iptr->isn_arg.debug.dbg_break_lnum + 1,
5557 iptr->isn_lnum,
5558 iptr->isn_arg.debug.dbg_var_names_len);
Bram Moolenaare99d4222021-06-13 14:01:26 +02005559 break;
5560
Bram Moolenaar4c137212021-04-19 16:48:48 +02005561 case ISN_UNPACK: smsg("%s%4d UNPACK %d%s", pfx, current,
5562 iptr->isn_arg.unpack.unp_count,
5563 iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");
5564 break;
5565 case ISN_SHUFFLE: smsg("%s%4d SHUFFLE %d up %d", pfx, current,
5566 iptr->isn_arg.shuffle.shfl_item,
5567 iptr->isn_arg.shuffle.shfl_up);
5568 break;
5569 case ISN_DROP: smsg("%s%4d DROP", pfx, current); break;
5570
5571 case ISN_FINISH: // End of list of instructions for ISN_SUBSTITUTE.
5572 return;
5573 }
5574
5575 out_flush(); // output one line at a time
5576 ui_breakcheck();
5577 if (got_int)
5578 break;
5579 }
5580}
5581
5582/*
Bram Moolenaar4ee9d8e2021-06-13 18:38:48 +02005583 * Handle command line completion for the :disassemble command.
5584 */
5585 void
5586set_context_in_disassemble_cmd(expand_T *xp, char_u *arg)
5587{
5588 char_u *p;
5589
5590 // Default: expand user functions, "debug" and "profile"
5591 xp->xp_context = EXPAND_DISASSEMBLE;
5592 xp->xp_pattern = arg;
5593
5594 // first argument already typed: only user function names
5595 if (*arg != NUL && *(p = skiptowhite(arg)) != NUL)
5596 {
5597 xp->xp_context = EXPAND_USER_FUNC;
5598 xp->xp_pattern = skipwhite(p);
5599 }
5600}
5601
5602/*
5603 * Function given to ExpandGeneric() to obtain the list of :disassemble
5604 * arguments.
5605 */
5606 char_u *
5607get_disassemble_argument(expand_T *xp, int idx)
5608{
5609 if (idx == 0)
5610 return (char_u *)"debug";
5611 if (idx == 1)
5612 return (char_u *)"profile";
5613 return get_user_func_name(xp, idx - 2);
5614}
5615
5616/*
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01005617 * ":disassemble".
Bram Moolenaar777770f2020-02-06 21:27:08 +01005618 * We don't really need this at runtime, but we do have tests that require it,
5619 * so always include this.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005620 */
5621 void
5622ex_disassemble(exarg_T *eap)
5623{
Bram Moolenaar21456cd2020-02-13 21:29:32 +01005624 char_u *arg = eap->arg;
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01005625 char_u *fname;
5626 ufunc_T *ufunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005627 dfunc_T *dfunc;
5628 isn_T *instr;
Bram Moolenaarb2049902021-01-24 12:53:53 +01005629 int instr_count;
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02005630 int is_global = FALSE;
Bram Moolenaare99d4222021-06-13 14:01:26 +02005631 compiletype_T compile_type = CT_NONE;
5632
5633 if (STRNCMP(arg, "profile", 7) == 0)
5634 {
5635 compile_type = CT_PROFILE;
5636 arg = skipwhite(arg + 7);
5637 }
5638 else if (STRNCMP(arg, "debug", 5) == 0)
5639 {
5640 compile_type = CT_DEBUG;
5641 arg = skipwhite(arg + 5);
5642 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005643
Bram Moolenaarbfd65582020-07-13 18:18:00 +02005644 if (STRNCMP(arg, "<lambda>", 8) == 0)
5645 {
5646 arg += 8;
5647 (void)getdigits(&arg);
5648 fname = vim_strnsave(eap->arg, arg - eap->arg);
5649 }
5650 else
5651 fname = trans_function_name(&arg, &is_global, FALSE,
Bram Moolenaar32b3f822021-01-06 21:59:39 +01005652 TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL);
Bram Moolenaar21456cd2020-02-13 21:29:32 +01005653 if (fname == NULL)
5654 {
5655 semsg(_(e_invarg2), eap->arg);
5656 return;
5657 }
5658
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02005659 ufunc = find_func(fname, is_global, NULL);
Bram Moolenaara26b9702020-04-18 19:53:28 +02005660 if (ufunc == NULL)
5661 {
5662 char_u *p = untrans_function_name(fname);
5663
5664 if (p != NULL)
5665 // Try again without making it script-local.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02005666 ufunc = find_func(p, FALSE, NULL);
Bram Moolenaara26b9702020-04-18 19:53:28 +02005667 }
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01005668 vim_free(fname);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005669 if (ufunc == NULL)
5670 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005671 semsg(_(e_cannot_find_function_str), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005672 return;
5673 }
Bram Moolenaare99d4222021-06-13 14:01:26 +02005674 if (func_needs_compiling(ufunc, compile_type)
5675 && compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02005676 return;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02005677 if (ufunc->uf_def_status != UF_COMPILED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005678 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005679 semsg(_(e_function_is_not_compiled_str), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005680 return;
5681 }
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005682 msg((char *)printable_func_name(ufunc));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005683
5684 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
Bram Moolenaare99d4222021-06-13 14:01:26 +02005685 switch (compile_type)
5686 {
5687 case CT_PROFILE:
Bram Moolenaarf002a412021-01-24 13:34:18 +01005688#ifdef FEAT_PROFILE
Bram Moolenaare99d4222021-06-13 14:01:26 +02005689 instr = dfunc->df_instr_prof;
5690 instr_count = dfunc->df_instr_prof_count;
5691 break;
Bram Moolenaarf002a412021-01-24 13:34:18 +01005692#endif
Bram Moolenaare99d4222021-06-13 14:01:26 +02005693 // FALLTHROUGH
5694 case CT_NONE:
5695 instr = dfunc->df_instr;
5696 instr_count = dfunc->df_instr_count;
5697 break;
5698 case CT_DEBUG:
5699 instr = dfunc->df_instr_debug;
5700 instr_count = dfunc->df_instr_debug_count;
5701 break;
5702 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005703
Bram Moolenaar4c137212021-04-19 16:48:48 +02005704 list_instructions("", instr, instr_count, ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005705}
5706
5707/*
Bram Moolenaar13106602020-10-04 16:06:05 +02005708 * Return TRUE when "tv" is not falsy: non-zero, non-empty string, non-empty
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005709 * list, etc. Mostly like what JavaScript does, except that empty list and
5710 * empty dictionary are FALSE.
5711 */
5712 int
5713tv2bool(typval_T *tv)
5714{
5715 switch (tv->v_type)
5716 {
5717 case VAR_NUMBER:
5718 return tv->vval.v_number != 0;
5719 case VAR_FLOAT:
5720#ifdef FEAT_FLOAT
5721 return tv->vval.v_float != 0.0;
5722#else
5723 break;
5724#endif
5725 case VAR_PARTIAL:
5726 return tv->vval.v_partial != NULL;
5727 case VAR_FUNC:
5728 case VAR_STRING:
5729 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
5730 case VAR_LIST:
5731 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
5732 case VAR_DICT:
5733 return tv->vval.v_dict != NULL
5734 && tv->vval.v_dict->dv_hashtab.ht_used > 0;
5735 case VAR_BOOL:
5736 case VAR_SPECIAL:
5737 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
5738 case VAR_JOB:
5739#ifdef FEAT_JOB_CHANNEL
5740 return tv->vval.v_job != NULL;
5741#else
5742 break;
5743#endif
5744 case VAR_CHANNEL:
5745#ifdef FEAT_JOB_CHANNEL
5746 return tv->vval.v_channel != NULL;
5747#else
5748 break;
5749#endif
5750 case VAR_BLOB:
5751 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
5752 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02005753 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005754 case VAR_VOID:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02005755 case VAR_INSTR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005756 break;
5757 }
5758 return FALSE;
5759}
5760
Bram Moolenaarea2d4072020-11-12 12:08:51 +01005761 void
5762emsg_using_string_as(typval_T *tv, int as_number)
5763{
5764 semsg(_(as_number ? e_using_string_as_number_str
5765 : e_using_string_as_bool_str),
5766 tv->vval.v_string == NULL
5767 ? (char_u *)"" : tv->vval.v_string);
5768}
5769
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005770/*
5771 * If "tv" is a string give an error and return FAIL.
5772 */
5773 int
5774check_not_string(typval_T *tv)
5775{
5776 if (tv->v_type == VAR_STRING)
5777 {
Bram Moolenaarea2d4072020-11-12 12:08:51 +01005778 emsg_using_string_as(tv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005779 clear_tv(tv);
5780 return FAIL;
5781 }
5782 return OK;
5783}
5784
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005785
5786#endif // FEAT_EVAL