blob: 2bc81c38b18ef224e7e726f6e0ac60a7d161aeac [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
Bram Moolenaardc7c3662021-12-20 15:04:29 +000019// When not generating protos this is included in proto.h
20#ifdef PROTO
21# include "vim9.h"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010022#endif
23
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010024
25// Structure put on ec_trystack when ISN_TRY is encountered.
26typedef struct {
Bram Moolenaard9d77892021-02-12 21:32:47 +010027 int tcd_frame_idx; // ec_frame_idx at ISN_TRY
28 int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY
Bram Moolenaard3d8fee2021-06-30 19:54:43 +020029 int tcd_in_catch; // in catch or finally block
30 int tcd_did_throw; // set did_throw in :endtry
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +010031 int tcd_catch_idx; // instruction of the first :catch or :finally
32 int tcd_finally_idx; // instruction of the :finally block or zero
33 int tcd_endtry_idx; // instruction of the :endtry
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010034 int tcd_caught; // catch block entered
Bram Moolenaar2e34c342021-03-14 12:13:33 +010035 int tcd_cont; // :continue encountered, jump here (minus one)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010036 int tcd_return; // when TRUE return from end of :finally
37} trycmd_T;
38
Bram Moolenaar4c137212021-04-19 16:48:48 +020039// Data local to a function.
40// On a function call, if not empty, is saved on the stack and restored when
41// returning.
42typedef struct {
43 int floc_restore_cmdmod;
44 cmdmod_T floc_save_cmdmod;
45 int floc_restore_cmdmod_stacklen;
46} funclocal_T;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010047
Bram Moolenaarc04f2a42021-06-09 19:30:03 +020048// Structure to hold a reference to an outer_T, with information of whether it
49// was allocated.
50typedef struct {
51 outer_T *or_outer;
52 partial_T *or_partial; // decrement "or_partial->pt_refcount" later
53 int or_outer_allocated; // free "or_outer" later
54} outer_ref_T;
55
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010056// A stack is used to store:
57// - arguments passed to a :def function
58// - info about the calling function, to use when returning
59// - local variables
60// - temporary values
61//
62// In detail (FP == Frame Pointer):
63// arg1 first argument from caller (if present)
64// arg2 second argument from caller (if present)
65// extra_arg1 any missing optional argument default value
66// FP -> cur_func calling function
Bram Moolenaar6ed545e2022-05-09 20:09:23 +010067// current previous instruction pointer
68// frame_ptr previous Frame Pointer
69// var1 space for local variable
70// var2 space for local variable
71// .... fixed space for max. number of local variables
72// temp temporary values
73// .... flexible space for temporary values (can grow big)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010074
75/*
76 * Execution context.
77 */
Bram Moolenaarcd45ed02020-12-22 17:35:54 +010078struct ectx_S {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010079 garray_T ec_stack; // stack of typval_T values
Bram Moolenaarbf67ea12020-05-02 17:52:42 +020080 int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx
Bram Moolenaar4c137212021-04-19 16:48:48 +020081 int ec_initial_frame_idx; // frame index when called
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010082
Bram Moolenaarc04f2a42021-06-09 19:30:03 +020083 outer_ref_T *ec_outer_ref; // outer scope used for closures, allocated
Bram Moolenaar4c137212021-04-19 16:48:48 +020084 funclocal_T ec_funclocal;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +020085
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010086 garray_T ec_trystack; // stack of trycmd_T values
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010087
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010088 isn_T *ec_instr; // array with instructions
Dominique Pelle3276f582021-08-07 12:44:41 +020089 int ec_dfunc_idx; // current function index
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010090 int ec_iidx; // index in ec_instr: instruction to execute
Bram Moolenaar148ce7a2020-09-23 21:57:23 +020091
92 garray_T ec_funcrefs; // partials that might be a closure
Bram Moolenaar4c137212021-04-19 16:48:48 +020093
94 int ec_did_emsg_before;
95 int ec_trylevel_at_start;
96 where_T ec_where;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +010097};
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010098
Bram Moolenaar12d26532021-02-19 19:13:21 +010099#ifdef FEAT_PROFILE
100// stack of profinfo_T used when profiling.
101static garray_T profile_info_ga = {0, 0, sizeof(profinfo_T), 20, NULL};
102#endif
103
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100104// Get pointer to item in the stack.
105#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
106
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100107// Get pointer to item relative to the bottom of the stack, -1 is the last one.
Bram Moolenaar11107ba2020-08-15 21:10:16 +0200108#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 +0100109
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100110// Get pointer to a local variable on the stack. Negative for arguments.
111#define STACK_TV_VAR(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx + STACK_FRAME_SIZE + idx)
112
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200113 void
114to_string_error(vartype_T vartype)
115{
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200116 semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype));
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200117}
118
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100119/*
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100120 * Return the number of arguments, including optional arguments and any vararg.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100121 */
122 static int
123ufunc_argcount(ufunc_T *ufunc)
124{
125 return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0);
126}
127
128/*
LemonBoy372bcce2022-04-25 12:43:20 +0100129 * Create a new string from "count" items at the bottom of the stack.
130 * A trailing NUL is appended.
131 * When "count" is zero an empty string is added to the stack.
132 */
133 static int
134exe_concat(int count, ectx_T *ectx)
135{
136 int idx;
137 int len = 0;
138 typval_T *tv;
139 garray_T ga;
140
141 ga_init2(&ga, sizeof(char), 1);
142 // Preallocate enough space for the whole string to avoid having to grow
143 // and copy.
144 for (idx = 0; idx < count; ++idx)
145 {
146 tv = STACK_TV_BOT(idx - count);
147 if (tv->vval.v_string != NULL)
148 len += (int)STRLEN(tv->vval.v_string);
149 }
150
151 if (ga_grow(&ga, len + 1) == FAIL)
152 return FAIL;
153
154 for (idx = 0; idx < count; ++idx)
155 {
156 tv = STACK_TV_BOT(idx - count);
157 ga_concat(&ga, tv->vval.v_string);
158 clear_tv(tv);
159 }
160
161 // add a terminating NUL
162 ga_append(&ga, NUL);
163
164 ectx->ec_stack.ga_len -= count - 1;
165 STACK_TV_BOT(-1)->vval.v_string = ga.ga_data;
166
167 return OK;
168}
169
170/*
Bram Moolenaarfe270812020-04-11 22:31:27 +0200171 * Create a new list from "count" items at the bottom of the stack.
172 * When "count" is zero an empty list is added to the stack.
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100173 * When "count" is -1 a NULL list is added to the stack.
Bram Moolenaarfe270812020-04-11 22:31:27 +0200174 */
175 static int
176exe_newlist(int count, ectx_T *ectx)
177{
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100178 list_T *list = NULL;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200179 int idx;
180 typval_T *tv;
181
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100182 if (count >= 0)
183 {
184 list = list_alloc_with_items(count);
185 if (list == NULL)
186 return FAIL;
187 for (idx = 0; idx < count; ++idx)
188 list_set_item(list, idx, STACK_TV_BOT(idx - count));
189 }
Bram Moolenaarfe270812020-04-11 22:31:27 +0200190
191 if (count > 0)
192 ectx->ec_stack.ga_len -= count - 1;
Bram Moolenaar35578162021-08-02 19:10:38 +0200193 else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100194 {
195 list_unref(list);
Bram Moolenaarfe270812020-04-11 22:31:27 +0200196 return FAIL;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100197 }
Bram Moolenaarfe270812020-04-11 22:31:27 +0200198 else
199 ++ectx->ec_stack.ga_len;
200 tv = STACK_TV_BOT(-1);
201 tv->v_type = VAR_LIST;
202 tv->vval.v_list = list;
Bram Moolenaar566badc2022-09-18 13:46:08 +0100203 tv->v_lock = 0;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100204 if (list != NULL)
205 ++list->lv_refcount;
206 return OK;
207}
208
209/*
210 * Implementation of ISN_NEWDICT.
211 * Returns FAIL on total failure, MAYBE on error.
212 */
213 static int
214exe_newdict(int count, ectx_T *ectx)
215{
216 dict_T *dict = NULL;
217 dictitem_T *item;
218 char_u *key;
219 int idx;
220 typval_T *tv;
221
222 if (count >= 0)
223 {
224 dict = dict_alloc();
225 if (unlikely(dict == NULL))
226 return FAIL;
227 for (idx = 0; idx < count; ++idx)
228 {
229 // have already checked key type is VAR_STRING
230 tv = STACK_TV_BOT(2 * (idx - count));
231 // check key is unique
232 key = tv->vval.v_string == NULL
233 ? (char_u *)"" : tv->vval.v_string;
234 item = dict_find(dict, key, -1);
235 if (item != NULL)
236 {
dundargocc57b5bc2022-11-02 13:30:51 +0000237 semsg(_(e_duplicate_key_in_dictionary), key);
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100238 dict_unref(dict);
239 return MAYBE;
240 }
241 item = dictitem_alloc(key);
242 clear_tv(tv);
243 if (unlikely(item == NULL))
244 {
245 dict_unref(dict);
246 return FAIL;
247 }
Bram Moolenaar0d1f55c2022-04-05 17:30:29 +0100248 tv = STACK_TV_BOT(2 * (idx - count) + 1);
249 item->di_tv = *tv;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100250 item->di_tv.v_lock = 0;
Bram Moolenaar0d1f55c2022-04-05 17:30:29 +0100251 tv->v_type = VAR_UNKNOWN;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +0100252 if (dict_add(dict, item) == FAIL)
253 {
254 // can this ever happen?
255 dict_unref(dict);
256 return FAIL;
257 }
258 }
259 }
260
261 if (count > 0)
262 ectx->ec_stack.ga_len -= 2 * count - 1;
263 else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
264 return FAIL;
265 else
266 ++ectx->ec_stack.ga_len;
267 tv = STACK_TV_BOT(-1);
268 tv->v_type = VAR_DICT;
269 tv->v_lock = 0;
270 tv->vval.v_dict = dict;
271 if (dict != NULL)
272 ++dict->dv_refcount;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200273 return OK;
274}
275
276/*
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200277 * If debug_tick changed check if "ufunc" has a breakpoint and update
278 * "uf_has_breakpoint".
279 */
Bram Moolenaar96923b72022-03-15 15:57:04 +0000280 void
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200281update_has_breakpoint(ufunc_T *ufunc)
282{
283 if (ufunc->uf_debug_tick != debug_tick)
284 {
285 linenr_T breakpoint;
286
287 ufunc->uf_debug_tick = debug_tick;
288 breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name, 0);
289 ufunc->uf_has_breakpoint = breakpoint > 0;
290 }
291}
292
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +0200293static garray_T dict_stack = GA_EMPTY;
294
295/*
296 * Put a value on the dict stack. This consumes "tv".
297 */
298 static int
299dict_stack_save(typval_T *tv)
300{
301 if (dict_stack.ga_growsize == 0)
Bram Moolenaar04935fb2022-01-08 16:19:22 +0000302 ga_init2(&dict_stack, sizeof(typval_T), 10);
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +0200303 if (ga_grow(&dict_stack, 1) == FAIL)
304 return FAIL;
305 ((typval_T *)dict_stack.ga_data)[dict_stack.ga_len] = *tv;
306 ++dict_stack.ga_len;
307 return OK;
308}
309
310/*
311 * Get the typval at top of the dict stack.
312 */
313 static typval_T *
314dict_stack_get_tv(void)
315{
316 if (dict_stack.ga_len == 0)
317 return NULL;
318 return ((typval_T *)dict_stack.ga_data) + dict_stack.ga_len - 1;
319}
320
321/*
322 * Get the dict at top of the dict stack.
323 */
324 static dict_T *
325dict_stack_get_dict(void)
326{
327 typval_T *tv;
328
329 if (dict_stack.ga_len == 0)
330 return NULL;
331 tv = ((typval_T *)dict_stack.ga_data) + dict_stack.ga_len - 1;
332 if (tv->v_type == VAR_DICT)
333 return tv->vval.v_dict;
334 return NULL;
335}
336
337/*
338 * Drop an item from the dict stack.
339 */
340 static void
341dict_stack_drop(void)
342{
343 if (dict_stack.ga_len == 0)
344 {
345 iemsg("Dict stack underflow");
346 return;
347 }
348 --dict_stack.ga_len;
349 clear_tv(((typval_T *)dict_stack.ga_data) + dict_stack.ga_len);
350}
351
352/*
353 * Drop items from the dict stack until the length is equal to "len".
354 */
355 static void
356dict_stack_clear(int len)
357{
358 while (dict_stack.ga_len > len)
359 dict_stack_drop();
360}
361
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200362/*
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +0000363 * Get a pointer to useful "pt_outer" of "pt".
364 */
365 static outer_T *
366get_pt_outer(partial_T *pt)
367{
368 partial_T *ptref = pt->pt_outer_partial;
369
370 if (ptref == NULL)
371 return &pt->pt_outer;
372
373 // partial using partial (recursively)
374 while (ptref->pt_outer_partial != NULL)
375 ptref = ptref->pt_outer_partial;
376 return &ptref->pt_outer;
377}
378
379/*
Bram Moolenaar0d89d8a2022-12-31 14:01:24 +0000380 * Check "argcount" arguments on the stack against what "ufunc" expects.
381 * "off" is the offset of arguments on the stack.
382 * Return OK or FAIL.
383 */
384 static int
385check_ufunc_arg_types(ufunc_T *ufunc, int argcount, int off, ectx_T *ectx)
386{
387 if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL)
388 {
389 typval_T *argv = STACK_TV_BOT(0) - argcount - off;
390
391 // The function can change at runtime, check that the argument
392 // types are correct.
393 for (int i = 0; i < argcount; ++i)
394 {
395 type_T *type = NULL;
396
397 // assume a v:none argument, using the default value, is always OK
398 if (argv[i].v_type == VAR_SPECIAL
399 && argv[i].vval.v_number == VVAL_NONE)
400 continue;
401
402 if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
403 type = ufunc->uf_arg_types[i];
404 else if (ufunc->uf_va_type != NULL)
405 type = ufunc->uf_va_type->tt_member;
406 if (type != NULL && check_typval_arg_type(type,
407 &argv[i], NULL, i + 1) == FAIL)
408 return FAIL;
409 }
410 }
411 return OK;
412}
413
414/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100415 * Call compiled function "cdf_idx" from compiled code.
Bram Moolenaarab360522021-01-10 14:02:28 +0100416 * This adds a stack frame and sets the instruction pointer to the start of the
417 * called function.
Bram Moolenaar5800c792022-09-22 17:34:01 +0100418 * If "pt_arg" is not NULL use "pt_arg->pt_outer" for ec_outer_ref->or_outer.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100419 *
420 * Stack has:
421 * - current arguments (already there)
422 * - omitted optional argument (default values) added here
423 * - stack frame:
424 * - pointer to calling function
425 * - Index of next instruction in calling function
426 * - previous frame pointer
427 * - reserved space for local variables
428 */
429 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100430call_dfunc(
431 int cdf_idx,
Bram Moolenaar5800c792022-09-22 17:34:01 +0100432 partial_T *pt_arg,
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100433 int argcount_arg,
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100434 ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100435{
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100436 int argcount = argcount_arg;
437 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
438 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200439 int did_emsg_before = did_emsg_cumul + did_emsg;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100440 int arg_to_add;
441 int vararg_count = 0;
442 int varcount;
443 int idx;
444 estack_T *entry;
445 funclocal_T *floc = NULL;
Bram Moolenaar648594e2021-07-11 17:55:01 +0200446 int res = OK;
Bram Moolenaar139575d2022-03-15 19:29:30 +0000447 compiletype_T compile_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100448
449 if (dfunc->df_deleted)
450 {
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100451 // don't use ufunc->uf_name, it may have been freed
Bram Moolenaar460ae5d2022-01-01 14:19:49 +0000452 emsg_funcname(e_function_was_deleted_str,
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100453 dfunc->df_name == NULL ? (char_u *)"unknown" : dfunc->df_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100454 return FAIL;
455 }
456
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100457#ifdef FEAT_PROFILE
Bram Moolenaar12d26532021-02-19 19:13:21 +0100458 if (do_profiling == PROF_YES)
459 {
Bram Moolenaar35578162021-08-02 19:10:38 +0200460 if (GA_GROW_OK(&profile_info_ga, 1))
Bram Moolenaar12d26532021-02-19 19:13:21 +0100461 {
462 profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data)
463 + profile_info_ga.ga_len;
464 ++profile_info_ga.ga_len;
465 CLEAR_POINTER(info);
466 profile_may_start_func(info, ufunc,
467 (((dfunc_T *)def_functions.ga_data)
468 + ectx->ec_dfunc_idx)->df_ufunc);
469 }
Bram Moolenaar12d26532021-02-19 19:13:21 +0100470 }
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100471#endif
472
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200473 // When debugging and using "cont" switches to the not-debugged
474 // instructions, may need to still compile them.
Bram Moolenaar139575d2022-03-15 19:29:30 +0000475 compile_type = get_compile_type(ufunc);
476 if (func_needs_compiling(ufunc, compile_type))
Bram Moolenaar648594e2021-07-11 17:55:01 +0200477 {
Bram Moolenaar139575d2022-03-15 19:29:30 +0000478 res = compile_def_function(ufunc, FALSE, compile_type, NULL);
Bram Moolenaar648594e2021-07-11 17:55:01 +0200479
480 // compile_def_function() may cause def_functions.ga_data to change
481 dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
482 }
483 if (res == FAIL || INSTRUCTIONS(dfunc) == NULL)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200484 {
485 if (did_emsg_cumul + did_emsg == did_emsg_before)
486 semsg(_(e_function_is_not_compiled_str),
487 printable_func_name(ufunc));
488 return FAIL;
489 }
490
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200491 if (ufunc->uf_va_name != NULL)
492 {
Bram Moolenaarfe270812020-04-11 22:31:27 +0200493 // Need to make a list out of the vararg arguments.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200494 // Stack at time of call with 2 varargs:
495 // normal_arg
496 // optional_arg
497 // vararg_1
498 // vararg_2
Bram Moolenaarfe270812020-04-11 22:31:27 +0200499 // After creating the list:
500 // normal_arg
501 // optional_arg
502 // vararg-list
503 // With missing optional arguments we get:
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200504 // normal_arg
Bram Moolenaarfe270812020-04-11 22:31:27 +0200505 // After creating the list
506 // normal_arg
507 // (space for optional_arg)
508 // vararg-list
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200509 vararg_count = argcount - ufunc->uf_args.ga_len;
510 if (vararg_count < 0)
511 vararg_count = 0;
512 else
513 argcount -= vararg_count;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200514 if (exe_newlist(vararg_count, ectx) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200515 return FAIL;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200516
517 vararg_count = 1;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200518 }
519
Bram Moolenaarfe270812020-04-11 22:31:27 +0200520 arg_to_add = ufunc->uf_args.ga_len - argcount;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200521 if (arg_to_add < 0)
522 {
Matvey Tarasovd14bb1a2022-06-29 13:18:27 +0100523 semsg(NGETTEXT(e_one_argument_too_many, e_nr_arguments_too_many,
524 -arg_to_add), -arg_to_add);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200525 return FAIL;
526 }
Bram Moolenaarcd1cda22022-02-16 21:48:25 +0000527 else if (arg_to_add > ufunc->uf_def_args.ga_len)
528 {
529 int missing = arg_to_add - ufunc->uf_def_args.ga_len;
530
Matvey Tarasovd14bb1a2022-06-29 13:18:27 +0100531 semsg(NGETTEXT(e_one_argument_too_few, e_nr_arguments_too_few,
532 missing), missing);
Bram Moolenaarcd1cda22022-02-16 21:48:25 +0000533 return FAIL;
534 }
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200535
Bram Moolenaar0d89d8a2022-12-31 14:01:24 +0000536 // Check the argument types.
537 if (check_ufunc_arg_types(ufunc, argcount, vararg_count, ectx) == FAIL)
538 return FAIL;
539
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200540 // Reserve space for:
541 // - missing arguments
542 // - stack frame
543 // - local variables
544 // - if needed: a counter for number of closures created in
545 // ectx->ec_funcrefs.
546 varcount = dfunc->df_varcount + dfunc->df_has_closure;
Bram Moolenaarb46c0832022-09-15 17:19:37 +0100547 if (GA_GROW_FAILS(&ectx->ec_stack,
548 arg_to_add + STACK_FRAME_SIZE + varcount))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100549 return FAIL;
550
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100551 // If depth of calling is getting too high, don't execute the function.
552 if (funcdepth_increment() == FAIL)
553 return FAIL;
Bram Moolenaare99d4222021-06-13 14:01:26 +0200554 ++ex_nesting_level;
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100555
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100556 // Only make a copy of funclocal if it contains something to restore.
Bram Moolenaar4c137212021-04-19 16:48:48 +0200557 if (ectx->ec_funclocal.floc_restore_cmdmod)
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100558 {
559 floc = ALLOC_ONE(funclocal_T);
560 if (floc == NULL)
561 return FAIL;
Bram Moolenaar4c137212021-04-19 16:48:48 +0200562 *floc = ectx->ec_funclocal;
563 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100564 }
565
Bram Moolenaarfe270812020-04-11 22:31:27 +0200566 // Move the vararg-list to below the missing optional arguments.
567 if (vararg_count > 0 && arg_to_add > 0)
568 *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100569
570 // Reserve space for omitted optional arguments, filled in soon.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200571 for (idx = 0; idx < arg_to_add; ++idx)
Bram Moolenaarfe270812020-04-11 22:31:27 +0200572 STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200573 ectx->ec_stack.ga_len += arg_to_add;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100574
575 // Store current execution state in stack frame for ISN_RETURN.
Bram Moolenaar0186e582021-01-10 18:33:11 +0100576 STACK_TV_BOT(STACK_FRAME_FUNC_OFF)->vval.v_number = ectx->ec_dfunc_idx;
577 STACK_TV_BOT(STACK_FRAME_IIDX_OFF)->vval.v_number = ectx->ec_iidx;
Bram Moolenaar5930ddc2021-04-26 20:32:59 +0200578 STACK_TV_BOT(STACK_FRAME_INSTR_OFF)->vval.v_string = (void *)ectx->ec_instr;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200579 STACK_TV_BOT(STACK_FRAME_OUTER_OFF)->vval.v_string =
580 (void *)ectx->ec_outer_ref;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100581 STACK_TV_BOT(STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string = (void *)floc;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100582 STACK_TV_BOT(STACK_FRAME_IDX_OFF)->vval.v_number = ectx->ec_frame_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200583 ectx->ec_frame_idx = ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100584
Bram Moolenaar5800c792022-09-22 17:34:01 +0100585 // Initialize all local variables to number zero. Also initialize the
586 // variable that counts how many closures were created. This is used in
587 // handle_closure_in_use().
588 int initcount = dfunc->df_varcount + (dfunc->df_has_closure ? 1 : 0);
589 for (idx = 0; idx < initcount; ++idx)
Bram Moolenaar5cd64792021-12-25 18:23:24 +0000590 {
591 typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + idx);
592
593 tv->v_type = VAR_NUMBER;
594 tv->vval.v_number = 0;
595 }
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200596 ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100597
Bram Moolenaar5800c792022-09-22 17:34:01 +0100598 partial_T *pt = pt_arg != NULL ? pt_arg : ufunc->uf_partial;
599 if (pt != NULL || (ufunc->uf_flags & FC_CLOSURE))
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100600 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200601 outer_ref_T *ref = ALLOC_CLEAR_ONE(outer_ref_T);
Bram Moolenaar0186e582021-01-10 18:33:11 +0100602
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200603 if (ref == NULL)
Bram Moolenaar0186e582021-01-10 18:33:11 +0100604 return FAIL;
605 if (pt != NULL)
606 {
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +0000607 ref->or_outer = get_pt_outer(pt);
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200608 ++pt->pt_refcount;
609 ref->or_partial = pt;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100610 }
Bram Moolenaar0186e582021-01-10 18:33:11 +0100611 else
612 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200613 ref->or_outer = ALLOC_CLEAR_ONE(outer_T);
Dominique Pelle5a9e5842021-07-24 19:32:12 +0200614 if (unlikely(ref->or_outer == NULL))
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200615 {
616 vim_free(ref);
617 return FAIL;
618 }
619 ref->or_outer_allocated = TRUE;
620 ref->or_outer->out_stack = &ectx->ec_stack;
621 ref->or_outer->out_frame_idx = ectx->ec_frame_idx;
622 if (ectx->ec_outer_ref != NULL)
623 ref->or_outer->out_up = ectx->ec_outer_ref->or_outer;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100624 }
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200625 ectx->ec_outer_ref = ref;
Bram Moolenaarab360522021-01-10 14:02:28 +0100626 }
Bram Moolenaar0186e582021-01-10 18:33:11 +0100627 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200628 ectx->ec_outer_ref = NULL;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100629
Bram Moolenaarc970e422021-03-17 15:03:04 +0100630 ++ufunc->uf_calls;
631
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100632 // Set execution state to the start of the called function.
633 ectx->ec_dfunc_idx = cdf_idx;
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100634 ectx->ec_instr = INSTRUCTIONS(dfunc);
Bram Moolenaarb2049902021-01-24 12:53:53 +0100635 entry = estack_push_ufunc(ufunc, 1);
Bram Moolenaarc620c052020-07-08 15:16:19 +0200636 if (entry != NULL)
637 {
638 // Set the script context to the script where the function was defined.
Bram Moolenaarc70fe462021-04-17 17:59:19 +0200639 // Save the current context so it can be restored on return.
640 entry->es_save_sctx = current_sctx;
641 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaarc620c052020-07-08 15:16:19 +0200642 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100643
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200644 // Start execution at the first instruction.
645 ectx->ec_iidx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100646
647 return OK;
648}
649
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000650// Double linked list of funcstack_T in use.
651static funcstack_T *first_funcstack = NULL;
652
653 static void
654add_funcstack_to_list(funcstack_T *funcstack)
655{
656 // Link in list of funcstacks.
657 if (first_funcstack != NULL)
658 first_funcstack->fs_prev = funcstack;
659 funcstack->fs_next = first_funcstack;
660 funcstack->fs_prev = NULL;
661 first_funcstack = funcstack;
662}
663
664 static void
665remove_funcstack_from_list(funcstack_T *funcstack)
666{
667 if (funcstack->fs_prev == NULL)
668 first_funcstack = funcstack->fs_next;
669 else
670 funcstack->fs_prev->fs_next = funcstack->fs_next;
671 if (funcstack->fs_next != NULL)
672 funcstack->fs_next->fs_prev = funcstack->fs_prev;
673}
674
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100675/*
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200676 * Used when returning from a function: Check if any closure is still
677 * referenced. If so then move the arguments and variables to a separate piece
678 * of stack to be used when the closure is called.
679 * When "free_arguments" is TRUE the arguments are to be freed.
680 * Returns FAIL when out of memory.
681 */
682 static int
683handle_closure_in_use(ectx_T *ectx, int free_arguments)
684{
685 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
686 + ectx->ec_dfunc_idx;
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200687 int argcount;
688 int top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200689 int idx;
690 typval_T *tv;
691 int closure_in_use = FALSE;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200692 garray_T *gap = &ectx->ec_funcrefs;
693 varnumber_T closure_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200694
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200695 if (dfunc->df_ufunc == NULL)
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200696 return OK; // function was freed
697 if (dfunc->df_has_closure == 0)
698 return OK; // no closures
699 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + dfunc->df_varcount);
700 closure_count = tv->vval.v_number;
701 if (closure_count == 0)
702 return OK; // no funcrefs created
703
Bram Moolenaar8fa745e2022-09-16 19:04:24 +0100704 // Compute "top": the first entry in the stack used by the function.
705 // This is the first argument (after that comes the stack frame and then
706 // the local variables).
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200707 argcount = ufunc_argcount(dfunc->df_ufunc);
708 top = ectx->ec_frame_idx - argcount;
709
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200710 // Check if any created closure is still in use.
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200711 for (idx = 0; idx < closure_count; ++idx)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200712 {
Bram Moolenaarc70bdab2020-09-26 19:59:38 +0200713 partial_T *pt;
714 int off = gap->ga_len - closure_count + idx;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200715
Bram Moolenaarc70bdab2020-09-26 19:59:38 +0200716 if (off < 0)
717 continue; // count is off or already done
718 pt = ((partial_T **)gap->ga_data)[off];
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200719 if (pt->pt_refcount > 1)
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200720 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200721 int refcount = pt->pt_refcount;
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200722 int i;
723
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000724 // A Reference in a local variable doesn't count, it gets
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200725 // unreferenced on return.
726 for (i = 0; i < dfunc->df_varcount; ++i)
727 {
728 typval_T *stv = STACK_TV(ectx->ec_frame_idx
729 + STACK_FRAME_SIZE + i);
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200730 if (stv->v_type == VAR_PARTIAL && pt == stv->vval.v_partial)
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200731 --refcount;
732 }
733 if (refcount > 1)
734 {
735 closure_in_use = TRUE;
736 break;
737 }
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200738 }
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200739 }
740
741 if (closure_in_use)
742 {
743 funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T);
744 typval_T *stack;
745
746 // A closure is using the arguments and/or local variables.
747 // Move them to the called function.
748 if (funcstack == NULL)
749 return FAIL;
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000750
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200751 funcstack->fs_var_offset = argcount + STACK_FRAME_SIZE;
Bram Moolenaar1936c762022-09-28 15:19:10 +0100752 funcstack->fs_ga.ga_len = funcstack->fs_var_offset
753 + dfunc->df_varcount;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200754 stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len);
755 funcstack->fs_ga.ga_data = stack;
756 if (stack == NULL)
757 {
758 vim_free(funcstack);
759 return FAIL;
760 }
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000761 add_funcstack_to_list(funcstack);
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200762
763 // Move or copy the arguments.
764 for (idx = 0; idx < argcount; ++idx)
765 {
766 tv = STACK_TV(top + idx);
767 if (free_arguments)
768 {
769 *(stack + idx) = *tv;
770 tv->v_type = VAR_UNKNOWN;
771 }
772 else
773 copy_tv(tv, stack + idx);
774 }
Bram Moolenaar8fa745e2022-09-16 19:04:24 +0100775 // Skip the stack frame.
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200776 // Move the local variables.
777 for (idx = 0; idx < dfunc->df_varcount; ++idx)
778 {
779 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx);
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200780
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200781 // A partial created for a local function, that is also used as a
782 // local variable, has a reference count for the variable, thus
783 // will never go down to zero. When all these refcounts are one
784 // then the funcstack is unused. We need to count how many we have
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000785 // so we know when to check.
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200786 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
787 {
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200788 int i;
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200789
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200790 for (i = 0; i < closure_count; ++i)
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200791 if (tv->vval.v_partial == ((partial_T **)gap->ga_data)[
792 gap->ga_len - closure_count + i])
793 ++funcstack->fs_min_refcount;
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200794 }
795
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200796 *(stack + funcstack->fs_var_offset + idx) = *tv;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200797 tv->v_type = VAR_UNKNOWN;
798 }
799
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200800 for (idx = 0; idx < closure_count; ++idx)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200801 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200802 partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len
803 - closure_count + idx];
804 if (pt->pt_refcount > 1)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200805 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200806 ++funcstack->fs_refcount;
807 pt->pt_funcstack = funcstack;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100808 pt->pt_outer.out_stack = &funcstack->fs_ga;
809 pt->pt_outer.out_frame_idx = ectx->ec_frame_idx - top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200810 }
811 }
812 }
813
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200814 for (idx = 0; idx < closure_count; ++idx)
815 partial_unref(((partial_T **)gap->ga_data)[gap->ga_len
816 - closure_count + idx]);
817 gap->ga_len -= closure_count;
818 if (gap->ga_len == 0)
819 ga_clear(gap);
820
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200821 return OK;
822}
823
824/*
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200825 * Called when a partial is freed or its reference count goes down to one. The
826 * funcstack may be the only reference to the partials in the local variables.
827 * Go over all of them, the funcref and can be freed if all partials
828 * referencing the funcstack have a reference count of one.
Bram Moolenaaracd6b992022-09-17 16:27:39 +0100829 * Returns TRUE if the funcstack is freed, the partial referencing it will then
830 * also have been freed.
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200831 */
Bram Moolenaaracd6b992022-09-17 16:27:39 +0100832 int
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200833funcstack_check_refcount(funcstack_T *funcstack)
834{
Bram Moolenaaracd6b992022-09-17 16:27:39 +0100835 int i;
836 garray_T *gap = &funcstack->fs_ga;
837 int done = 0;
838 typval_T *stack;
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200839
840 if (funcstack->fs_refcount > funcstack->fs_min_refcount)
Bram Moolenaaracd6b992022-09-17 16:27:39 +0100841 return FALSE;
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200842 for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i)
843 {
844 typval_T *tv = ((typval_T *)gap->ga_data) + i;
845
846 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL
847 && tv->vval.v_partial->pt_funcstack == funcstack
848 && tv->vval.v_partial->pt_refcount == 1)
849 ++done;
850 }
Bram Moolenaaracd6b992022-09-17 16:27:39 +0100851 if (done != funcstack->fs_min_refcount)
852 return FALSE;
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200853
Bram Moolenaaracd6b992022-09-17 16:27:39 +0100854 stack = gap->ga_data;
855
856 // All partials referencing the funcstack have a reference count of
857 // one, thus the funcstack is no longer of use.
858 for (i = 0; i < gap->ga_len; ++i)
859 clear_tv(stack + i);
860 vim_free(stack);
861 remove_funcstack_from_list(funcstack);
862 vim_free(funcstack);
863
864 return TRUE;
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200865}
866
867/*
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000868 * For garbage collecting: set references in all variables referenced by
869 * all funcstacks.
870 */
871 int
872set_ref_in_funcstacks(int copyID)
873{
874 funcstack_T *funcstack;
875
876 for (funcstack = first_funcstack; funcstack != NULL;
877 funcstack = funcstack->fs_next)
878 {
879 typval_T *stack = funcstack->fs_ga.ga_data;
880 int i;
881
882 for (i = 0; i < funcstack->fs_ga.ga_len; ++i)
883 if (set_ref_in_item(stack + i, copyID, NULL, NULL))
884 return TRUE; // abort
885 }
886 return FALSE;
887}
888
Bram Moolenaar806a2732022-09-04 15:40:36 +0100889// Ugly static to avoid passing the execution context around through many
890// layers.
891static ectx_T *current_ectx = NULL;
892
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000893/*
Bram Moolenaar806a2732022-09-04 15:40:36 +0100894 * Return TRUE if currently executing a :def function.
895 * Can be used by builtin functions only.
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100896 */
Bram Moolenaar806a2732022-09-04 15:40:36 +0100897 int
898in_def_function(void)
899{
900 return current_ectx != NULL;
901}
902
903/*
Bram Moolenaar98aff652022-09-06 21:02:35 +0100904 * Clear "current_ectx" and return the previous value. To be used when calling
905 * a user function.
906 */
907 ectx_T *
dundargocc57b5bc2022-11-02 13:30:51 +0000908clear_current_ectx(void)
Bram Moolenaar98aff652022-09-06 21:02:35 +0100909{
910 ectx_T *r = current_ectx;
911
912 current_ectx = NULL;
913 return r;
914}
915
916 void
917restore_current_ectx(ectx_T *ectx)
918{
919 if (current_ectx != NULL)
920 iemsg("Restoring current_ectx while it is not NULL");
921 current_ectx = ectx;
922}
923
924/*
Bram Moolenaar806a2732022-09-04 15:40:36 +0100925 * Add an entry for a deferred function call to the currently executing
926 * function.
927 * Return the list or NULL when failed.
928 */
929 static list_T *
930add_defer_item(int var_idx, int argcount, ectx_T *ectx)
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100931{
932 typval_T *defer_tv = STACK_TV_VAR(var_idx);
933 list_T *defer_l;
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100934 list_T *l;
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100935 typval_T listval;
936
937 if (defer_tv->v_type != VAR_LIST)
938 {
Bram Moolenaara5348f22022-09-04 11:42:22 +0100939 // first time, allocate the list
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100940 if (rettv_list_alloc(defer_tv) == FAIL)
Bram Moolenaar806a2732022-09-04 15:40:36 +0100941 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100942 }
943 defer_l = defer_tv->vval.v_list;
944
945 l = list_alloc_with_items(argcount + 1);
946 if (l == NULL)
Bram Moolenaar806a2732022-09-04 15:40:36 +0100947 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100948 listval.v_type = VAR_LIST;
949 listval.vval.v_list = l;
950 listval.v_lock = 0;
Bram Moolenaara5348f22022-09-04 11:42:22 +0100951 if (list_insert_tv(defer_l, &listval, defer_l->lv_first) == FAIL)
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100952 {
953 vim_free(l);
Bram Moolenaar806a2732022-09-04 15:40:36 +0100954 return NULL;
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100955 }
956
Bram Moolenaar806a2732022-09-04 15:40:36 +0100957 return l;
958}
959
960/*
961 * Handle ISN_DEFER. Stack has a function reference and "argcount" arguments.
962 * The local variable that lists deferred functions is "var_idx".
963 * Returns OK or FAIL.
964 */
965 static int
966defer_command(int var_idx, int argcount, ectx_T *ectx)
967{
968 list_T *l = add_defer_item(var_idx, argcount, ectx);
969 int i;
970 typval_T *func_tv;
971
972 if (l == NULL)
973 return FAIL;
974
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100975 func_tv = STACK_TV_BOT(-argcount - 1);
Bram Moolenaarf5fec052022-09-11 11:49:22 +0100976 if (func_tv->v_type != VAR_FUNC && func_tv->v_type != VAR_PARTIAL)
977 {
978 semsg(_(e_expected_str_but_got_str),
979 "function or partial",
980 vartype_name(func_tv->v_type));
981 return FAIL;
982 }
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100983 list_set_item(l, 0, func_tv);
984
Bram Moolenaarf5fec052022-09-11 11:49:22 +0100985 for (i = 0; i < argcount; ++i)
986 list_set_item(l, i + 1, STACK_TV_BOT(-argcount + i));
Bram Moolenaar1d84f762022-09-03 21:35:53 +0100987 ectx->ec_stack.ga_len -= argcount + 1;
988 return OK;
989}
990
991/*
Bram Moolenaar806a2732022-09-04 15:40:36 +0100992 * Add a deferred function "name" with one argument "arg_tv".
993 * Consumes "name", also on failure.
994 * Only to be called when in_def_function() returns TRUE.
995 */
996 int
997add_defer_function(char_u *name, int argcount, typval_T *argvars)
998{
999 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1000 + current_ectx->ec_dfunc_idx;
1001 list_T *l;
1002 typval_T func_tv;
1003 int i;
1004
1005 if (dfunc->df_defer_var_idx == 0)
1006 {
1007 iemsg("df_defer_var_idx is zero");
Bram Moolenaar31ea6bf2022-09-05 10:47:13 +01001008 vim_free(name);
Bram Moolenaar806a2732022-09-04 15:40:36 +01001009 return FAIL;
1010 }
Bram Moolenaar806a2732022-09-04 15:40:36 +01001011
Bram Moolenaarf5fec052022-09-11 11:49:22 +01001012 l = add_defer_item(dfunc->df_defer_var_idx - 1, argcount, current_ectx);
Bram Moolenaar806a2732022-09-04 15:40:36 +01001013 if (l == NULL)
1014 {
Bram Moolenaar31ea6bf2022-09-05 10:47:13 +01001015 vim_free(name);
Bram Moolenaar806a2732022-09-04 15:40:36 +01001016 return FAIL;
1017 }
1018
Bram Moolenaar31ea6bf2022-09-05 10:47:13 +01001019 func_tv.v_type = VAR_FUNC;
1020 func_tv.v_lock = 0;
1021 func_tv.vval.v_string = name;
Bram Moolenaar806a2732022-09-04 15:40:36 +01001022 list_set_item(l, 0, &func_tv);
Bram Moolenaar31ea6bf2022-09-05 10:47:13 +01001023
Bram Moolenaar806a2732022-09-04 15:40:36 +01001024 for (i = 0; i < argcount; ++i)
1025 list_set_item(l, i + 1, argvars + i);
1026 return OK;
1027}
1028
1029/*
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001030 * Invoked when returning from a function: Invoke any deferred calls.
1031 */
1032 static void
1033invoke_defer_funcs(ectx_T *ectx)
1034{
1035 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1036 + ectx->ec_dfunc_idx;
1037 typval_T *defer_tv = STACK_TV_VAR(dfunc->df_defer_var_idx - 1);
1038 listitem_T *li;
1039
1040 if (defer_tv->v_type != VAR_LIST)
1041 return; // no function added
1042 for (li = defer_tv->vval.v_list->lv_first; li != NULL; li = li->li_next)
1043 {
1044 list_T *l = li->li_tv.vval.v_list;
1045 typval_T rettv;
1046 typval_T argvars[MAX_FUNC_ARGS];
1047 int i;
1048 listitem_T *arg_li = l->lv_first;
1049 funcexe_T funcexe;
1050
1051 for (i = 0; i < l->lv_len - 1; ++i)
1052 {
1053 arg_li = arg_li->li_next;
1054 argvars[i] = arg_li->li_tv;
1055 }
1056
1057 CLEAR_FIELD(funcexe);
1058 funcexe.fe_evaluate = TRUE;
1059 rettv.v_type = VAR_UNKNOWN;
1060 (void)call_func(l->lv_first->li_tv.vval.v_string, -1,
1061 &rettv, l->lv_len - 1, argvars, &funcexe);
1062 clear_tv(&rettv);
1063 }
1064}
1065
1066/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001067 * Return from the current function.
1068 */
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001069 static int
Bram Moolenaar4c137212021-04-19 16:48:48 +02001070func_return(ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001071{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001072 int idx;
Bram Moolenaar34c54eb2020-11-25 19:15:19 +01001073 int ret_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001074 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1075 + ectx->ec_dfunc_idx;
1076 int argcount = ufunc_argcount(dfunc->df_ufunc);
1077 int top = ectx->ec_frame_idx - argcount;
Bram Moolenaarc620c052020-07-08 15:16:19 +02001078 estack_T *entry;
Bram Moolenaar12d26532021-02-19 19:13:21 +01001079 int prev_dfunc_idx = STACK_TV(ectx->ec_frame_idx
1080 + STACK_FRAME_FUNC_OFF)->vval.v_number;
Bram Moolenaarb06b50d2021-04-26 21:39:25 +02001081 funclocal_T *floc;
1082#ifdef FEAT_PROFILE
Bram Moolenaar12d26532021-02-19 19:13:21 +01001083 dfunc_T *prev_dfunc = ((dfunc_T *)def_functions.ga_data)
1084 + prev_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001085
Bram Moolenaar12d26532021-02-19 19:13:21 +01001086 if (do_profiling == PROF_YES)
1087 {
1088 ufunc_T *caller = prev_dfunc->df_ufunc;
1089
1090 if (dfunc->df_ufunc->uf_profiling
1091 || (caller != NULL && caller->uf_profiling))
1092 {
1093 profile_may_end_func(((profinfo_T *)profile_info_ga.ga_data)
1094 + profile_info_ga.ga_len - 1, dfunc->df_ufunc, caller);
1095 --profile_info_ga.ga_len;
1096 }
1097 }
1098#endif
Bram Moolenaar919c12c2021-12-14 14:29:16 +00001099
Bram Moolenaar1d84f762022-09-03 21:35:53 +01001100 if (dfunc->df_defer_var_idx > 0)
1101 invoke_defer_funcs(ectx);
1102
Bram Moolenaar919c12c2021-12-14 14:29:16 +00001103 // No check for uf_refcount being zero, cannot think of a way that would
1104 // happen.
Bram Moolenaarc970e422021-03-17 15:03:04 +01001105 --dfunc->df_ufunc->uf_calls;
1106
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001107 // execution context goes one level up
Bram Moolenaarc620c052020-07-08 15:16:19 +02001108 entry = estack_pop();
1109 if (entry != NULL)
Bram Moolenaarc70fe462021-04-17 17:59:19 +02001110 current_sctx = entry->es_save_sctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001111
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001112 if (handle_closure_in_use(ectx, TRUE) == FAIL)
1113 return FAIL;
1114
1115 // Clear the arguments.
1116 for (idx = top; idx < ectx->ec_frame_idx; ++idx)
1117 clear_tv(STACK_TV(idx));
1118
1119 // Clear local variables and temp values, but not the return value.
1120 for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001121 idx < ectx->ec_stack.ga_len - 1; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001122 clear_tv(STACK_TV(idx));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001123
Bram Moolenaar34c54eb2020-11-25 19:15:19 +01001124 // The return value should be on top of the stack. However, when aborting
1125 // it may not be there and ec_frame_idx is the top of the stack.
1126 ret_idx = ectx->ec_stack.ga_len - 1;
Bram Moolenaar0186e582021-01-10 18:33:11 +01001127 if (ret_idx == ectx->ec_frame_idx + STACK_FRAME_IDX_OFF)
Bram Moolenaar34c54eb2020-11-25 19:15:19 +01001128 ret_idx = 0;
1129
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001130 if (ectx->ec_outer_ref != NULL)
1131 {
1132 if (ectx->ec_outer_ref->or_outer_allocated)
1133 vim_free(ectx->ec_outer_ref->or_outer);
1134 partial_unref(ectx->ec_outer_ref->or_partial);
1135 vim_free(ectx->ec_outer_ref);
1136 }
Bram Moolenaar0186e582021-01-10 18:33:11 +01001137
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001138 // Restore the previous frame.
Bram Moolenaar12d26532021-02-19 19:13:21 +01001139 ectx->ec_dfunc_idx = prev_dfunc_idx;
Bram Moolenaar0186e582021-01-10 18:33:11 +01001140 ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx
1141 + STACK_FRAME_IIDX_OFF)->vval.v_number;
Bram Moolenaar5930ddc2021-04-26 20:32:59 +02001142 ectx->ec_instr = (void *)STACK_TV(ectx->ec_frame_idx
1143 + STACK_FRAME_INSTR_OFF)->vval.v_string;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001144 ectx->ec_outer_ref = (void *)STACK_TV(ectx->ec_frame_idx
Bram Moolenaar0186e582021-01-10 18:33:11 +01001145 + STACK_FRAME_OUTER_OFF)->vval.v_string;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001146 floc = (void *)STACK_TV(ectx->ec_frame_idx
1147 + STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string;
Bram Moolenaar5366e1a2020-10-01 13:01:34 +02001148 // restoring ec_frame_idx must be last
Bram Moolenaar0186e582021-01-10 18:33:11 +01001149 ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx
1150 + STACK_FRAME_IDX_OFF)->vval.v_number;
Bram Moolenaard386e922021-04-25 14:48:49 +02001151
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001152 if (floc == NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02001153 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001154 else
1155 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02001156 ectx->ec_funclocal = *floc;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001157 vim_free(floc);
1158 }
1159
Bram Moolenaar34c54eb2020-11-25 19:15:19 +01001160 if (ret_idx > 0)
1161 {
1162 // Reset the stack to the position before the call, with a spot for the
1163 // return value, moved there from above the frame.
1164 ectx->ec_stack.ga_len = top + 1;
1165 *STACK_TV_BOT(-1) = *STACK_TV(ret_idx);
1166 }
1167 else
1168 // Reset the stack to the position before the call.
1169 ectx->ec_stack.ga_len = top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001170
Bram Moolenaar0ba48e82020-11-17 18:23:19 +01001171 funcdepth_decrement();
Bram Moolenaare99d4222021-06-13 14:01:26 +02001172 --ex_nesting_level;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001173 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001174}
1175
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001176/*
1177 * Prepare arguments and rettv for calling a builtin or user function.
1178 */
1179 static int
1180call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
1181{
1182 int idx;
1183 typval_T *tv;
1184
1185 // Move arguments from bottom of the stack to argvars[] and add terminator.
1186 for (idx = 0; idx < argcount; ++idx)
1187 argvars[idx] = *STACK_TV_BOT(idx - argcount);
1188 argvars[argcount].v_type = VAR_UNKNOWN;
1189
1190 // Result replaces the arguments on the stack.
1191 if (argcount > 0)
1192 ectx->ec_stack.ga_len -= argcount - 1;
Bram Moolenaar35578162021-08-02 19:10:38 +02001193 else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001194 return FAIL;
1195 else
1196 ++ectx->ec_stack.ga_len;
1197
1198 // Default return value is zero.
1199 tv = STACK_TV_BOT(-1);
1200 tv->v_type = VAR_NUMBER;
1201 tv->vval.v_number = 0;
Bram Moolenaar24565cf2022-03-28 18:16:52 +01001202 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001203
1204 return OK;
1205}
1206
1207/*
1208 * Call a builtin function by index.
1209 */
1210 static int
1211call_bfunc(int func_idx, int argcount, ectx_T *ectx)
1212{
1213 typval_T argvars[MAX_FUNC_ARGS];
1214 int idx;
Bram Moolenaar171fb922020-10-28 16:54:47 +01001215 int did_emsg_before = did_emsg;
Bram Moolenaar08f7a412020-07-13 20:41:08 +02001216 ectx_T *prev_ectx = current_ectx;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02001217 char *save_func_name = ectx->ec_where.wt_func_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001218
1219 if (call_prepare(argcount, argvars, ectx) == FAIL)
1220 return FAIL;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02001221 ectx->ec_where.wt_func_name = internal_func_name(func_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001222
Bram Moolenaar08f7a412020-07-13 20:41:08 +02001223 // Call the builtin function. Set "current_ectx" so that when it
1224 // recursively invokes call_def_function() a closure context can be set.
1225 current_ectx = ectx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001226 call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1));
Bram Moolenaar08f7a412020-07-13 20:41:08 +02001227 current_ectx = prev_ectx;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02001228 ectx->ec_where.wt_func_name = save_func_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001229
1230 // Clear the arguments.
1231 for (idx = 0; idx < argcount; ++idx)
1232 clear_tv(&argvars[idx]);
Bram Moolenaar015f4262020-05-05 21:25:22 +02001233
Bram Moolenaar57f799e2020-12-12 20:42:19 +01001234 if (did_emsg > did_emsg_before)
Bram Moolenaar015f4262020-05-05 21:25:22 +02001235 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001236 return OK;
1237}
1238
1239/*
1240 * Execute a user defined function.
Bram Moolenaarab360522021-01-10 14:02:28 +01001241 * If the function is compiled this will add a stack frame and set the
1242 * instruction pointer at the start of the function.
1243 * Otherwise the function is called here.
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001244 * If "pt" is not null use "pt->pt_outer" for ec_outer_ref->or_outer.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001245 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001246 */
1247 static int
Bram Moolenaar0186e582021-01-10 18:33:11 +01001248call_ufunc(
1249 ufunc_T *ufunc,
1250 partial_T *pt,
1251 int argcount,
1252 ectx_T *ectx,
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001253 isn_T *iptr,
1254 dict_T *selfdict)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001255{
1256 typval_T argvars[MAX_FUNC_ARGS];
1257 funcexe_T funcexe;
1258 int error;
1259 int idx;
Bram Moolenaar28ee8922020-10-28 20:20:00 +01001260 int did_emsg_before = did_emsg;
Bram Moolenaar139575d2022-03-15 19:29:30 +00001261 compiletype_T compile_type = get_compile_type(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001262
Bram Moolenaare99d4222021-06-13 14:01:26 +02001263 if (func_needs_compiling(ufunc, compile_type)
1264 && compile_def_function(ufunc, FALSE, compile_type, NULL)
1265 == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02001266 return FAIL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001267 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001268 {
Bram Moolenaar52c124d2020-12-20 21:43:35 +01001269 error = check_user_func_argcount(ufunc, argcount);
Bram Moolenaar50824712020-12-20 21:10:17 +01001270 if (error != FCERR_UNKNOWN)
1271 {
1272 if (error == FCERR_TOOMANY)
Bram Moolenaara6c18d32022-03-31 20:02:56 +01001273 semsg(_(e_too_many_arguments_for_function_str),
1274 printable_func_name(ufunc));
Bram Moolenaar50824712020-12-20 21:10:17 +01001275 else
Bram Moolenaare1242042021-12-16 20:56:57 +00001276 semsg(_(e_not_enough_arguments_for_function_str),
Bram Moolenaara6c18d32022-03-31 20:02:56 +01001277 printable_func_name(ufunc));
Bram Moolenaar50824712020-12-20 21:10:17 +01001278 return FAIL;
1279 }
1280
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001281 // The function has been compiled, can call it quickly. For a function
1282 // that was defined later: we can call it directly next time.
1283 if (iptr != NULL)
1284 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001285 delete_instr(iptr);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001286 iptr->isn_type = ISN_DCALL;
1287 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1288 iptr->isn_arg.dfunc.cdf_argcount = argcount;
1289 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02001290 return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, ectx);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001291 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001292
1293 if (call_prepare(argcount, argvars, ectx) == FAIL)
1294 return FAIL;
Bram Moolenaara80faa82020-04-12 19:37:17 +02001295 CLEAR_FIELD(funcexe);
Bram Moolenaar851f86b2021-12-13 14:26:44 +00001296 funcexe.fe_evaluate = TRUE;
1297 funcexe.fe_selfdict = selfdict != NULL ? selfdict : dict_stack_get_dict();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001298
1299 // Call the user function. Result goes in last position on the stack.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001300 error = call_user_func_check(ufunc, argcount, argvars,
Bram Moolenaar851f86b2021-12-13 14:26:44 +00001301 STACK_TV_BOT(-1), &funcexe, funcexe.fe_selfdict);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001302
1303 // Clear the arguments.
1304 for (idx = 0; idx < argcount; ++idx)
1305 clear_tv(&argvars[idx]);
1306
1307 if (error != FCERR_NONE)
1308 {
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +01001309 user_func_error(error, printable_func_name(ufunc),
1310 funcexe.fe_found_var);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001311 return FAIL;
1312 }
Bram Moolenaar28ee8922020-10-28 20:20:00 +01001313 if (did_emsg > did_emsg_before)
Bram Moolenaared677f52020-08-12 16:38:10 +02001314 // Error other than from calling the function itself.
1315 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001316 return OK;
1317}
1318
1319/*
Bram Moolenaara91a7132021-03-25 21:12:15 +01001320 * If command modifiers were applied restore them.
1321 */
1322 static void
1323may_restore_cmdmod(funclocal_T *funclocal)
1324{
1325 if (funclocal->floc_restore_cmdmod)
1326 {
1327 cmdmod.cmod_filter_regmatch.regprog = NULL;
1328 undo_cmdmod(&cmdmod);
1329 cmdmod = funclocal->floc_save_cmdmod;
1330 funclocal->floc_restore_cmdmod = FALSE;
1331 }
1332}
1333
1334/*
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001335 * Return TRUE if an error was given (not caught in try/catch) or CTRL-C was
1336 * pressed.
Bram Moolenaara1773442020-08-12 15:21:22 +02001337 */
1338 static int
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001339vim9_aborting(int prev_uncaught_emsg)
Bram Moolenaara1773442020-08-12 15:21:22 +02001340{
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001341 return uncaught_emsg > prev_uncaught_emsg || got_int || did_throw;
Bram Moolenaara1773442020-08-12 15:21:22 +02001342}
1343
1344/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001345 * Execute a function by "name".
1346 * This can be a builtin function or a user function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001347 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001348 * Returns FAIL if not found without an error message.
1349 */
1350 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001351call_by_name(
1352 char_u *name,
1353 int argcount,
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001354 ectx_T *ectx,
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001355 isn_T *iptr,
1356 dict_T *selfdict)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001357{
1358 ufunc_T *ufunc;
1359
1360 if (builtin_function(name, -1))
1361 {
1362 int func_idx = find_internal_func(name);
1363
Bram Moolenaar1983f1a2022-02-28 20:55:02 +00001364 if (func_idx < 0) // Impossible?
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001365 return FAIL;
Bram Moolenaar389df252020-07-09 21:20:47 +02001366 if (check_internal_func(func_idx, argcount) < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001367 return FAIL;
1368 return call_bfunc(func_idx, argcount, ectx);
1369 }
1370
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00001371 ufunc = find_func(name, FALSE);
Bram Moolenaara1773442020-08-12 15:21:22 +02001372
1373 if (ufunc == NULL)
1374 {
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001375 int prev_uncaught_emsg = uncaught_emsg;
Bram Moolenaara1773442020-08-12 15:21:22 +02001376
1377 if (script_autoload(name, TRUE))
1378 // loaded a package, search for the function again
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00001379 ufunc = find_func(name, FALSE);
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001380
1381 if (vim9_aborting(prev_uncaught_emsg))
Bram Moolenaara1773442020-08-12 15:21:22 +02001382 return FAIL; // bail out if loading the script caused an error
1383 }
1384
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001385 if (ufunc != NULL)
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001386 {
Bram Moolenaar0d89d8a2022-12-31 14:01:24 +00001387 if (check_ufunc_arg_types(ufunc, argcount, 0, ectx) == FAIL)
1388 return FAIL;
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001389
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001390 return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict);
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001391 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001392
1393 return FAIL;
1394}
1395
1396 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001397call_partial(
1398 typval_T *tv,
1399 int argcount_arg,
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001400 ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001401{
Bram Moolenaara90afb92020-07-15 22:38:56 +02001402 int argcount = argcount_arg;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001403 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001404 int called_emsg_before = called_emsg;
Bram Moolenaarcb6cbf22021-01-12 17:17:01 +01001405 int res = FAIL;
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001406 dict_T *selfdict = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001407
1408 if (tv->v_type == VAR_PARTIAL)
1409 {
Bram Moolenaara90afb92020-07-15 22:38:56 +02001410 partial_T *pt = tv->vval.v_partial;
1411 int i;
1412
1413 if (pt->pt_argc > 0)
1414 {
1415 // Make space for arguments from the partial, shift the "argcount"
1416 // arguments up.
Bram Moolenaar35578162021-08-02 19:10:38 +02001417 if (GA_GROW_FAILS(&ectx->ec_stack, pt->pt_argc))
Bram Moolenaara90afb92020-07-15 22:38:56 +02001418 return FAIL;
1419 for (i = 1; i <= argcount; ++i)
1420 *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i);
1421 ectx->ec_stack.ga_len += pt->pt_argc;
1422 argcount += pt->pt_argc;
1423
1424 // copy the arguments from the partial onto the stack
1425 for (i = 0; i < pt->pt_argc; ++i)
1426 copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i));
1427 }
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001428 selfdict = pt->pt_dict;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001429
1430 if (pt->pt_func != NULL)
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001431 return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL, selfdict);
Bram Moolenaarf7779c62020-05-03 15:38:16 +02001432
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001433 name = pt->pt_name;
1434 }
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001435 else if (tv->v_type == VAR_FUNC)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001436 name = tv->vval.v_string;
Bram Moolenaar95006e32020-08-29 17:47:08 +02001437 if (name != NULL)
1438 {
1439 char_u fname_buf[FLEN_FIXED + 1];
1440 char_u *tofree = NULL;
1441 int error = FCERR_NONE;
1442 char_u *fname;
1443
1444 // May need to translate <SNR>123_ to K_SNR.
1445 fname = fname_trans_sid(name, fname_buf, &tofree, &error);
1446 if (error != FCERR_NONE)
1447 res = FAIL;
1448 else
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001449 res = call_by_name(fname, argcount, ectx, NULL, selfdict);
Bram Moolenaar95006e32020-08-29 17:47:08 +02001450 vim_free(tofree);
1451 }
1452
Bram Moolenaarcb6cbf22021-01-12 17:17:01 +01001453 if (res == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001454 {
1455 if (called_emsg == called_emsg_before)
Bram Moolenaara6c18d32022-03-31 20:02:56 +01001456 emsg_funcname(e_unknown_function_str,
Bram Moolenaar015f4262020-05-05 21:25:22 +02001457 name == NULL ? (char_u *)"[unknown]" : name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001458 return FAIL;
1459 }
1460 return OK;
1461}
1462
1463/*
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001464 * Check if "lock" is VAR_LOCKED or VAR_FIXED. If so give an error and return
1465 * TRUE.
1466 */
1467 static int
1468error_if_locked(int lock, char *error)
1469{
1470 if (lock & (VAR_LOCKED | VAR_FIXED))
1471 {
1472 emsg(_(error));
1473 return TRUE;
1474 }
1475 return FALSE;
1476}
1477
1478/*
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01001479 * Give an error if "tv" is not a number and return FAIL.
1480 */
1481 static int
1482check_for_number(typval_T *tv)
1483{
1484 if (tv->v_type != VAR_NUMBER)
1485 {
1486 semsg(_(e_expected_str_but_got_str),
1487 vartype_name(VAR_NUMBER), vartype_name(tv->v_type));
1488 return FAIL;
1489 }
1490 return OK;
1491}
1492
1493/*
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001494 * Store "tv" in variable "name".
1495 * This is for s: and g: variables.
1496 */
1497 static void
1498store_var(char_u *name, typval_T *tv)
1499{
1500 funccal_entry_T entry;
Bram Moolenaard877a572021-04-01 19:42:48 +02001501 int flags = ASSIGN_DECL;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001502
Bram Moolenaard877a572021-04-01 19:42:48 +02001503 if (tv->v_lock)
1504 flags |= ASSIGN_CONST;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001505 save_funccal(&entry);
Bram Moolenaard5f400c2022-01-06 21:10:28 +00001506 set_var_const(name, 0, NULL, tv, FALSE, flags, 0);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001507 restore_funccal();
1508}
1509
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001510/*
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001511 * Convert "tv" to a string.
1512 * Return FAIL if not allowed.
1513 */
1514 static int
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001515do_2string(typval_T *tv, int is_2string_any, int tolerant)
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001516{
1517 if (tv->v_type != VAR_STRING)
1518 {
1519 char_u *str;
1520
1521 if (is_2string_any)
1522 {
1523 switch (tv->v_type)
1524 {
1525 case VAR_SPECIAL:
1526 case VAR_BOOL:
1527 case VAR_NUMBER:
1528 case VAR_FLOAT:
1529 case VAR_BLOB: break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001530
1531 case VAR_LIST:
1532 if (tolerant)
1533 {
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001534 char_u *s, *e, *p;
1535 garray_T ga;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001536
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001537 ga_init2(&ga, sizeof(char_u *), 1);
1538
1539 // Convert to NL separated items, then
1540 // escape the items and replace the NL with
1541 // a space.
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001542 str = typval2string(tv, TRUE);
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001543 if (str == NULL)
1544 return FAIL;
1545 s = str;
1546 while ((e = vim_strchr(s, '\n')) != NULL)
1547 {
1548 *e = NUL;
Bram Moolenaar21c1a0c2021-10-17 17:20:23 +01001549 p = vim_strsave_fnameescape(s,
1550 VSE_NONE);
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001551 if (p != NULL)
1552 {
1553 ga_concat(&ga, p);
1554 ga_concat(&ga, (char_u *)" ");
1555 vim_free(p);
1556 }
1557 s = e + 1;
1558 }
1559 vim_free(str);
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001560 clear_tv(tv);
1561 tv->v_type = VAR_STRING;
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001562 tv->vval.v_string = ga.ga_data;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001563 return OK;
1564 }
1565 // FALLTHROUGH
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001566 default: to_string_error(tv->v_type);
1567 return FAIL;
1568 }
1569 }
Bram Moolenaar34453202021-01-31 13:08:38 +01001570 str = typval_tostring(tv, TRUE);
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001571 clear_tv(tv);
1572 tv->v_type = VAR_STRING;
1573 tv->vval.v_string = str;
1574 }
1575 return OK;
1576}
1577
1578/*
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001579 * When the value of "sv" is a null list of dict, allocate it.
1580 */
1581 static void
Bram Moolenaar859cc212022-03-28 15:22:35 +01001582allocate_if_null(svar_T *sv)
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001583{
Bram Moolenaar859cc212022-03-28 15:22:35 +01001584 typval_T *tv = sv->sv_tv;
1585
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001586 switch (tv->v_type)
1587 {
1588 case VAR_LIST:
Bram Moolenaar859cc212022-03-28 15:22:35 +01001589 if (tv->vval.v_list == NULL && sv->sv_type != &t_list_empty)
Bram Moolenaarfef80642021-02-03 20:01:19 +01001590 (void)rettv_list_alloc(tv);
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001591 break;
1592 case VAR_DICT:
Bram Moolenaar859cc212022-03-28 15:22:35 +01001593 if (tv->vval.v_dict == NULL && sv->sv_type != &t_dict_empty)
Bram Moolenaarfef80642021-02-03 20:01:19 +01001594 (void)rettv_dict_alloc(tv);
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001595 break;
Bram Moolenaarb7c21af2021-04-18 14:12:31 +02001596 case VAR_BLOB:
Bram Moolenaar859cc212022-03-28 15:22:35 +01001597 if (tv->vval.v_blob == NULL && sv->sv_type != &t_blob_null)
Bram Moolenaarb7c21af2021-04-18 14:12:31 +02001598 (void)rettv_blob_alloc(tv);
1599 break;
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001600 default:
1601 break;
1602 }
1603}
Bram Moolenaard3aac292020-04-19 14:32:17 +02001604
Bram Moolenaare7525c52021-01-09 13:20:37 +01001605/*
Bram Moolenaar0289a092021-03-14 18:40:19 +01001606 * Return the character "str[index]" where "index" is the character index,
1607 * including composing characters.
1608 * If "index" is out of range NULL is returned.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001609 */
1610 char_u *
1611char_from_string(char_u *str, varnumber_T index)
1612{
1613 size_t nbyte = 0;
1614 varnumber_T nchar = index;
1615 size_t slen;
1616
1617 if (str == NULL)
1618 return NULL;
1619 slen = STRLEN(str);
1620
Bram Moolenaarff871402021-03-26 13:34:05 +01001621 // Do the same as for a list: a negative index counts from the end.
1622 // Optimization to check the first byte to be below 0x80 (and no composing
1623 // character follows) makes this a lot faster.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001624 if (index < 0)
1625 {
1626 int clen = 0;
1627
1628 for (nbyte = 0; nbyte < slen; ++clen)
Bram Moolenaarff871402021-03-26 13:34:05 +01001629 {
1630 if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
1631 ++nbyte;
1632 else if (enc_utf8)
1633 nbyte += utfc_ptr2len(str + nbyte);
1634 else
1635 nbyte += mb_ptr2len(str + nbyte);
1636 }
Bram Moolenaare7525c52021-01-09 13:20:37 +01001637 nchar = clen + index;
1638 if (nchar < 0)
1639 // unlike list: index out of range results in empty string
1640 return NULL;
1641 }
1642
1643 for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar)
Bram Moolenaarff871402021-03-26 13:34:05 +01001644 {
1645 if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
1646 ++nbyte;
1647 else if (enc_utf8)
1648 nbyte += utfc_ptr2len(str + nbyte);
1649 else
1650 nbyte += mb_ptr2len(str + nbyte);
1651 }
Bram Moolenaare7525c52021-01-09 13:20:37 +01001652 if (nbyte >= slen)
1653 return NULL;
Bram Moolenaar0289a092021-03-14 18:40:19 +01001654 return vim_strnsave(str + nbyte, mb_ptr2len(str + nbyte));
Bram Moolenaare7525c52021-01-09 13:20:37 +01001655}
1656
1657/*
1658 * Get the byte index for character index "idx" in string "str" with length
Bram Moolenaar0289a092021-03-14 18:40:19 +01001659 * "str_len". Composing characters are included.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001660 * If going over the end return "str_len".
1661 * If "idx" is negative count from the end, -1 is the last character.
1662 * When going over the start return -1.
1663 */
1664 static long
1665char_idx2byte(char_u *str, size_t str_len, varnumber_T idx)
1666{
1667 varnumber_T nchar = idx;
1668 size_t nbyte = 0;
1669
1670 if (nchar >= 0)
1671 {
1672 while (nchar > 0 && nbyte < str_len)
1673 {
Bram Moolenaar0289a092021-03-14 18:40:19 +01001674 nbyte += mb_ptr2len(str + nbyte);
Bram Moolenaare7525c52021-01-09 13:20:37 +01001675 --nchar;
1676 }
1677 }
1678 else
1679 {
1680 nbyte = str_len;
1681 while (nchar < 0 && nbyte > 0)
1682 {
1683 --nbyte;
1684 nbyte -= mb_head_off(str, str + nbyte);
1685 ++nchar;
1686 }
1687 if (nchar < 0)
1688 return -1;
1689 }
1690 return (long)nbyte;
1691}
1692
1693/*
Bram Moolenaar0289a092021-03-14 18:40:19 +01001694 * Return the slice "str[first : last]" using character indexes. Composing
1695 * characters are included.
Bram Moolenaar6601b622021-01-13 21:47:15 +01001696 * "exclusive" is TRUE for slice().
Bram Moolenaare7525c52021-01-09 13:20:37 +01001697 * Return NULL when the result is empty.
1698 */
1699 char_u *
Bram Moolenaar6601b622021-01-13 21:47:15 +01001700string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001701{
1702 long start_byte, end_byte;
1703 size_t slen;
1704
1705 if (str == NULL)
1706 return NULL;
1707 slen = STRLEN(str);
1708 start_byte = char_idx2byte(str, slen, first);
1709 if (start_byte < 0)
1710 start_byte = 0; // first index very negative: use zero
Bram Moolenaar6601b622021-01-13 21:47:15 +01001711 if ((last == -1 && !exclusive) || last == VARNUM_MAX)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001712 end_byte = (long)slen;
1713 else
1714 {
1715 end_byte = char_idx2byte(str, slen, last);
Bram Moolenaar6601b622021-01-13 21:47:15 +01001716 if (!exclusive && end_byte >= 0 && end_byte < (long)slen)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001717 // end index is inclusive
Bram Moolenaar0289a092021-03-14 18:40:19 +01001718 end_byte += mb_ptr2len(str + end_byte);
Bram Moolenaare7525c52021-01-09 13:20:37 +01001719 }
1720
1721 if (start_byte >= (long)slen || end_byte <= start_byte)
1722 return NULL;
1723 return vim_strnsave(str + start_byte, end_byte - start_byte);
1724}
1725
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001726/*
1727 * Get a script variable for ISN_STORESCRIPT and ISN_LOADSCRIPT.
1728 * When "dfunc_idx" is negative don't give an error.
1729 * Returns NULL for an error.
1730 */
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001731 static svar_T *
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001732get_script_svar(scriptref_T *sref, int dfunc_idx)
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001733{
1734 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001735 dfunc_T *dfunc = dfunc_idx < 0 ? NULL
1736 : ((dfunc_T *)def_functions.ga_data) + dfunc_idx;
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001737 svar_T *sv;
1738
1739 if (sref->sref_seq != si->sn_script_seq)
1740 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001741 // The script was reloaded after the function was compiled, the
1742 // script_idx may not be valid.
1743 if (dfunc != NULL)
1744 semsg(_(e_script_variable_invalid_after_reload_in_function_str),
1745 printable_func_name(dfunc->df_ufunc));
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001746 return NULL;
1747 }
1748 sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx;
Bram Moolenaar6de22962022-09-09 21:35:36 +01001749 if (sv->sv_name == NULL)
1750 {
1751 if (dfunc != NULL)
1752 emsg(_(e_script_variable_was_deleted));
1753 return NULL;
1754 }
Bram Moolenaar60dc8272021-07-29 22:48:54 +02001755 if (!equal_type(sv->sv_type, sref->sref_type, 0))
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001756 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001757 if (dfunc != NULL)
1758 emsg(_(e_script_variable_type_changed));
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001759 return NULL;
1760 }
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01001761
Bram Moolenaaraa7d0c22022-04-05 21:40:38 +01001762 if ((sv->sv_flags & SVFLAG_EXPORTED) == 0
1763 && sref->sref_sid != current_sctx.sc_sid)
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01001764 {
1765 if (dfunc != NULL)
1766 semsg(_(e_item_not_exported_in_script_str), sv->sv_name);
1767 return NULL;
1768 }
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001769 return sv;
1770}
1771
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001772/*
Bram Moolenaar20677332021-06-06 17:02:53 +02001773 * Function passed to do_cmdline() for splitting a script joined by NL
1774 * characters.
1775 */
1776 static char_u *
1777get_split_sourceline(
1778 int c UNUSED,
1779 void *cookie,
1780 int indent UNUSED,
1781 getline_opt_T options UNUSED)
1782{
1783 source_cookie_T *sp = (source_cookie_T *)cookie;
1784 char_u *p;
1785 char_u *line;
1786
Bram Moolenaar20677332021-06-06 17:02:53 +02001787 p = vim_strchr(sp->nextline, '\n');
1788 if (p == NULL)
1789 {
1790 line = vim_strsave(sp->nextline);
1791 sp->nextline += STRLEN(sp->nextline);
1792 }
1793 else
1794 {
1795 line = vim_strnsave(sp->nextline, p - sp->nextline);
1796 sp->nextline = p + 1;
1797 }
1798 return line;
1799}
1800
1801/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001802 * Execute a function by "name".
1803 * This can be a builtin function, user function or a funcref.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001804 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001805 */
1806 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001807call_eval_func(
1808 char_u *name,
1809 int argcount,
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001810 ectx_T *ectx,
1811 isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001812{
Bram Moolenaared677f52020-08-12 16:38:10 +02001813 int called_emsg_before = called_emsg;
1814 int res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001815
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001816 res = call_by_name(name, argcount, ectx, iptr, NULL);
Bram Moolenaared677f52020-08-12 16:38:10 +02001817 if (res == FAIL && called_emsg == called_emsg_before)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001818 {
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001819 dictitem_T *v;
1820
1821 v = find_var(name, NULL, FALSE);
Bram Moolenaara6c18d32022-03-31 20:02:56 +01001822 if (v == NULL || (v->di_tv.v_type != VAR_PARTIAL
1823 && v->di_tv.v_type != VAR_FUNC))
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001824 {
Bram Moolenaara6c18d32022-03-31 20:02:56 +01001825 emsg_funcname(e_unknown_function_str, name);
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001826 return FAIL;
1827 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02001828 return call_partial(&v->di_tv, argcount, ectx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001829 }
Bram Moolenaared677f52020-08-12 16:38:10 +02001830 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001831}
1832
1833/*
Bram Moolenaarf112f302020-12-20 17:47:52 +01001834 * When a function reference is used, fill a partial with the information
1835 * needed, especially when it is used as a closure.
1836 */
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01001837 int
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001838fill_partial_and_closure(
Bram Moolenaarcc341812022-09-19 15:54:34 +01001839 partial_T *pt,
1840 ufunc_T *ufunc,
1841 loopvarinfo_T *lvi,
1842 ectx_T *ectx)
Bram Moolenaarf112f302020-12-20 17:47:52 +01001843{
1844 pt->pt_func = ufunc;
1845 pt->pt_refcount = 1;
1846
Bram Moolenaar0d3de8c2021-01-22 20:46:27 +01001847 if (ufunc->uf_flags & FC_CLOSURE)
Bram Moolenaarf112f302020-12-20 17:47:52 +01001848 {
1849 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1850 + ectx->ec_dfunc_idx;
1851
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001852 // The closure may need to find arguments and local variables of the
1853 // current function in the stack.
Bram Moolenaar0186e582021-01-10 18:33:11 +01001854 pt->pt_outer.out_stack = &ectx->ec_stack;
1855 pt->pt_outer.out_frame_idx = ectx->ec_frame_idx;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001856 if (ectx->ec_outer_ref != NULL)
1857 {
1858 // The current context already has a context, link to that one.
1859 pt->pt_outer.out_up = ectx->ec_outer_ref->or_outer;
1860 if (ectx->ec_outer_ref->or_partial != NULL)
1861 {
1862 pt->pt_outer.out_up_partial = ectx->ec_outer_ref->or_partial;
1863 ++pt->pt_outer.out_up_partial->pt_refcount;
1864 }
1865 }
Bram Moolenaarf112f302020-12-20 17:47:52 +01001866
Bram Moolenaarcc341812022-09-19 15:54:34 +01001867 if (lvi != NULL)
1868 {
1869 int depth;
1870
1871 // The closure may need to find variables defined inside a loop,
1872 // for every nested loop. A new reference is made every time,
1873 // ISN_ENDLOOP will check if they are actually used.
1874 for (depth = 0; depth < lvi->lvi_depth; ++depth)
1875 {
1876 pt->pt_outer.out_loop[depth].stack = &ectx->ec_stack;
1877 pt->pt_outer.out_loop[depth].var_idx = ectx->ec_frame_idx
1878 + STACK_FRAME_SIZE + lvi->lvi_loop[depth].var_idx;
1879 pt->pt_outer.out_loop[depth].var_count =
1880 lvi->lvi_loop[depth].var_count;
1881 }
Bram Moolenaar6d313be2022-09-22 16:36:25 +01001882 pt->pt_outer.out_loop_size = lvi->lvi_depth;
Bram Moolenaarcc341812022-09-19 15:54:34 +01001883 }
Bram Moolenaar6d313be2022-09-22 16:36:25 +01001884 else
1885 pt->pt_outer.out_loop_size = 0;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001886
Bram Moolenaarb46c0832022-09-15 17:19:37 +01001887 // If the function currently executing returns and the closure is still
1888 // being referenced, we need to make a copy of the context (arguments
1889 // and local variables) so that the closure can use it later.
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001890 // Store a reference to the partial so we can handle that.
Bram Moolenaar35578162021-08-02 19:10:38 +02001891 if (GA_GROW_FAILS(&ectx->ec_funcrefs, 1))
Bram Moolenaarf112f302020-12-20 17:47:52 +01001892 {
1893 vim_free(pt);
1894 return FAIL;
1895 }
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001896 // Extra variable keeps the count of closures created in the current
1897 // function call.
Bram Moolenaarf112f302020-12-20 17:47:52 +01001898 ++(((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx
1899 + STACK_FRAME_SIZE + dfunc->df_varcount)->vval.v_number;
1900
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01001901 ((partial_T **)ectx->ec_funcrefs.ga_data)[ectx->ec_funcrefs.ga_len]
1902 = pt;
Bram Moolenaarf112f302020-12-20 17:47:52 +01001903 ++pt->pt_refcount;
1904 ++ectx->ec_funcrefs.ga_len;
1905 }
Bram Moolenaar0d3de8c2021-01-22 20:46:27 +01001906 ++ufunc->uf_refcount;
Bram Moolenaarf112f302020-12-20 17:47:52 +01001907 return OK;
1908}
1909
Bram Moolenaaraacc9662021-08-13 19:40:51 +02001910/*
1911 * Execute iptr->isn_arg.string as an Ex command.
1912 */
1913 static int
1914exec_command(isn_T *iptr)
1915{
1916 source_cookie_T cookie;
1917
1918 SOURCING_LNUM = iptr->isn_lnum;
1919 // Pass getsourceline to get an error for a missing ":end"
1920 // command.
1921 CLEAR_FIELD(cookie);
1922 cookie.sourcing_lnum = iptr->isn_lnum - 1;
1923 if (do_cmdline(iptr->isn_arg.string,
1924 getsourceline, &cookie,
1925 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED) == FAIL
1926 || did_emsg)
1927 return FAIL;
1928 return OK;
1929}
1930
Bram Moolenaar89445512022-04-14 12:58:23 +01001931/*
1932 * If script "sid" is not loaded yet then load it now.
1933 * Caller must make sure "sid" is a valid script ID.
1934 * "loaded" is set to TRUE if the script had to be loaded.
1935 * Returns FAIL if loading fails, OK if already loaded or loaded now.
1936 */
1937 int
1938may_load_script(int sid, int *loaded)
1939{
1940 scriptitem_T *si = SCRIPT_ITEM(sid);
1941
1942 if (si->sn_state == SN_STATE_NOT_LOADED)
1943 {
1944 *loaded = TRUE;
1945 if (do_source(si->sn_name, FALSE, DOSO_NONE, NULL) == FAIL)
1946 {
1947 semsg(_(e_cant_open_file_str), si->sn_name);
1948 return FAIL;
1949 }
1950 }
1951 return OK;
1952}
1953
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001954// used for v_instr of typval of VAR_INSTR
1955struct instr_S {
1956 ectx_T *instr_ectx;
1957 isn_T *instr_instr;
1958};
1959
Bram Moolenaar4c137212021-04-19 16:48:48 +02001960// used for substitute_instr
1961typedef struct subs_expr_S {
1962 ectx_T *subs_ectx;
1963 isn_T *subs_instr;
1964 int subs_status;
1965} subs_expr_T;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001966
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001967// Set when calling do_debug().
1968static ectx_T *debug_context = NULL;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001969static int debug_var_count;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001970
1971/*
1972 * When debugging lookup "name" and return the typeval.
1973 * When not found return NULL.
1974 */
1975 typval_T *
1976lookup_debug_var(char_u *name)
1977{
1978 int idx;
1979 dfunc_T *dfunc;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001980 ufunc_T *ufunc;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001981 ectx_T *ectx = debug_context;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001982 int varargs_off;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001983
1984 if (ectx == NULL)
1985 return NULL;
1986 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
1987
1988 // Go through the local variable names, from last to first.
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001989 for (idx = debug_var_count - 1; idx >= 0; --idx)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001990 {
Bram Moolenaare406ff82022-03-10 20:47:43 +00001991 char_u *varname = ((char_u **)dfunc->df_var_names.ga_data)[idx];
1992
1993 // the variable name may be NULL when not available in this block
1994 if (varname != NULL && STRCMP(varname, name) == 0)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001995 return STACK_TV_VAR(idx);
1996 }
1997
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001998 // Go through argument names.
1999 ufunc = dfunc->df_ufunc;
2000 varargs_off = ufunc->uf_va_name == NULL ? 0 : 1;
2001 for (idx = 0; idx < ufunc->uf_args.ga_len; ++idx)
2002 if (STRCMP(((char_u **)(ufunc->uf_args.ga_data))[idx], name) == 0)
2003 return STACK_TV(ectx->ec_frame_idx - ufunc->uf_args.ga_len
2004 - varargs_off + idx);
2005 if (ufunc->uf_va_name != NULL && STRCMP(ufunc->uf_va_name, name) == 0)
2006 return STACK_TV(ectx->ec_frame_idx - 1);
2007
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02002008 return NULL;
2009}
2010
Bram Moolenaar26a44842021-09-02 18:49:06 +02002011/*
2012 * Return TRUE if there might be a breakpoint in "ufunc", which is when a
2013 * breakpoint was set in that function or when there is any expression.
2014 */
2015 int
2016may_break_in_function(ufunc_T *ufunc)
2017{
2018 return ufunc->uf_has_breakpoint || debug_has_expr_breakpoint();
2019}
2020
Bram Moolenaar4cea5362021-06-16 22:24:40 +02002021 static void
2022handle_debug(isn_T *iptr, ectx_T *ectx)
2023{
2024 char_u *line;
2025 ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
2026 + ectx->ec_dfunc_idx)->df_ufunc;
2027 isn_T *ni;
2028 int end_lnum = iptr->isn_lnum;
2029 garray_T ga;
2030 int lnum;
2031
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02002032 if (ex_nesting_level > debug_break_level)
2033 {
2034 linenr_T breakpoint;
2035
Bram Moolenaar26a44842021-09-02 18:49:06 +02002036 if (!may_break_in_function(ufunc))
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02002037 return;
2038
2039 // check for the next breakpoint if needed
2040 breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name,
Bram Moolenaar8cec9272021-06-23 20:20:53 +02002041 iptr->isn_arg.debug.dbg_break_lnum);
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02002042 if (breakpoint <= 0 || breakpoint > iptr->isn_lnum)
2043 return;
2044 }
2045
Bram Moolenaar4cea5362021-06-16 22:24:40 +02002046 SOURCING_LNUM = iptr->isn_lnum;
2047 debug_context = ectx;
Bram Moolenaar8cec9272021-06-23 20:20:53 +02002048 debug_var_count = iptr->isn_arg.debug.dbg_var_names_len;
Bram Moolenaar4cea5362021-06-16 22:24:40 +02002049
2050 for (ni = iptr + 1; ni->isn_type != ISN_FINISH; ++ni)
2051 if (ni->isn_type == ISN_DEBUG
2052 || ni->isn_type == ISN_RETURN
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002053 || ni->isn_type == ISN_RETURN_OBJECT
Bram Moolenaar4cea5362021-06-16 22:24:40 +02002054 || ni->isn_type == ISN_RETURN_VOID)
2055 {
Bram Moolenaar112bed02021-11-23 22:16:34 +00002056 end_lnum = ni->isn_lnum + (ni->isn_type == ISN_DEBUG ? 0 : 1);
Bram Moolenaar4cea5362021-06-16 22:24:40 +02002057 break;
2058 }
2059
2060 if (end_lnum > iptr->isn_lnum)
2061 {
2062 ga_init2(&ga, sizeof(char_u *), 10);
Bram Moolenaar310091d2021-12-23 21:14:37 +00002063 for (lnum = iptr->isn_lnum; lnum < end_lnum
2064 && lnum <= ufunc->uf_lines.ga_len; ++lnum)
Bram Moolenaar59b50c32021-06-17 22:27:48 +02002065 {
Bram Moolenaar303215d2021-07-07 20:10:43 +02002066 char_u *p = ((char_u **)ufunc->uf_lines.ga_data)[lnum - 1];
Bram Moolenaar59b50c32021-06-17 22:27:48 +02002067
Bram Moolenaar303215d2021-07-07 20:10:43 +02002068 if (p == NULL)
2069 continue; // left over from continuation line
2070 p = skipwhite(p);
Bram Moolenaar59b50c32021-06-17 22:27:48 +02002071 if (*p == '#')
2072 break;
Bram Moolenaar35578162021-08-02 19:10:38 +02002073 if (GA_GROW_OK(&ga, 1))
Bram Moolenaar59b50c32021-06-17 22:27:48 +02002074 ((char_u **)(ga.ga_data))[ga.ga_len++] = p;
2075 if (STRNCMP(p, "def ", 4) == 0)
2076 break;
2077 }
Bram Moolenaar4cea5362021-06-16 22:24:40 +02002078 line = ga_concat_strings(&ga, " ");
2079 vim_free(ga.ga_data);
2080 }
2081 else
2082 line = ((char_u **)ufunc->uf_lines.ga_data)[iptr->isn_lnum - 1];
Bram Moolenaar4cea5362021-06-16 22:24:40 +02002083
Dominique Pelle6e969552021-06-17 13:53:41 +02002084 do_debug(line == NULL ? (char_u *)"[empty]" : line);
Bram Moolenaar4cea5362021-06-16 22:24:40 +02002085 debug_context = NULL;
2086
2087 if (end_lnum > iptr->isn_lnum)
2088 vim_free(line);
2089}
2090
Bram Moolenaar4c137212021-04-19 16:48:48 +02002091/*
Bram Moolenaar65b0d162022-12-13 18:43:22 +00002092 * Store a value in a list, dict, blob or object variable.
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002093 * Returns OK, FAIL or NOTDONE (uncatchable error).
2094 */
2095 static int
2096execute_storeindex(isn_T *iptr, ectx_T *ectx)
2097{
2098 vartype_T dest_type = iptr->isn_arg.vartype;
2099 typval_T *tv;
2100 typval_T *tv_idx = STACK_TV_BOT(-2);
2101 typval_T *tv_dest = STACK_TV_BOT(-1);
2102 int status = OK;
2103
2104 // Stack contains:
2105 // -3 value to be stored
2106 // -2 index
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002107 // -1 dict, list, blob or object
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002108 tv = STACK_TV_BOT(-3);
2109 SOURCING_LNUM = iptr->isn_lnum;
2110 if (dest_type == VAR_ANY)
2111 {
2112 dest_type = tv_dest->v_type;
2113 if (dest_type == VAR_DICT)
2114 status = do_2string(tv_idx, TRUE, FALSE);
2115 else if (dest_type == VAR_LIST && tv_idx->v_type != VAR_NUMBER)
2116 {
2117 emsg(_(e_number_expected));
2118 status = FAIL;
2119 }
2120 }
Bram Moolenaare08be092022-02-17 13:08:26 +00002121
2122 if (status == OK)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002123 {
Bram Moolenaare08be092022-02-17 13:08:26 +00002124 if (dest_type == VAR_LIST)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002125 {
Bram Moolenaare08be092022-02-17 13:08:26 +00002126 long lidx = (long)tv_idx->vval.v_number;
2127 list_T *list = tv_dest->vval.v_list;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002128
Bram Moolenaare08be092022-02-17 13:08:26 +00002129 if (list == NULL)
2130 {
2131 emsg(_(e_list_not_set));
2132 return FAIL;
2133 }
2134 if (lidx < 0 && list->lv_len + lidx >= 0)
2135 // negative index is relative to the end
2136 lidx = list->lv_len + lidx;
2137 if (lidx < 0 || lidx > list->lv_len)
2138 {
2139 semsg(_(e_list_index_out_of_range_nr), lidx);
2140 return FAIL;
2141 }
2142 if (lidx < list->lv_len)
2143 {
2144 listitem_T *li = list_find(list, lidx);
2145
2146 if (error_if_locked(li->li_tv.v_lock,
Bram Moolenaar70c43d82022-01-26 21:01:15 +00002147 e_cannot_change_locked_list_item))
Bram Moolenaare08be092022-02-17 13:08:26 +00002148 return FAIL;
2149 // overwrite existing list item
2150 clear_tv(&li->li_tv);
2151 li->li_tv = *tv;
2152 }
2153 else
2154 {
2155 if (error_if_locked(list->lv_lock, e_cannot_change_locked_list))
2156 return FAIL;
2157 // append to list, only fails when out of memory
2158 if (list_append_tv(list, tv) == FAIL)
2159 return NOTDONE;
2160 clear_tv(tv);
2161 }
2162 }
2163 else if (dest_type == VAR_DICT)
2164 {
2165 char_u *key = tv_idx->vval.v_string;
2166 dict_T *dict = tv_dest->vval.v_dict;
2167 dictitem_T *di;
2168
2169 SOURCING_LNUM = iptr->isn_lnum;
2170 if (dict == NULL)
2171 {
2172 emsg(_(e_dictionary_not_set));
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002173 return FAIL;
Bram Moolenaare08be092022-02-17 13:08:26 +00002174 }
2175 if (key == NULL)
2176 key = (char_u *)"";
2177 di = dict_find(dict, key, -1);
2178 if (di != NULL)
2179 {
2180 if (error_if_locked(di->di_tv.v_lock,
2181 e_cannot_change_dict_item))
2182 return FAIL;
2183 // overwrite existing value
2184 clear_tv(&di->di_tv);
2185 di->di_tv = *tv;
2186 }
2187 else
2188 {
2189 if (error_if_locked(dict->dv_lock, e_cannot_change_dict))
2190 return FAIL;
2191 // add to dict, only fails when out of memory
2192 if (dict_add_tv(dict, (char *)key, tv) == FAIL)
2193 return NOTDONE;
2194 clear_tv(tv);
2195 }
2196 }
2197 else if (dest_type == VAR_BLOB)
2198 {
2199 long lidx = (long)tv_idx->vval.v_number;
2200 blob_T *blob = tv_dest->vval.v_blob;
Bram Moolenaar65b0d162022-12-13 18:43:22 +00002201 varnumber_T nr;
2202 int error = FALSE;
2203 int len;
Bram Moolenaare08be092022-02-17 13:08:26 +00002204
2205 if (blob == NULL)
2206 {
2207 emsg(_(e_blob_not_set));
2208 return FAIL;
2209 }
2210 len = blob_len(blob);
2211 if (lidx < 0 && len + lidx >= 0)
2212 // negative index is relative to the end
2213 lidx = len + lidx;
2214
2215 // Can add one byte at the end.
2216 if (lidx < 0 || lidx > len)
2217 {
2218 semsg(_(e_blob_index_out_of_range_nr), lidx);
2219 return FAIL;
2220 }
2221 if (value_check_lock(blob->bv_lock, (char_u *)"blob", FALSE))
2222 return FAIL;
2223 nr = tv_get_number_chk(tv, &error);
2224 if (error)
2225 return FAIL;
2226 blob_set_append(blob, lidx, nr);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002227 }
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002228 else if (dest_type == VAR_CLASS || dest_type == VAR_OBJECT)
2229 {
2230 long idx = (long)tv_idx->vval.v_number;
2231 object_T *obj = tv_dest->vval.v_object;
2232 typval_T *otv = (typval_T *)(obj + 1);
Bram Moolenaar65b0d162022-12-13 18:43:22 +00002233 clear_tv(&otv[idx]);
Bram Moolenaar00b28d62022-12-08 15:32:33 +00002234 otv[idx] = *tv;
2235 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002236 else
2237 {
Bram Moolenaare08be092022-02-17 13:08:26 +00002238 status = FAIL;
2239 semsg(_(e_cannot_index_str), vartype_name(dest_type));
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002240 }
2241 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002242
2243 clear_tv(tv_idx);
2244 clear_tv(tv_dest);
2245 ectx->ec_stack.ga_len -= 3;
2246 if (status == FAIL)
2247 {
2248 clear_tv(tv);
2249 return FAIL;
2250 }
2251 return OK;
2252}
2253
2254/*
Bram Moolenaarea5c8982022-02-17 14:42:02 +00002255 * Store a value in a list or blob range.
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002256 */
2257 static int
2258execute_storerange(isn_T *iptr, ectx_T *ectx)
2259{
2260 typval_T *tv;
2261 typval_T *tv_idx1 = STACK_TV_BOT(-3);
2262 typval_T *tv_idx2 = STACK_TV_BOT(-2);
2263 typval_T *tv_dest = STACK_TV_BOT(-1);
2264 int status = OK;
2265
2266 // Stack contains:
2267 // -4 value to be stored
2268 // -3 first index or "none"
2269 // -2 second index or "none"
2270 // -1 destination list or blob
2271 tv = STACK_TV_BOT(-4);
Bram Moolenaarea5c8982022-02-17 14:42:02 +00002272 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002273 if (tv_dest->v_type == VAR_LIST)
2274 {
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00002275 long n1;
2276 long n2;
2277 listitem_T *li1;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002278
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00002279 n1 = (long)tv_get_number_chk(tv_idx1, NULL);
2280 if (tv_idx2->v_type == VAR_SPECIAL
2281 && tv_idx2->vval.v_number == VVAL_NONE)
2282 n2 = list_len(tv_dest->vval.v_list) - 1;
2283 else
2284 n2 = (long)tv_get_number_chk(tv_idx2, NULL);
2285
Bram Moolenaar22ebd172022-04-01 15:26:58 +01002286 li1 = check_range_index_one(tv_dest->vval.v_list, &n1, TRUE, FALSE);
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00002287 if (li1 == NULL)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002288 status = FAIL;
2289 else
2290 {
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00002291 status = check_range_index_two(tv_dest->vval.v_list,
2292 &n1, li1, &n2, FALSE);
2293 if (status != FAIL)
2294 status = list_assign_range(
2295 tv_dest->vval.v_list,
2296 tv->vval.v_list,
2297 n1,
2298 n2,
2299 tv_idx2->v_type == VAR_SPECIAL,
2300 (char_u *)"=",
2301 (char_u *)"[unknown]");
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002302 }
2303 }
2304 else if (tv_dest->v_type == VAR_BLOB)
2305 {
2306 varnumber_T n1;
2307 varnumber_T n2;
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00002308 long bloblen;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002309
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00002310 n1 = tv_get_number_chk(tv_idx1, NULL);
2311 if (tv_idx2->v_type == VAR_SPECIAL
2312 && tv_idx2->vval.v_number == VVAL_NONE)
2313 n2 = blob_len(tv_dest->vval.v_blob) - 1;
2314 else
2315 n2 = tv_get_number_chk(tv_idx2, NULL);
2316 bloblen = blob_len(tv_dest->vval.v_blob);
2317
2318 if (check_blob_index(bloblen, n1, FALSE) == FAIL
2319 || check_blob_range(bloblen, n1, n2, FALSE) == FAIL)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002320 status = FAIL;
2321 else
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00002322 status = blob_set_range(tv_dest->vval.v_blob, n1, n2, tv);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002323 }
2324 else
2325 {
2326 status = FAIL;
Bram Moolenaarea5c8982022-02-17 14:42:02 +00002327 emsg(_(e_list_or_blob_required));
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002328 }
2329
2330 clear_tv(tv_idx1);
2331 clear_tv(tv_idx2);
2332 clear_tv(tv_dest);
2333 ectx->ec_stack.ga_len -= 4;
2334 clear_tv(tv);
2335
2336 return status;
2337}
2338
2339/*
2340 * Unlet item in list or dict variable.
2341 */
2342 static int
2343execute_unletindex(isn_T *iptr, ectx_T *ectx)
2344{
2345 typval_T *tv_idx = STACK_TV_BOT(-2);
2346 typval_T *tv_dest = STACK_TV_BOT(-1);
2347 int status = OK;
2348
2349 // Stack contains:
2350 // -2 index
2351 // -1 dict or list
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002352 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002353 if (tv_dest->v_type == VAR_DICT)
2354 {
2355 // unlet a dict item, index must be a string
Bram Moolenaarea5c8982022-02-17 14:42:02 +00002356 if (tv_idx->v_type != VAR_STRING && tv_idx->v_type != VAR_NUMBER)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002357 {
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002358 semsg(_(e_expected_str_but_got_str),
2359 vartype_name(VAR_STRING),
2360 vartype_name(tv_idx->v_type));
2361 status = FAIL;
2362 }
2363 else
2364 {
2365 dict_T *d = tv_dest->vval.v_dict;
Bram Moolenaarea5c8982022-02-17 14:42:02 +00002366 char_u *key;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002367 dictitem_T *di = NULL;
2368
2369 if (d != NULL && value_check_lock(
2370 d->dv_lock, NULL, FALSE))
2371 status = FAIL;
2372 else
2373 {
Bram Moolenaarea5c8982022-02-17 14:42:02 +00002374 if (tv_idx->v_type == VAR_STRING)
2375 {
2376 key = tv_idx->vval.v_string;
2377 if (key == NULL)
2378 key = (char_u *)"";
2379 }
2380 else
2381 {
2382 key = tv_get_string(tv_idx);
2383 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002384 if (d != NULL)
2385 di = dict_find(d, key, (int)STRLEN(key));
2386 if (di == NULL)
2387 {
2388 // NULL dict is equivalent to empty dict
2389 semsg(_(e_key_not_present_in_dictionary),
2390 key);
2391 status = FAIL;
2392 }
2393 else if (var_check_fixed(di->di_flags,
2394 NULL, FALSE)
2395 || var_check_ro(di->di_flags,
2396 NULL, FALSE))
2397 status = FAIL;
2398 else
Bram Moolenaaref2c3252022-11-25 16:31:51 +00002399 dictitem_remove(d, di, "unlet");
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002400 }
2401 }
2402 }
2403 else if (tv_dest->v_type == VAR_LIST)
2404 {
2405 // unlet a List item, index must be a number
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002406 if (check_for_number(tv_idx) == FAIL)
2407 {
2408 status = FAIL;
2409 }
2410 else
2411 {
2412 list_T *l = tv_dest->vval.v_list;
2413 long n = (long)tv_idx->vval.v_number;
2414
2415 if (l != NULL && value_check_lock(
2416 l->lv_lock, NULL, FALSE))
2417 status = FAIL;
2418 else
2419 {
2420 listitem_T *li = list_find(l, n);
2421
2422 if (li == NULL)
2423 {
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002424 semsg(_(e_list_index_out_of_range_nr), n);
2425 status = FAIL;
2426 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002427 else
2428 listitem_remove(l, li);
2429 }
2430 }
2431 }
2432 else
2433 {
2434 status = FAIL;
2435 semsg(_(e_cannot_index_str),
2436 vartype_name(tv_dest->v_type));
2437 }
2438
2439 clear_tv(tv_idx);
2440 clear_tv(tv_dest);
2441 ectx->ec_stack.ga_len -= 2;
2442
2443 return status;
2444}
2445
2446/*
2447 * Unlet a range of items in a list variable.
2448 */
2449 static int
2450execute_unletrange(isn_T *iptr, ectx_T *ectx)
2451{
2452 // Stack contains:
2453 // -3 index1
2454 // -2 index2
2455 // -1 dict or list
2456 typval_T *tv_idx1 = STACK_TV_BOT(-3);
2457 typval_T *tv_idx2 = STACK_TV_BOT(-2);
2458 typval_T *tv_dest = STACK_TV_BOT(-1);
2459 int status = OK;
2460
2461 if (tv_dest->v_type == VAR_LIST)
2462 {
2463 // indexes must be a number
2464 SOURCING_LNUM = iptr->isn_lnum;
2465 if (check_for_number(tv_idx1) == FAIL
2466 || (tv_idx2->v_type != VAR_SPECIAL
2467 && check_for_number(tv_idx2) == FAIL))
2468 {
2469 status = FAIL;
2470 }
2471 else
2472 {
2473 list_T *l = tv_dest->vval.v_list;
2474 long n1 = (long)tv_idx1->vval.v_number;
2475 long n2 = tv_idx2->v_type == VAR_SPECIAL
2476 ? 0 : (long)tv_idx2->vval.v_number;
2477 listitem_T *li;
2478
2479 li = list_find_index(l, &n1);
2480 if (li == NULL)
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002481 {
2482 semsg(_(e_list_index_out_of_range_nr),
2483 (long)tv_idx1->vval.v_number);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002484 status = FAIL;
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002485 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002486 else
2487 {
2488 if (n1 < 0)
2489 n1 = list_idx_of_item(l, li);
2490 if (n2 < 0)
2491 {
2492 listitem_T *li2 = list_find(l, n2);
2493
2494 if (li2 == NULL)
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002495 {
2496 semsg(_(e_list_index_out_of_range_nr), n2);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002497 status = FAIL;
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002498 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002499 else
2500 n2 = list_idx_of_item(l, li2);
2501 }
2502 if (status != FAIL
2503 && tv_idx2->v_type != VAR_SPECIAL
2504 && n2 < n1)
2505 {
2506 semsg(_(e_list_index_out_of_range_nr), n2);
2507 status = FAIL;
2508 }
Bram Moolenaar6b8c7ba2022-03-20 17:46:06 +00002509 if (status != FAIL)
2510 list_unlet_range(l, li, n1,
2511 tv_idx2->v_type != VAR_SPECIAL, n2);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002512 }
2513 }
2514 }
2515 else
2516 {
2517 status = FAIL;
2518 SOURCING_LNUM = iptr->isn_lnum;
2519 semsg(_(e_cannot_index_str),
2520 vartype_name(tv_dest->v_type));
2521 }
2522
2523 clear_tv(tv_idx1);
2524 clear_tv(tv_idx2);
2525 clear_tv(tv_dest);
2526 ectx->ec_stack.ga_len -= 3;
2527
2528 return status;
2529}
2530
2531/*
2532 * Top of a for loop.
2533 */
2534 static int
2535execute_for(isn_T *iptr, ectx_T *ectx)
2536{
2537 typval_T *tv;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002538 int jump = FALSE;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002539 typval_T *ltv = STACK_TV_BOT(-1);
2540 typval_T *idxtv =
Bram Moolenaarcc341812022-09-19 15:54:34 +01002541 STACK_TV_VAR(iptr->isn_arg.forloop.for_loop_idx);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002542
2543 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2544 return FAIL;
2545 if (ltv->v_type == VAR_LIST)
2546 {
2547 list_T *list = ltv->vval.v_list;
2548
2549 // push the next item from the list
2550 ++idxtv->vval.v_number;
2551 if (list == NULL
2552 || idxtv->vval.v_number >= list->lv_len)
2553 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002554 jump = TRUE;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002555 }
2556 else if (list->lv_first == &range_list_item)
2557 {
2558 // non-materialized range() list
2559 tv = STACK_TV_BOT(0);
2560 tv->v_type = VAR_NUMBER;
2561 tv->v_lock = 0;
2562 tv->vval.v_number = list_find_nr(
2563 list, idxtv->vval.v_number, NULL);
2564 ++ectx->ec_stack.ga_len;
2565 }
2566 else
2567 {
2568 listitem_T *li = list_find(list,
2569 idxtv->vval.v_number);
2570
2571 copy_tv(&li->li_tv, STACK_TV_BOT(0));
2572 ++ectx->ec_stack.ga_len;
2573 }
2574 }
2575 else if (ltv->v_type == VAR_STRING)
2576 {
2577 char_u *str = ltv->vval.v_string;
2578
2579 // The index is for the last byte of the previous
2580 // character.
2581 ++idxtv->vval.v_number;
2582 if (str == NULL || str[idxtv->vval.v_number] == NUL)
2583 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002584 jump = TRUE;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002585 }
2586 else
2587 {
2588 int clen = mb_ptr2len(str + idxtv->vval.v_number);
2589
2590 // Push the next character from the string.
2591 tv = STACK_TV_BOT(0);
2592 tv->v_type = VAR_STRING;
2593 tv->vval.v_string = vim_strnsave(
2594 str + idxtv->vval.v_number, clen);
2595 ++ectx->ec_stack.ga_len;
2596 idxtv->vval.v_number += clen - 1;
2597 }
2598 }
2599 else if (ltv->v_type == VAR_BLOB)
2600 {
2601 blob_T *blob = ltv->vval.v_blob;
2602
2603 // When we get here the first time make a copy of the
2604 // blob, so that the iteration still works when it is
2605 // changed.
2606 if (idxtv->vval.v_number == -1 && blob != NULL)
2607 {
2608 blob_copy(blob, ltv);
2609 blob_unref(blob);
2610 blob = ltv->vval.v_blob;
2611 }
2612
2613 // The index is for the previous byte.
2614 ++idxtv->vval.v_number;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002615 if (blob == NULL || idxtv->vval.v_number >= blob_len(blob))
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002616 {
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002617 jump = TRUE;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002618 }
2619 else
2620 {
2621 // Push the next byte from the blob.
2622 tv = STACK_TV_BOT(0);
2623 tv->v_type = VAR_NUMBER;
2624 tv->vval.v_number = blob_get(blob,
2625 idxtv->vval.v_number);
2626 ++ectx->ec_stack.ga_len;
2627 }
2628 }
2629 else
2630 {
2631 semsg(_(e_for_loop_on_str_not_supported),
2632 vartype_name(ltv->v_type));
2633 return FAIL;
2634 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002635
2636 if (jump)
2637 {
2638 // past the end of the list/string/blob, jump to "endfor"
2639 ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
2640 may_restore_cmdmod(&ectx->ec_funclocal);
2641 }
2642 else
2643 {
2644 // Store the current number of funcrefs, this may be used in
2645 // ISN_LOOPEND. The variable index is always one more than the loop
2646 // variable index.
Bram Moolenaarcc341812022-09-19 15:54:34 +01002647 tv = STACK_TV_VAR(iptr->isn_arg.forloop.for_loop_idx + 1);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002648 tv->vval.v_number = ectx->ec_funcrefs.ga_len;
2649 }
2650
2651 return OK;
2652}
2653
2654/*
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002655 * Code for handling variables declared inside a loop and used in a closure.
2656 * This is very similar to what is done with funcstack_T. The difference is
2657 * that the funcstack_T has the scope of a function, while a loopvars_T has the
2658 * scope of the block inside a loop and each loop may have its own.
2659 */
2660
2661// Double linked list of loopvars_T in use.
2662static loopvars_T *first_loopvars = NULL;
2663
2664 static void
2665add_loopvars_to_list(loopvars_T *loopvars)
2666{
2667 // Link in list of loopvarss.
2668 if (first_loopvars != NULL)
2669 first_loopvars->lvs_prev = loopvars;
2670 loopvars->lvs_next = first_loopvars;
2671 loopvars->lvs_prev = NULL;
2672 first_loopvars = loopvars;
2673}
2674
2675 static void
2676remove_loopvars_from_list(loopvars_T *loopvars)
2677{
2678 if (loopvars->lvs_prev == NULL)
2679 first_loopvars = loopvars->lvs_next;
2680 else
2681 loopvars->lvs_prev->lvs_next = loopvars->lvs_next;
2682 if (loopvars->lvs_next != NULL)
2683 loopvars->lvs_next->lvs_prev = loopvars->lvs_prev;
2684}
2685
2686/*
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002687 * End of a for or while loop: Handle any variables used by a closure.
2688 */
2689 static int
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002690execute_endloop(isn_T *iptr, ectx_T *ectx)
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002691{
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002692 endloop_T *endloop = &iptr->isn_arg.endloop;
2693 typval_T *tv_refcount = STACK_TV_VAR(endloop->end_funcref_idx);
2694 int prev_closure_count = tv_refcount->vval.v_number;
Bram Moolenaarcc341812022-09-19 15:54:34 +01002695 int depth = endloop->end_depth;
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002696 garray_T *gap = &ectx->ec_funcrefs;
2697 int closure_in_use = FALSE;
2698 loopvars_T *loopvars;
2699 typval_T *stack;
2700 int idx;
2701
Bram Moolenaarcc341812022-09-19 15:54:34 +01002702 // Check if any created closure is still being referenced and loopvars have
2703 // not been saved yet for the current depth.
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002704 for (idx = prev_closure_count; idx < gap->ga_len; ++idx)
2705 {
2706 partial_T *pt = ((partial_T **)gap->ga_data)[idx];
2707
Bram Moolenaarcc341812022-09-19 15:54:34 +01002708 if (pt->pt_refcount > 1 && pt->pt_loopvars[depth] == NULL)
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002709 {
2710 int refcount = pt->pt_refcount;
2711 int i;
2712
2713 // A Reference in a variable inside the loop doesn't count, it gets
2714 // unreferenced at the end of the loop.
2715 for (i = 0; i < endloop->end_var_count; ++i)
2716 {
2717 typval_T *stv = STACK_TV_VAR(endloop->end_var_idx + i);
2718
2719 if (stv->v_type == VAR_PARTIAL && pt == stv->vval.v_partial)
2720 --refcount;
2721 }
2722 if (refcount > 1)
2723 {
2724 closure_in_use = TRUE;
2725 break;
2726 }
2727 }
2728 }
2729
2730 // If no function reference were created since the start of the loop block
2731 // or it is no longer referenced there is nothing to do.
2732 if (!closure_in_use)
2733 return OK;
2734
2735 // A closure is using variables declared inside the loop.
2736 // Move them to the called function.
2737 loopvars = ALLOC_CLEAR_ONE(loopvars_T);
2738 if (loopvars == NULL)
2739 return FAIL;
2740
2741 loopvars->lvs_ga.ga_len = endloop->end_var_count;
2742 stack = ALLOC_CLEAR_MULT(typval_T, loopvars->lvs_ga.ga_len);
2743 loopvars->lvs_ga.ga_data = stack;
2744 if (stack == NULL)
2745 {
2746 vim_free(loopvars);
2747 return FAIL;
2748 }
2749 add_loopvars_to_list(loopvars);
2750
2751 // Move the variable values.
2752 for (idx = 0; idx < endloop->end_var_count; ++idx)
2753 {
2754 typval_T *tv = STACK_TV_VAR(endloop->end_var_idx + idx);
2755
2756 *(stack + idx) = *tv;
2757 tv->v_type = VAR_UNKNOWN;
2758 }
2759
2760 for (idx = prev_closure_count; idx < gap->ga_len; ++idx)
2761 {
2762 partial_T *pt = ((partial_T **)gap->ga_data)[idx];
2763
Bram Moolenaarcc341812022-09-19 15:54:34 +01002764 if (pt->pt_refcount > 1 && pt->pt_loopvars[depth] == NULL)
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002765 {
2766 ++loopvars->lvs_refcount;
Bram Moolenaarcc341812022-09-19 15:54:34 +01002767 pt->pt_loopvars[depth] = loopvars;
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002768
Bram Moolenaarcc341812022-09-19 15:54:34 +01002769 pt->pt_outer.out_loop[depth].stack = &loopvars->lvs_ga;
2770 pt->pt_outer.out_loop[depth].var_idx -=
2771 ectx->ec_frame_idx + STACK_FRAME_SIZE + endloop->end_var_idx;
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002772 }
2773 }
Bram Moolenaarb46c0832022-09-15 17:19:37 +01002774
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002775 return OK;
2776}
2777
2778/*
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002779 * Called when a partial is freed or its reference count goes down to one. The
2780 * loopvars may be the only reference to the partials in the local variables.
2781 * Go over all of them, the funcref and can be freed if all partials
2782 * referencing the loopvars have a reference count of one.
Bram Moolenaarcc341812022-09-19 15:54:34 +01002783 * Return TRUE if it was freed.
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002784 */
Bram Moolenaarcc341812022-09-19 15:54:34 +01002785 int
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002786loopvars_check_refcount(loopvars_T *loopvars)
2787{
2788 int i;
2789 garray_T *gap = &loopvars->lvs_ga;
2790 int done = 0;
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002791 typval_T *stack = gap->ga_data;
2792
Bram Moolenaarcc341812022-09-19 15:54:34 +01002793 if (loopvars->lvs_refcount > loopvars->lvs_min_refcount)
2794 return FALSE;
2795 for (i = 0; i < gap->ga_len; ++i)
2796 {
2797 typval_T *tv = ((typval_T *)gap->ga_data) + i;
2798
2799 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL
2800 && tv->vval.v_partial->pt_refcount == 1)
2801 {
2802 int depth;
2803
2804 for (depth = 0; depth < MAX_LOOP_DEPTH; ++depth)
2805 if (tv->vval.v_partial->pt_loopvars[depth] == loopvars)
2806 ++done;
2807 }
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002808 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01002809 if (done != loopvars->lvs_min_refcount)
2810 return FALSE;
2811
2812 // All partials referencing the loopvars have a reference count of
2813 // one, thus the loopvars is no longer of use.
2814 stack = gap->ga_data;
2815 for (i = 0; i < gap->ga_len; ++i)
2816 clear_tv(stack + i);
2817 vim_free(stack);
2818 remove_loopvars_from_list(loopvars);
2819 vim_free(loopvars);
2820 return TRUE;
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01002821}
2822
2823/*
2824 * For garbage collecting: set references in all variables referenced by
2825 * all loopvars.
2826 */
2827 int
2828set_ref_in_loopvars(int copyID)
2829{
2830 loopvars_T *loopvars;
2831
2832 for (loopvars = first_loopvars; loopvars != NULL;
2833 loopvars = loopvars->lvs_next)
2834 {
2835 typval_T *stack = loopvars->lvs_ga.ga_data;
2836 int i;
2837
2838 for (i = 0; i < loopvars->lvs_ga.ga_len; ++i)
2839 if (set_ref_in_item(stack + i, copyID, NULL, NULL))
2840 return TRUE; // abort
2841 }
2842 return FALSE;
2843}
2844
2845/*
Bram Moolenaar06b77222022-01-25 15:51:56 +00002846 * Load instruction for w:/b:/g:/t: variable.
2847 * "isn_type" is used instead of "iptr->isn_type".
2848 */
2849 static int
2850load_namespace_var(ectx_T *ectx, isntype_T isn_type, isn_T *iptr)
2851{
2852 dictitem_T *di = NULL;
2853 hashtab_T *ht = NULL;
2854 char namespace;
2855
2856 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2857 return NOTDONE;
2858 switch (isn_type)
2859 {
2860 case ISN_LOADG:
2861 ht = get_globvar_ht();
2862 namespace = 'g';
2863 break;
2864 case ISN_LOADB:
2865 ht = &curbuf->b_vars->dv_hashtab;
2866 namespace = 'b';
2867 break;
2868 case ISN_LOADW:
2869 ht = &curwin->w_vars->dv_hashtab;
2870 namespace = 'w';
2871 break;
2872 case ISN_LOADT:
2873 ht = &curtab->tp_vars->dv_hashtab;
2874 namespace = 't';
2875 break;
2876 default: // Cannot reach here
2877 return NOTDONE;
2878 }
2879 di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
2880
Bram Moolenaar06b77222022-01-25 15:51:56 +00002881 if (di == NULL)
2882 {
Bram Moolenaarfe732552022-02-22 19:39:13 +00002883 if (isn_type == ISN_LOADG)
2884 {
2885 ufunc_T *ufunc = find_func(iptr->isn_arg.string, TRUE);
2886
2887 // g:Something could be a function
2888 if (ufunc != NULL)
2889 {
2890 typval_T *tv = STACK_TV_BOT(0);
2891
2892 ++ectx->ec_stack.ga_len;
2893 tv->v_type = VAR_FUNC;
2894 tv->vval.v_string = alloc(STRLEN(iptr->isn_arg.string) + 3);
2895 if (tv->vval.v_string == NULL)
2896 return FAIL;
2897 STRCPY(tv->vval.v_string, "g:");
2898 STRCPY(tv->vval.v_string + 2, iptr->isn_arg.string);
2899 return OK;
2900 }
2901 }
Bram Moolenaar06b77222022-01-25 15:51:56 +00002902 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarfe732552022-02-22 19:39:13 +00002903 if (vim_strchr(iptr->isn_arg.string, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar06b77222022-01-25 15:51:56 +00002904 // no check if the item exists in the script but
2905 // isn't exported, it is too complicated
Bram Moolenaarfe732552022-02-22 19:39:13 +00002906 semsg(_(e_item_not_found_in_script_str), iptr->isn_arg.string);
Bram Moolenaar06b77222022-01-25 15:51:56 +00002907 else
2908 semsg(_(e_undefined_variable_char_str),
Bram Moolenaarfe732552022-02-22 19:39:13 +00002909 namespace, iptr->isn_arg.string);
Bram Moolenaar06b77222022-01-25 15:51:56 +00002910 return FAIL;
2911 }
2912 else
2913 {
2914 copy_tv(&di->di_tv, STACK_TV_BOT(0));
2915 ++ectx->ec_stack.ga_len;
2916 }
2917 return OK;
2918}
2919
2920/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02002921 * Execute instructions in execution context "ectx".
2922 * Return OK or FAIL;
2923 */
2924 static int
2925exec_instructions(ectx_T *ectx)
2926{
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002927 int ret = FAIL;
2928 int save_trylevel_at_start = ectx->ec_trylevel_at_start;
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02002929 int dict_stack_len_at_start = dict_stack.ga_len;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01002930
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02002931 // Start execution at the first instruction.
Bram Moolenaar4c137212021-04-19 16:48:48 +02002932 ectx->ec_iidx = 0;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01002933
Bram Moolenaarff652882021-05-16 15:24:49 +02002934 // Only catch exceptions in this instruction list.
2935 ectx->ec_trylevel_at_start = trylevel;
2936
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002937 for (;;)
2938 {
Bram Moolenaara7490192021-07-22 12:26:14 +02002939 static int breakcheck_count = 0; // using "static" makes it faster
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002940 isn_T *iptr;
Bram Moolenaara7490192021-07-22 12:26:14 +02002941 typval_T *tv;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002942
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002943 if (unlikely(++breakcheck_count >= 100))
Bram Moolenaar270d0382020-05-15 21:42:53 +02002944 {
2945 line_breakcheck();
2946 breakcheck_count = 0;
2947 }
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002948 if (unlikely(got_int))
Bram Moolenaar20431c92020-03-20 18:39:46 +01002949 {
2950 // Turn CTRL-C into an exception.
2951 got_int = FALSE;
Bram Moolenaar97acfc72020-03-22 13:44:28 +01002952 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002953 goto theend;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002954 did_throw = TRUE;
2955 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002956
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002957 if (unlikely(did_emsg && msg_list != NULL && *msg_list != NULL))
Bram Moolenaara26b9702020-04-18 19:53:28 +02002958 {
2959 // Turn an error message into an exception.
2960 did_emsg = FALSE;
2961 if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002962 goto theend;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002963 did_throw = TRUE;
2964 *msg_list = NULL;
2965 }
2966
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002967 if (unlikely(did_throw))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002968 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02002969 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002970 trycmd_T *trycmd = NULL;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002971 int index = trystack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002972
2973 // An exception jumps to the first catch, finally, or returns from
2974 // the current function.
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002975 while (index > 0)
2976 {
2977 trycmd = ((trycmd_T *)trystack->ga_data) + index - 1;
Bram Moolenaar834193a2021-06-30 20:39:15 +02002978 if (!trycmd->tcd_in_catch || trycmd->tcd_finally_idx != 0)
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002979 break;
2980 // In the catch and finally block of this try we have to go up
2981 // one level.
2982 --index;
2983 trycmd = NULL;
2984 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02002985 if (trycmd != NULL && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002986 {
Bram Moolenaar834193a2021-06-30 20:39:15 +02002987 if (trycmd->tcd_in_catch)
2988 {
2989 // exception inside ":catch", jump to ":finally" once
2990 ectx->ec_iidx = trycmd->tcd_finally_idx;
2991 trycmd->tcd_finally_idx = 0;
2992 }
2993 else
2994 // jump to first ":catch"
2995 ectx->ec_iidx = trycmd->tcd_catch_idx;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002996 trycmd->tcd_in_catch = TRUE;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002997 did_throw = FALSE; // don't come back here until :endtry
2998 trycmd->tcd_did_throw = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002999 }
3000 else
3001 {
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02003002 // Not inside try or need to return from current functions.
3003 // Push a dummy return value.
Bram Moolenaar35578162021-08-02 19:10:38 +02003004 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003005 goto theend;
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02003006 tv = STACK_TV_BOT(0);
3007 tv->v_type = VAR_NUMBER;
3008 tv->vval.v_number = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003009 ++ectx->ec_stack.ga_len;
3010 if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003011 {
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02003012 // At the toplevel we are done.
Bram Moolenaar257cc5e2020-02-19 17:06:11 +01003013 need_rethrow = TRUE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003014 if (handle_closure_in_use(ectx, FALSE) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003015 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003016 goto done;
3017 }
3018
Bram Moolenaar4c137212021-04-19 16:48:48 +02003019 if (func_return(ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003020 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003021 }
3022 continue;
3023 }
3024
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003025 /*
3026 * Big switch on the instruction. Most compilers will be turning this
3027 * into an efficient lookup table, since the "case" values are an enum
3028 * with sequential numbers. It may look ugly, but it should be the
3029 * most efficient way.
3030 */
Bram Moolenaar4c137212021-04-19 16:48:48 +02003031 iptr = &ectx->ec_instr[ectx->ec_iidx++];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003032 switch (iptr->isn_type)
3033 {
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +00003034 // Constructor, first instruction in a new() method.
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003035 case ISN_CONSTRUCT:
3036 // "this" is always the local variable at index zero
3037 tv = STACK_TV_VAR(0);
3038 tv->v_type = VAR_OBJECT;
3039 tv->vval.v_object = alloc_clear(
3040 iptr->isn_arg.construct.construct_size);
3041 tv->vval.v_object->obj_class =
3042 iptr->isn_arg.construct.construct_class;
Bram Moolenaard28d7b92022-12-08 20:42:00 +00003043 ++tv->vval.v_object->obj_class->class_refcount;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003044 tv->vval.v_object->obj_refcount = 1;
Bram Moolenaard28d7b92022-12-08 20:42:00 +00003045 object_created(tv->vval.v_object);
Bram Moolenaar00b28d62022-12-08 15:32:33 +00003046 break;
3047
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003048 // execute Ex command line
3049 case ISN_EXEC:
Bram Moolenaaraacc9662021-08-13 19:40:51 +02003050 if (exec_command(iptr) == FAIL)
3051 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003052 break;
3053
Bram Moolenaar20677332021-06-06 17:02:53 +02003054 // execute Ex command line split at NL characters.
3055 case ISN_EXEC_SPLIT:
3056 {
3057 source_cookie_T cookie;
Bram Moolenaar518df272021-06-06 17:34:13 +02003058 char_u *line;
Bram Moolenaar20677332021-06-06 17:02:53 +02003059
3060 SOURCING_LNUM = iptr->isn_lnum;
3061 CLEAR_FIELD(cookie);
3062 cookie.sourcing_lnum = iptr->isn_lnum - 1;
3063 cookie.nextline = iptr->isn_arg.string;
Bram Moolenaar518df272021-06-06 17:34:13 +02003064 line = get_split_sourceline(0, &cookie, 0, 0);
3065 if (do_cmdline(line,
Bram Moolenaar20677332021-06-06 17:02:53 +02003066 get_split_sourceline, &cookie,
3067 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED)
3068 == FAIL
3069 || did_emsg)
Bram Moolenaar518df272021-06-06 17:34:13 +02003070 {
3071 vim_free(line);
Bram Moolenaar20677332021-06-06 17:02:53 +02003072 goto on_error;
Bram Moolenaar518df272021-06-06 17:34:13 +02003073 }
3074 vim_free(line);
Bram Moolenaar20677332021-06-06 17:02:53 +02003075 }
3076 break;
3077
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00003078 // execute Ex command line that is only a range
3079 case ISN_EXECRANGE:
3080 {
3081 exarg_T ea;
3082 char *error = NULL;
3083
3084 CLEAR_FIELD(ea);
3085 ea.cmdidx = CMD_SIZE;
3086 ea.addr_type = ADDR_LINES;
3087 ea.cmd = iptr->isn_arg.string;
Bram Moolenaar0c7f2612022-02-17 19:44:07 +00003088 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00003089 parse_cmd_address(&ea, &error, FALSE);
Bram Moolenaar01a4dcb2021-12-04 13:15:10 +00003090 if (ea.cmd == NULL)
3091 goto on_error;
Bram Moolenaar0c7f2612022-02-17 19:44:07 +00003092 // error is always NULL when using ADDR_LINES
3093 error = ex_range_without_command(&ea);
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00003094 if (error != NULL)
3095 {
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00003096 emsg(error);
3097 goto on_error;
3098 }
3099 }
3100 break;
3101
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02003102 // Evaluate an expression with legacy syntax, push it onto the
3103 // stack.
3104 case ISN_LEGACY_EVAL:
3105 {
3106 char_u *arg = iptr->isn_arg.string;
3107 int res;
3108 int save_flags = cmdmod.cmod_flags;
3109
Bram Moolenaar35578162021-08-02 19:10:38 +02003110 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003111 goto theend;
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02003112 tv = STACK_TV_BOT(0);
3113 init_tv(tv);
3114 cmdmod.cmod_flags |= CMOD_LEGACY;
3115 res = eval0(arg, tv, NULL, &EVALARG_EVALUATE);
3116 cmdmod.cmod_flags = save_flags;
3117 if (res == FAIL)
3118 goto on_error;
3119 ++ectx->ec_stack.ga_len;
3120 }
3121 break;
3122
Bram Moolenaarf18332f2021-05-07 17:55:55 +02003123 // push typeval VAR_INSTR with instructions to be executed
3124 case ISN_INSTR:
3125 {
Bram Moolenaar35578162021-08-02 19:10:38 +02003126 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003127 goto theend;
Bram Moolenaarf18332f2021-05-07 17:55:55 +02003128 tv = STACK_TV_BOT(0);
3129 tv->vval.v_instr = ALLOC_ONE(instr_T);
3130 if (tv->vval.v_instr == NULL)
3131 goto on_error;
3132 ++ectx->ec_stack.ga_len;
3133
3134 tv->v_type = VAR_INSTR;
3135 tv->vval.v_instr->instr_ectx = ectx;
3136 tv->vval.v_instr->instr_instr = iptr->isn_arg.instr;
3137 }
3138 break;
3139
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003140 case ISN_SOURCE:
3141 {
Bram Moolenaar89445512022-04-14 12:58:23 +01003142 int notused;
LemonBoy77142312022-04-15 20:50:46 +01003143
Bram Moolenaar89445512022-04-14 12:58:23 +01003144 SOURCING_LNUM = iptr->isn_lnum;
3145 if (may_load_script((int)iptr->isn_arg.number, &notused)
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003146 == FAIL)
Bram Moolenaar89445512022-04-14 12:58:23 +01003147 goto on_error;
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003148 }
3149 break;
3150
Bram Moolenaar4c137212021-04-19 16:48:48 +02003151 // execute :substitute with an expression
3152 case ISN_SUBSTITUTE:
3153 {
3154 subs_T *subs = &iptr->isn_arg.subs;
3155 source_cookie_T cookie;
3156 struct subs_expr_S *save_instr = substitute_instr;
3157 struct subs_expr_S subs_instr;
3158 int res;
3159
3160 subs_instr.subs_ectx = ectx;
3161 subs_instr.subs_instr = subs->subs_instr;
3162 subs_instr.subs_status = OK;
3163 substitute_instr = &subs_instr;
3164
3165 SOURCING_LNUM = iptr->isn_lnum;
3166 // This is very much like ISN_EXEC
3167 CLEAR_FIELD(cookie);
3168 cookie.sourcing_lnum = iptr->isn_lnum - 1;
3169 res = do_cmdline(subs->subs_cmd,
3170 getsourceline, &cookie,
3171 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
3172 substitute_instr = save_instr;
3173
3174 if (res == FAIL || did_emsg
3175 || subs_instr.subs_status == FAIL)
3176 goto on_error;
3177 }
3178 break;
3179
3180 case ISN_FINISH:
3181 goto done;
3182
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02003183 case ISN_REDIRSTART:
3184 // create a dummy entry for var_redir_str()
3185 if (alloc_redir_lval() == FAIL)
3186 goto on_error;
3187
3188 // The output is stored in growarray "redir_ga" until
3189 // redirection ends.
3190 init_redir_ga();
3191 redir_vname = 1;
3192 break;
3193
3194 case ISN_REDIREND:
3195 {
3196 char_u *res = get_clear_redir_ga();
3197
3198 // End redirection, put redirected text on the stack.
3199 clear_redir_lval();
3200 redir_vname = 0;
3201
Bram Moolenaar35578162021-08-02 19:10:38 +02003202 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02003203 {
3204 vim_free(res);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003205 goto theend;
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02003206 }
3207 tv = STACK_TV_BOT(0);
3208 tv->v_type = VAR_STRING;
3209 tv->vval.v_string = res;
3210 ++ectx->ec_stack.ga_len;
3211 }
3212 break;
3213
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02003214 case ISN_CEXPR_AUCMD:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02003215#ifdef FEAT_QUICKFIX
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003216 force_abort = TRUE;
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02003217 if (trigger_cexpr_autocmd(iptr->isn_arg.number) == FAIL)
3218 goto on_error;
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003219 force_abort = FALSE;
Bram Moolenaarb7c97812021-05-05 22:51:39 +02003220#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02003221 break;
3222
3223 case ISN_CEXPR_CORE:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02003224#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02003225 {
3226 exarg_T ea;
3227 int res;
3228
3229 CLEAR_FIELD(ea);
3230 ea.cmdidx = iptr->isn_arg.cexpr.cexpr_ref->cer_cmdidx;
3231 ea.forceit = iptr->isn_arg.cexpr.cexpr_ref->cer_forceit;
3232 ea.cmdlinep = &iptr->isn_arg.cexpr.cexpr_ref->cer_cmdline;
3233 --ectx->ec_stack.ga_len;
3234 tv = STACK_TV_BOT(0);
Bram Moolenaarbd683e32022-07-18 17:49:03 +01003235 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02003236 res = cexpr_core(&ea, tv);
3237 clear_tv(tv);
3238 if (res == FAIL)
3239 goto on_error;
3240 }
Bram Moolenaarb7c97812021-05-05 22:51:39 +02003241#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02003242 break;
3243
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02003244 // execute Ex command from pieces on the stack
3245 case ISN_EXECCONCAT:
3246 {
3247 int count = iptr->isn_arg.number;
Bram Moolenaar7f6f56f2020-04-30 20:21:43 +02003248 size_t len = 0;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02003249 int pass;
3250 int i;
3251 char_u *cmd = NULL;
3252 char_u *str;
3253
3254 for (pass = 1; pass <= 2; ++pass)
3255 {
3256 for (i = 0; i < count; ++i)
3257 {
3258 tv = STACK_TV_BOT(i - count);
3259 str = tv->vval.v_string;
3260 if (str != NULL && *str != NUL)
3261 {
3262 if (pass == 2)
3263 STRCPY(cmd + len, str);
3264 len += STRLEN(str);
3265 }
3266 if (pass == 2)
3267 clear_tv(tv);
3268 }
3269 if (pass == 1)
3270 {
3271 cmd = alloc(len + 1);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02003272 if (unlikely(cmd == NULL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003273 goto theend;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02003274 len = 0;
3275 }
3276 }
3277
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02003278 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02003279 do_cmdline_cmd(cmd);
3280 vim_free(cmd);
3281 }
3282 break;
3283
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003284 // execute :echo {string} ...
3285 case ISN_ECHO:
3286 {
3287 int count = iptr->isn_arg.echo.echo_count;
3288 int atstart = TRUE;
3289 int needclr = TRUE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003290 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003291
3292 for (idx = 0; idx < count; ++idx)
3293 {
3294 tv = STACK_TV_BOT(idx - count);
3295 echo_one(tv, iptr->isn_arg.echo.echo_with_white,
3296 &atstart, &needclr);
3297 clear_tv(tv);
3298 }
Bram Moolenaare0807ea2020-02-20 22:18:06 +01003299 if (needclr)
3300 msg_clr_eos();
Bram Moolenaar4c137212021-04-19 16:48:48 +02003301 ectx->ec_stack.ga_len -= count;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003302 }
3303 break;
3304
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003305 // :execute {string} ...
3306 // :echomsg {string} ...
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01003307 // :echowindow {string} ...
Bram Moolenaar7de62622021-08-07 15:05:47 +02003308 // :echoconsole {string} ...
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003309 // :echoerr {string} ...
Bram Moolenaarad39c092020-02-26 18:23:43 +01003310 case ISN_EXECUTE:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003311 case ISN_ECHOMSG:
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01003312 case ISN_ECHOWINDOW:
Bram Moolenaar7de62622021-08-07 15:05:47 +02003313 case ISN_ECHOCONSOLE:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003314 case ISN_ECHOERR:
Bram Moolenaarad39c092020-02-26 18:23:43 +01003315 {
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01003316 int count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01003317 garray_T ga;
3318 char_u buf[NUMBUFLEN];
3319 char_u *p;
3320 int len;
3321 int failed = FALSE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003322 int idx;
Bram Moolenaarad39c092020-02-26 18:23:43 +01003323
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01003324 if (iptr->isn_type == ISN_ECHOWINDOW)
3325 count = iptr->isn_arg.echowin.ewin_count;
3326 else
3327 count = iptr->isn_arg.number;
Bram Moolenaarad39c092020-02-26 18:23:43 +01003328 ga_init2(&ga, 1, 80);
3329 for (idx = 0; idx < count; ++idx)
3330 {
3331 tv = STACK_TV_BOT(idx - count);
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02003332 if (iptr->isn_type == ISN_EXECUTE)
Bram Moolenaarad39c092020-02-26 18:23:43 +01003333 {
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02003334 if (tv->v_type == VAR_CHANNEL
3335 || tv->v_type == VAR_JOB)
3336 {
3337 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar68db9962021-05-09 23:19:22 +02003338 semsg(_(e_using_invalid_value_as_string_str),
3339 vartype_name(tv->v_type));
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02003340 break;
3341 }
3342 else
3343 p = tv_get_string_buf(tv, buf);
Bram Moolenaarad39c092020-02-26 18:23:43 +01003344 }
3345 else
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02003346 p = tv_stringify(tv, buf);
Bram Moolenaarad39c092020-02-26 18:23:43 +01003347
3348 len = (int)STRLEN(p);
Bram Moolenaar35578162021-08-02 19:10:38 +02003349 if (GA_GROW_FAILS(&ga, len + 2))
Bram Moolenaarad39c092020-02-26 18:23:43 +01003350 failed = TRUE;
3351 else
3352 {
3353 if (ga.ga_len > 0)
3354 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
3355 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
3356 ga.ga_len += len;
3357 }
3358 clear_tv(tv);
3359 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02003360 ectx->ec_stack.ga_len -= count;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02003361 if (failed)
Bram Moolenaarc71ee822020-11-21 11:45:50 +01003362 {
3363 ga_clear(&ga);
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02003364 goto on_error;
Bram Moolenaarc71ee822020-11-21 11:45:50 +01003365 }
Bram Moolenaarad39c092020-02-26 18:23:43 +01003366
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02003367 if (ga.ga_data != NULL)
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003368 {
3369 if (iptr->isn_type == ISN_EXECUTE)
Bram Moolenaar430deb12020-08-23 16:29:11 +02003370 {
3371 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003372 do_cmdline_cmd((char_u *)ga.ga_data);
Bram Moolenaareeece9e2020-11-20 19:26:48 +01003373 if (did_emsg)
Bram Moolenaarc71ee822020-11-21 11:45:50 +01003374 {
3375 ga_clear(&ga);
Bram Moolenaareeece9e2020-11-20 19:26:48 +01003376 goto on_error;
Bram Moolenaarc71ee822020-11-21 11:45:50 +01003377 }
Bram Moolenaar430deb12020-08-23 16:29:11 +02003378 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003379 else
3380 {
3381 msg_sb_eol();
3382 if (iptr->isn_type == ISN_ECHOMSG)
3383 {
3384 msg_attr(ga.ga_data, echo_attr);
3385 out_flush();
3386 }
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01003387#ifdef HAS_MESSAGE_WINDOW
3388 else if (iptr->isn_type == ISN_ECHOWINDOW)
3389 {
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01003390 start_echowindow(
3391 iptr->isn_arg.echowin.ewin_time);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01003392 msg_attr(ga.ga_data, echo_attr);
3393 end_echowindow();
3394 }
3395#endif
Bram Moolenaar7de62622021-08-07 15:05:47 +02003396 else if (iptr->isn_type == ISN_ECHOCONSOLE)
3397 {
3398 ui_write(ga.ga_data, (int)STRLEN(ga.ga_data),
3399 TRUE);
3400 ui_write((char_u *)"\r\n", 2, TRUE);
3401 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003402 else
3403 {
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003404 SOURCING_LNUM = iptr->isn_lnum;
3405 emsg(ga.ga_data);
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02003406 }
3407 }
3408 }
Bram Moolenaarad39c092020-02-26 18:23:43 +01003409 ga_clear(&ga);
3410 }
3411 break;
3412
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003413 // load local variable or argument
3414 case ISN_LOAD:
Bram Moolenaar35578162021-08-02 19:10:38 +02003415 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003416 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003417 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003418 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003419 break;
3420
3421 // load v: variable
3422 case ISN_LOADV:
Bram Moolenaar35578162021-08-02 19:10:38 +02003423 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003424 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003425 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003426 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003427 break;
3428
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003429 // load s: variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003430 case ISN_LOADSCRIPT:
3431 {
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01003432 scriptref_T *sref = iptr->isn_arg.script.scriptref;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003433 svar_T *sv;
3434
Bram Moolenaar6db660b2021-08-01 14:08:54 +02003435 sv = get_script_svar(sref, ectx->ec_dfunc_idx);
Bram Moolenaar07a65d22020-12-26 20:09:15 +01003436 if (sv == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003437 goto theend;
Bram Moolenaar859cc212022-03-28 15:22:35 +01003438 allocate_if_null(sv);
Bram Moolenaar35578162021-08-02 19:10:38 +02003439 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003440 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003441 copy_tv(sv->sv_tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003442 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003443 }
3444 break;
3445
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003446 // load s: variable in old script or autoload import
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003447 case ISN_LOADS:
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003448 case ISN_LOADEXPORT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003449 {
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003450 int sid = iptr->isn_arg.loadstore.ls_sid;
3451 hashtab_T *ht = &SCRIPT_VARS(sid);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003452 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003453 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003454
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003455 if (di == NULL)
3456 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003457 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003458 semsg(_(e_undefined_variable_str), name);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02003459 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003460 }
3461 else
3462 {
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003463 if (iptr->isn_type == ISN_LOADEXPORT)
3464 {
3465 int idx = get_script_item_idx(sid, name, 0,
3466 NULL, NULL);
3467 svar_T *sv;
3468
3469 if (idx >= 0)
3470 {
3471 sv = ((svar_T *)SCRIPT_ITEM(sid)
3472 ->sn_var_vals.ga_data) + idx;
Bram Moolenaaraa7d0c22022-04-05 21:40:38 +01003473 if ((sv->sv_flags & SVFLAG_EXPORTED) == 0)
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003474 {
3475 SOURCING_LNUM = iptr->isn_lnum;
3476 semsg(_(e_item_not_exported_in_script_str),
3477 name);
3478 goto on_error;
3479 }
3480 }
3481 }
Bram Moolenaar35578162021-08-02 19:10:38 +02003482 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003483 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003484 copy_tv(&di->di_tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003485 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003486 }
3487 }
3488 break;
3489
Bram Moolenaard3aac292020-04-19 14:32:17 +02003490 // load g:/b:/w:/t: variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003491 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02003492 case ISN_LOADB:
3493 case ISN_LOADW:
3494 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003495 {
Bram Moolenaar06b77222022-01-25 15:51:56 +00003496 int res = load_namespace_var(ectx, iptr->isn_type, iptr);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003497
Bram Moolenaar06b77222022-01-25 15:51:56 +00003498 if (res == NOTDONE)
Bram Moolenaarcbbc48f2022-01-18 12:58:28 +00003499 goto theend;
Bram Moolenaar06b77222022-01-25 15:51:56 +00003500 if (res == FAIL)
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02003501 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003502 }
Bram Moolenaar06b77222022-01-25 15:51:56 +00003503
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003504 break;
3505
Bram Moolenaar03290b82020-12-19 16:30:44 +01003506 // load autoload variable
3507 case ISN_LOADAUTO:
3508 {
3509 char_u *name = iptr->isn_arg.string;
3510
Bram Moolenaar35578162021-08-02 19:10:38 +02003511 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003512 goto theend;
Bram Moolenaar03290b82020-12-19 16:30:44 +01003513 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaard5f400c2022-01-06 21:10:28 +00003514 if (eval_variable(name, (int)STRLEN(name), 0,
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01003515 STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL)
Bram Moolenaar03290b82020-12-19 16:30:44 +01003516 goto on_error;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003517 ++ectx->ec_stack.ga_len;
Bram Moolenaar03290b82020-12-19 16:30:44 +01003518 }
3519 break;
3520
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003521 // load g:/b:/w:/t: namespace
3522 case ISN_LOADGDICT:
3523 case ISN_LOADBDICT:
3524 case ISN_LOADWDICT:
3525 case ISN_LOADTDICT:
3526 {
3527 dict_T *d = NULL;
3528
3529 switch (iptr->isn_type)
3530 {
Bram Moolenaar682d0a12020-07-19 20:48:59 +02003531 case ISN_LOADGDICT: d = get_globvar_dict(); break;
3532 case ISN_LOADBDICT: d = curbuf->b_vars; break;
3533 case ISN_LOADWDICT: d = curwin->w_vars; break;
3534 case ISN_LOADTDICT: d = curtab->tp_vars; break;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003535 default: // Cannot reach here
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003536 goto theend;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003537 }
Bram Moolenaar35578162021-08-02 19:10:38 +02003538 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003539 goto theend;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003540 tv = STACK_TV_BOT(0);
3541 tv->v_type = VAR_DICT;
3542 tv->v_lock = 0;
3543 tv->vval.v_dict = d;
Bram Moolenaar1bd3cb22021-02-24 12:27:31 +01003544 ++d->dv_refcount;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003545 ++ectx->ec_stack.ga_len;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003546 }
3547 break;
3548
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003549 // load &option
3550 case ISN_LOADOPT:
3551 {
3552 typval_T optval;
3553 char_u *name = iptr->isn_arg.string;
3554
Bram Moolenaara8c17702020-04-01 21:17:24 +02003555 // This is not expected to fail, name is checked during
3556 // compilation: don't set SOURCING_LNUM.
Bram Moolenaar35578162021-08-02 19:10:38 +02003557 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003558 goto theend;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003559 if (eval_option(&name, &optval, TRUE) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003560 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003561 *STACK_TV_BOT(0) = optval;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003562 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003563 }
3564 break;
3565
3566 // load $ENV
3567 case ISN_LOADENV:
3568 {
3569 typval_T optval;
3570 char_u *name = iptr->isn_arg.string;
3571
Bram Moolenaar35578162021-08-02 19:10:38 +02003572 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003573 goto theend;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003574 // name is always valid, checked when compiling
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003575 (void)eval_env_var(&name, &optval, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003576 *STACK_TV_BOT(0) = optval;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003577 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003578 }
3579 break;
3580
3581 // load @register
3582 case ISN_LOADREG:
Bram Moolenaar35578162021-08-02 19:10:38 +02003583 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003584 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003585 tv = STACK_TV_BOT(0);
3586 tv->v_type = VAR_STRING;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003587 tv->v_lock = 0;
Bram Moolenaar1e021e62020-10-16 20:25:23 +02003588 // This may result in NULL, which should be equivalent to an
3589 // empty string.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003590 tv->vval.v_string = get_reg_contents(
3591 iptr->isn_arg.number, GREG_EXPR_SRC);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003592 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003593 break;
3594
3595 // store local variable
3596 case ISN_STORE:
Bram Moolenaar4c137212021-04-19 16:48:48 +02003597 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003598 tv = STACK_TV_VAR(iptr->isn_arg.number);
3599 clear_tv(tv);
3600 *tv = *STACK_TV_BOT(0);
3601 break;
3602
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003603 // store s: variable in old script or autoload import
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003604 case ISN_STORES:
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003605 case ISN_STOREEXPORT:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003606 {
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003607 int sid = iptr->isn_arg.loadstore.ls_sid;
3608 hashtab_T *ht = &SCRIPT_VARS(sid);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003609 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003610 dictitem_T *di = find_var_in_ht(ht, 0,
3611 iptr->isn_type == ISN_STORES
3612 ? name + 2 : name, TRUE);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003613
Bram Moolenaar4c137212021-04-19 16:48:48 +02003614 --ectx->ec_stack.ga_len;
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003615 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003616 if (di == NULL)
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003617 {
3618 if (iptr->isn_type == ISN_STOREEXPORT)
3619 {
3620 semsg(_(e_undefined_variable_str), name);
Bram Moolenaard1d26842022-03-31 10:13:47 +01003621 clear_tv(STACK_TV_BOT(0));
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003622 goto on_error;
3623 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003624 store_var(name, STACK_TV_BOT(0));
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003625 }
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003626 else
3627 {
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003628 if (iptr->isn_type == ISN_STOREEXPORT)
3629 {
3630 int idx = get_script_item_idx(sid, name, 0,
3631 NULL, NULL);
3632
Bram Moolenaar06651632022-04-27 17:54:25 +01003633 // can this ever fail?
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003634 if (idx >= 0)
3635 {
3636 svar_T *sv = ((svar_T *)SCRIPT_ITEM(sid)
3637 ->sn_var_vals.ga_data) + idx;
3638
Bram Moolenaaraa7d0c22022-04-05 21:40:38 +01003639 if ((sv->sv_flags & SVFLAG_EXPORTED) == 0)
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003640 {
3641 semsg(_(e_item_not_exported_in_script_str),
3642 name);
Bram Moolenaard1d26842022-03-31 10:13:47 +01003643 clear_tv(STACK_TV_BOT(0));
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01003644 goto on_error;
3645 }
3646 }
3647 }
Bram Moolenaardcf29ac2021-04-02 14:44:02 +02003648 if (var_check_permission(di, name) == FAIL)
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02003649 {
3650 clear_tv(STACK_TV_BOT(0));
Bram Moolenaardcf29ac2021-04-02 14:44:02 +02003651 goto on_error;
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02003652 }
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003653 clear_tv(&di->di_tv);
3654 di->di_tv = *STACK_TV_BOT(0);
3655 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003656 }
3657 break;
3658
3659 // store script-local variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003660 case ISN_STORESCRIPT:
3661 {
Bram Moolenaar07a65d22020-12-26 20:09:15 +01003662 scriptref_T *sref = iptr->isn_arg.script.scriptref;
3663 svar_T *sv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003664
Bram Moolenaar6db660b2021-08-01 14:08:54 +02003665 sv = get_script_svar(sref, ectx->ec_dfunc_idx);
Bram Moolenaar07a65d22020-12-26 20:09:15 +01003666 if (sv == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003667 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003668 --ectx->ec_stack.ga_len;
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02003669
3670 // "const" and "final" are checked at compile time, locking
3671 // the value needs to be checked here.
3672 SOURCING_LNUM = iptr->isn_lnum;
3673 if (value_check_lock(sv->sv_tv->v_lock, sv->sv_name, FALSE))
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02003674 {
3675 clear_tv(STACK_TV_BOT(0));
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02003676 goto on_error;
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02003677 }
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02003678
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003679 clear_tv(sv->sv_tv);
3680 *sv->sv_tv = *STACK_TV_BOT(0);
3681 }
3682 break;
3683
3684 // store option
3685 case ISN_STOREOPT:
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003686 case ISN_STOREFUNCOPT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003687 {
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003688 char_u *opt_name = iptr->isn_arg.storeopt.so_name;
3689 int opt_flags = iptr->isn_arg.storeopt.so_flags;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003690 long n = 0;
3691 char_u *s = NULL;
3692 char *msg;
Bram Moolenaar2ef91562021-12-11 16:14:07 +00003693 char_u numbuf[NUMBUFLEN];
3694 char_u *tofree = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003695
Bram Moolenaar4c137212021-04-19 16:48:48 +02003696 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003697 tv = STACK_TV_BOT(0);
3698 if (tv->v_type == VAR_STRING)
Bram Moolenaar97a2af32020-01-28 22:52:48 +01003699 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003700 s = tv->vval.v_string;
Bram Moolenaar97a2af32020-01-28 22:52:48 +01003701 if (s == NULL)
3702 s = (char_u *)"";
3703 }
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003704 else if (iptr->isn_type == ISN_STOREFUNCOPT)
3705 {
3706 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar2ef91562021-12-11 16:14:07 +00003707 // If the option can be set to a function reference or
3708 // a lambda and the passed value is a function
3709 // reference, then convert it to the name (string) of
3710 // the function reference.
3711 s = tv2string(tv, &tofree, numbuf, 0);
3712 if (s == NULL || *s == NUL)
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003713 {
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003714 // cannot happen?
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003715 clear_tv(tv);
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003716 vim_free(tofree);
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003717 goto on_error;
3718 }
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003719 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003720 else
Bram Moolenaara6e67e42020-05-15 23:36:40 +02003721 // must be VAR_NUMBER, CHECKTYPE makes sure
3722 n = tv->vval.v_number;
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003723 msg = set_option_value(opt_name, n, s, opt_flags);
Bram Moolenaare75ba262020-05-16 15:43:31 +02003724 clear_tv(tv);
Bram Moolenaar2ef91562021-12-11 16:14:07 +00003725 vim_free(tofree);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003726 if (msg != NULL)
3727 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003728 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003729 emsg(_(msg));
Bram Moolenaare8593122020-07-18 15:17:02 +02003730 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003731 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003732 }
3733 break;
3734
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003735 // store $ENV
3736 case ISN_STOREENV:
Bram Moolenaar4c137212021-04-19 16:48:48 +02003737 --ectx->ec_stack.ga_len;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003738 tv = STACK_TV_BOT(0);
3739 vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
3740 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003741 break;
3742
3743 // store @r
3744 case ISN_STOREREG:
3745 {
3746 int reg = iptr->isn_arg.number;
3747
Bram Moolenaar4c137212021-04-19 16:48:48 +02003748 --ectx->ec_stack.ga_len;
Bram Moolenaar401d9ff2020-02-19 18:14:44 +01003749 tv = STACK_TV_BOT(0);
Bram Moolenaar74f4a962021-06-17 21:03:07 +02003750 write_reg_contents(reg, tv_get_string(tv), -1, FALSE);
Bram Moolenaar401d9ff2020-02-19 18:14:44 +01003751 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003752 }
3753 break;
3754
3755 // store v: variable
3756 case ISN_STOREV:
Bram Moolenaar4c137212021-04-19 16:48:48 +02003757 --ectx->ec_stack.ga_len;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003758 if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
3759 == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02003760 // should not happen, type is checked when compiling
3761 goto on_error;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003762 break;
3763
Bram Moolenaard3aac292020-04-19 14:32:17 +02003764 // store g:/b:/w:/t: variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003765 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02003766 case ISN_STOREB:
3767 case ISN_STOREW:
3768 case ISN_STORET:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003769 {
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01003770 dictitem_T *di;
3771 hashtab_T *ht;
3772 char_u *name = iptr->isn_arg.string + 2;
3773
Bram Moolenaard3aac292020-04-19 14:32:17 +02003774 switch (iptr->isn_type)
3775 {
3776 case ISN_STOREG:
3777 ht = get_globvar_ht();
3778 break;
3779 case ISN_STOREB:
3780 ht = &curbuf->b_vars->dv_hashtab;
3781 break;
3782 case ISN_STOREW:
3783 ht = &curwin->w_vars->dv_hashtab;
3784 break;
3785 case ISN_STORET:
3786 ht = &curtab->tp_vars->dv_hashtab;
3787 break;
3788 default: // Cannot reach here
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003789 goto theend;
Bram Moolenaard3aac292020-04-19 14:32:17 +02003790 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003791
Bram Moolenaar4c137212021-04-19 16:48:48 +02003792 --ectx->ec_stack.ga_len;
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01003793 di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003794 if (di == NULL)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003795 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003796 else
3797 {
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01003798 SOURCING_LNUM = iptr->isn_lnum;
3799 if (var_check_permission(di, name) == FAIL)
3800 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003801 clear_tv(&di->di_tv);
3802 di->di_tv = *STACK_TV_BOT(0);
3803 }
3804 }
3805 break;
3806
Bram Moolenaar03290b82020-12-19 16:30:44 +01003807 // store an autoload variable
3808 case ISN_STOREAUTO:
3809 SOURCING_LNUM = iptr->isn_lnum;
3810 set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE);
3811 clear_tv(STACK_TV_BOT(-1));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003812 --ectx->ec_stack.ga_len;
Bram Moolenaar03290b82020-12-19 16:30:44 +01003813 break;
3814
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003815 // store number in local variable
3816 case ISN_STORENR:
Bram Moolenaara471eea2020-03-04 22:20:26 +01003817 tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003818 clear_tv(tv);
3819 tv->v_type = VAR_NUMBER;
Bram Moolenaara471eea2020-03-04 22:20:26 +01003820 tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003821 break;
3822
Bram Moolenaar590162c2022-12-24 21:24:06 +00003823 // Store a value in a list, dict, blob or object variable.
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01003824 case ISN_STOREINDEX:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003825 {
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003826 int res = execute_storeindex(iptr, ectx);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003827
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003828 if (res == FAIL)
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02003829 goto on_error;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003830 if (res == NOTDONE)
3831 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003832 }
3833 break;
3834
Bram Moolenaarea5c8982022-02-17 14:42:02 +00003835 // store value in list or blob range
Bram Moolenaar68452172021-04-12 21:21:02 +02003836 case ISN_STORERANGE:
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003837 if (execute_storerange(iptr, ectx) == FAIL)
3838 goto on_error;
Bram Moolenaar68452172021-04-12 21:21:02 +02003839 break;
3840
Bram Moolenaard505d172022-12-18 21:42:55 +00003841 case ISN_LOAD_CLASSMEMBER:
3842 {
3843 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3844 goto theend;
3845 classmember_T *cm = &iptr->isn_arg.classmember;
3846 *STACK_TV_BOT(0) =
3847 cm->cm_class->class_members_tv[cm->cm_idx];
3848 ++ectx->ec_stack.ga_len;
3849 }
3850 break;
3851
3852 case ISN_STORE_CLASSMEMBER:
3853 {
3854 classmember_T *cm = &iptr->isn_arg.classmember;
3855 tv = &cm->cm_class->class_members_tv[cm->cm_idx];
3856 clear_tv(tv);
3857 *tv = *STACK_TV_BOT(-1);
3858 --ectx->ec_stack.ga_len;
3859 }
3860 break;
3861
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01003862 // Load or store variable or argument from outer scope.
Bram Moolenaar0186e582021-01-10 18:33:11 +01003863 case ISN_LOADOUTER:
3864 case ISN_STOREOUTER:
3865 {
3866 int depth = iptr->isn_arg.outer.outer_depth;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02003867 outer_T *outer = ectx->ec_outer_ref == NULL ? NULL
3868 : ectx->ec_outer_ref->or_outer;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003869
3870 while (depth > 1 && outer != NULL)
3871 {
3872 outer = outer->out_up;
3873 --depth;
3874 }
3875 if (outer == NULL)
3876 {
3877 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar69c76172021-12-02 16:38:52 +00003878 if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx
3879 || ectx->ec_outer_ref == NULL)
3880 // Possibly :def function called from legacy
3881 // context.
3882 emsg(_(e_closure_called_from_invalid_context));
3883 else
3884 iemsg("LOADOUTER depth more than scope levels");
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003885 goto theend;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003886 }
Bram Moolenaarcc341812022-09-19 15:54:34 +01003887 if (depth < 0)
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01003888 // Variable declared in loop. May be copied if the
3889 // loop block has already ended.
Bram Moolenaarcc341812022-09-19 15:54:34 +01003890 tv = ((typval_T *)outer->out_loop[-depth - 1]
3891 .stack->ga_data)
3892 + outer->out_loop[-depth - 1].var_idx
3893 + iptr->isn_arg.outer.outer_idx;
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01003894 else
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01003895 // Variable declared in a function. May be copied if
3896 // the function has already returned.
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01003897 tv = ((typval_T *)outer->out_stack->ga_data)
3898 + outer->out_frame_idx + STACK_FRAME_SIZE
3899 + iptr->isn_arg.outer.outer_idx;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003900 if (iptr->isn_type == ISN_LOADOUTER)
3901 {
Bram Moolenaar35578162021-08-02 19:10:38 +02003902 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003903 goto theend;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003904 copy_tv(tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003905 ++ectx->ec_stack.ga_len;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003906 }
3907 else
3908 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003909 --ectx->ec_stack.ga_len;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003910 clear_tv(tv);
3911 *tv = *STACK_TV_BOT(0);
3912 }
3913 }
3914 break;
3915
Bram Moolenaar752fc692021-01-04 21:57:11 +01003916 // unlet item in list or dict variable
3917 case ISN_UNLETINDEX:
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003918 if (execute_unletindex(iptr, ectx) == FAIL)
3919 goto on_error;
Bram Moolenaar752fc692021-01-04 21:57:11 +01003920 break;
3921
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01003922 // unlet range of items in list variable
3923 case ISN_UNLETRANGE:
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003924 if (execute_unletrange(iptr, ectx) == FAIL)
3925 goto on_error;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01003926 break;
3927
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003928 // push constant
3929 case ISN_PUSHNR:
3930 case ISN_PUSHBOOL:
3931 case ISN_PUSHSPEC:
3932 case ISN_PUSHF:
3933 case ISN_PUSHS:
3934 case ISN_PUSHBLOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003935 case ISN_PUSHFUNC:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003936 case ISN_PUSHCHANNEL:
3937 case ISN_PUSHJOB:
Bram Moolenaar35578162021-08-02 19:10:38 +02003938 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003939 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003940 tv = STACK_TV_BOT(0);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003941 tv->v_lock = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003942 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003943 switch (iptr->isn_type)
3944 {
3945 case ISN_PUSHNR:
3946 tv->v_type = VAR_NUMBER;
3947 tv->vval.v_number = iptr->isn_arg.number;
3948 break;
3949 case ISN_PUSHBOOL:
3950 tv->v_type = VAR_BOOL;
3951 tv->vval.v_number = iptr->isn_arg.number;
3952 break;
3953 case ISN_PUSHSPEC:
3954 tv->v_type = VAR_SPECIAL;
3955 tv->vval.v_number = iptr->isn_arg.number;
3956 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003957 case ISN_PUSHF:
3958 tv->v_type = VAR_FLOAT;
3959 tv->vval.v_float = iptr->isn_arg.fnumber;
3960 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003961 case ISN_PUSHBLOB:
3962 blob_copy(iptr->isn_arg.blob, tv);
3963 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003964 case ISN_PUSHFUNC:
3965 tv->v_type = VAR_FUNC;
Bram Moolenaar087d2e12020-03-01 15:36:42 +01003966 if (iptr->isn_arg.string == NULL)
3967 tv->vval.v_string = NULL;
3968 else
3969 tv->vval.v_string =
3970 vim_strsave(iptr->isn_arg.string);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003971 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003972 case ISN_PUSHCHANNEL:
3973#ifdef FEAT_JOB_CHANNEL
3974 tv->v_type = VAR_CHANNEL;
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003975 tv->vval.v_channel = NULL;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003976#endif
3977 break;
3978 case ISN_PUSHJOB:
3979#ifdef FEAT_JOB_CHANNEL
3980 tv->v_type = VAR_JOB;
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003981 tv->vval.v_job = NULL;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003982#endif
3983 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003984 default:
3985 tv->v_type = VAR_STRING;
Bram Moolenaarf8691002022-03-10 12:20:53 +00003986 tv->vval.v_string = iptr->isn_arg.string == NULL
3987 ? NULL : vim_strsave(iptr->isn_arg.string);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003988 }
3989 break;
3990
Bram Moolenaar06b77222022-01-25 15:51:56 +00003991 case ISN_AUTOLOAD:
3992 {
3993 char_u *name = iptr->isn_arg.string;
3994
3995 (void)script_autoload(name, FALSE);
3996 if (find_func(name, TRUE))
3997 {
3998 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3999 goto theend;
4000 tv = STACK_TV_BOT(0);
4001 tv->v_lock = 0;
4002 ++ectx->ec_stack.ga_len;
4003 tv->v_type = VAR_FUNC;
4004 tv->vval.v_string = vim_strsave(name);
4005 }
4006 else
4007 {
4008 int res = load_namespace_var(ectx, ISN_LOADG, iptr);
4009
4010 if (res == NOTDONE)
4011 goto theend;
4012 if (res == FAIL)
4013 goto on_error;
4014 }
4015 }
4016 break;
4017
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004018 case ISN_UNLET:
4019 if (do_unlet(iptr->isn_arg.unlet.ul_name,
4020 iptr->isn_arg.unlet.ul_forceit) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02004021 goto on_error;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004022 break;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004023 case ISN_UNLETENV:
LemonBoy77142312022-04-15 20:50:46 +01004024 vim_unsetenv_ext(iptr->isn_arg.unlet.ul_name);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004025 break;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004026
Bram Moolenaaraacc9662021-08-13 19:40:51 +02004027 case ISN_LOCKUNLOCK:
4028 {
4029 typval_T *lval_root_save = lval_root;
4030 int res;
4031
4032 // Stack has the local variable, argument the whole :lock
4033 // or :unlock command, like ISN_EXEC.
4034 --ectx->ec_stack.ga_len;
4035 lval_root = STACK_TV_BOT(0);
4036 res = exec_command(iptr);
4037 clear_tv(lval_root);
4038 lval_root = lval_root_save;
4039 if (res == FAIL)
4040 goto on_error;
4041 }
4042 break;
4043
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02004044 case ISN_LOCKCONST:
4045 item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE);
4046 break;
4047
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004048 // create a list from items on the stack; uses a single allocation
4049 // for the list header and the items
4050 case ISN_NEWLIST:
Bram Moolenaar4c137212021-04-19 16:48:48 +02004051 if (exe_newlist(iptr->isn_arg.number, ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004052 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004053 break;
4054
4055 // create a dict from items on the stack
4056 case ISN_NEWDICT:
4057 {
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01004058 int res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004059
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01004060 SOURCING_LNUM = iptr->isn_lnum;
4061 res = exe_newdict(iptr->isn_arg.number, ectx);
4062 if (res == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004063 goto theend;
Bram Moolenaarec15b1c2022-03-27 16:29:53 +01004064 if (res == MAYBE)
4065 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004066 }
4067 break;
4068
LemonBoy372bcce2022-04-25 12:43:20 +01004069 case ISN_CONCAT:
4070 if (exe_concat(iptr->isn_arg.number, ectx) == FAIL)
4071 goto theend;
4072 break;
4073
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00004074 // create a partial with NULL value
4075 case ISN_NEWPARTIAL:
4076 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
4077 goto theend;
4078 ++ectx->ec_stack.ga_len;
4079 tv = STACK_TV_BOT(-1);
4080 tv->v_type = VAR_PARTIAL;
4081 tv->v_lock = 0;
4082 tv->vval.v_partial = NULL;
4083 break;
4084
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004085 // call a :def function
4086 case ISN_DCALL:
Bram Moolenaardfa3d552020-09-10 22:05:08 +02004087 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01004088 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
4089 NULL,
4090 iptr->isn_arg.dfunc.cdf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02004091 ectx) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02004092 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004093 break;
4094
4095 // call a builtin function
4096 case ISN_BCALL:
4097 SOURCING_LNUM = iptr->isn_lnum;
4098 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
4099 iptr->isn_arg.bfunc.cbf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02004100 ectx) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02004101 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004102 break;
4103
4104 // call a funcref or partial
4105 case ISN_PCALL:
4106 {
4107 cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
4108 int r;
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02004109 typval_T partial_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004110
4111 SOURCING_LNUM = iptr->isn_lnum;
4112 if (pfunc->cpf_top)
4113 {
4114 // funcref is above the arguments
4115 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
4116 }
4117 else
4118 {
4119 // Get the funcref from the stack.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004120 --ectx->ec_stack.ga_len;
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02004121 partial_tv = *STACK_TV_BOT(0);
4122 tv = &partial_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004123 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004124 r = call_partial(tv, pfunc->cpf_argcount, ectx);
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02004125 if (tv == &partial_tv)
4126 clear_tv(&partial_tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004127 if (r == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02004128 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004129 }
4130 break;
4131
Bram Moolenaarbd5da372020-03-31 23:13:10 +02004132 case ISN_PCALL_END:
4133 // PCALL finished, arguments have been consumed and replaced by
4134 // the return value. Now clear the funcref from the stack,
4135 // and move the return value in its place.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004136 --ectx->ec_stack.ga_len;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02004137 clear_tv(STACK_TV_BOT(-1));
4138 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
4139 break;
4140
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004141 // call a user defined function or funcref/partial
4142 case ISN_UCALL:
4143 {
4144 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
4145
4146 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01004147 if (call_eval_func(cufunc->cuf_name, cufunc->cuf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02004148 ectx, iptr) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02004149 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004150 }
4151 break;
4152
Bram Moolenaar1d84f762022-09-03 21:35:53 +01004153 // :defer func(arg)
4154 case ISN_DEFER:
Bram Moolenaar806a2732022-09-04 15:40:36 +01004155 if (defer_command(iptr->isn_arg.defer.defer_var_idx,
Bram Moolenaar1d84f762022-09-03 21:35:53 +01004156 iptr->isn_arg.defer.defer_argcount, ectx) == FAIL)
4157 goto on_error;
4158 break;
4159
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004160 // Return from a :def function call without a value.
4161 // Return from a constructor.
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02004162 case ISN_RETURN_VOID:
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004163 case ISN_RETURN_OBJECT:
Bram Moolenaar35578162021-08-02 19:10:38 +02004164 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004165 goto theend;
Bram Moolenaar299f3032021-01-08 20:53:09 +01004166 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004167 ++ectx->ec_stack.ga_len;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00004168 if (iptr->isn_type == ISN_RETURN_VOID)
4169 {
4170 tv->v_type = VAR_VOID;
4171 tv->vval.v_number = 0;
4172 tv->v_lock = 0;
4173 }
4174 else
4175 {
4176 *tv = *STACK_TV_VAR(0);
4177 ++tv->vval.v_object->obj_refcount;
4178 }
Bram Moolenaar299f3032021-01-08 20:53:09 +01004179 // FALLTHROUGH
4180
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02004181 // return from a :def function call with what is on the stack
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004182 case ISN_RETURN:
4183 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004184 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004185 trycmd_T *trycmd = NULL;
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01004186
4187 if (trystack->ga_len > 0)
4188 trycmd = ((trycmd_T *)trystack->ga_data)
4189 + trystack->ga_len - 1;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02004190 if (trycmd != NULL
Bram Moolenaar4c137212021-04-19 16:48:48 +02004191 && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004192 {
Bram Moolenaar9cb577a2021-02-22 22:45:10 +01004193 // jump to ":finally" or ":endtry"
4194 if (trycmd->tcd_finally_idx != 0)
Bram Moolenaar4c137212021-04-19 16:48:48 +02004195 ectx->ec_iidx = trycmd->tcd_finally_idx;
Bram Moolenaar9cb577a2021-02-22 22:45:10 +01004196 else
Bram Moolenaar4c137212021-04-19 16:48:48 +02004197 ectx->ec_iidx = trycmd->tcd_endtry_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004198 trycmd->tcd_return = TRUE;
4199 }
4200 else
Bram Moolenaard032f342020-07-18 18:13:02 +02004201 goto func_return;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004202 }
4203 break;
4204
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02004205 // push a partial, a reference to a compiled function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004206 case ISN_FUNCREF:
4207 {
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01004208 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
4209 ufunc_T *ufunc;
4210 funcref_T *funcref = &iptr->isn_arg.funcref;
4211 funcref_extra_T *extra = funcref->fr_extra;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004212
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004213 if (pt == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004214 goto theend;
Bram Moolenaar35578162021-08-02 19:10:38 +02004215 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004216 {
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02004217 vim_free(pt);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004218 goto theend;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02004219 }
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01004220 if (extra == NULL || extra->fre_func_name == NULL)
Bram Moolenaar38453522021-11-28 22:00:12 +00004221 {
4222 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data)
4223 + funcref->fr_dfunc_idx;
4224
4225 ufunc = pt_dfunc->df_ufunc;
4226 }
4227 else
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01004228 ufunc = find_func(extra->fre_func_name, FALSE);
Bram Moolenaar56acd1f2022-02-18 13:24:52 +00004229 if (ufunc == NULL)
4230 {
4231 SOURCING_LNUM = iptr->isn_lnum;
4232 iemsg("ufunc unexpectedly NULL for FUNCREF");
4233 goto theend;
4234 }
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01004235 if (fill_partial_and_closure(pt, ufunc,
Bram Moolenaarcc341812022-09-19 15:54:34 +01004236 extra == NULL ? NULL : &extra->fre_loopvar_info,
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01004237 ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004238 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004239 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004240 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004241 tv->vval.v_partial = pt;
4242 tv->v_type = VAR_PARTIAL;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02004243 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004244 }
4245 break;
4246
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004247 // Create a global function from a lambda.
4248 case ISN_NEWFUNC:
4249 {
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01004250 newfuncarg_T *arg = iptr->isn_arg.newfunc.nf_arg;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004251
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01004252 if (copy_lambda_to_global_func(arg->nfa_lambda,
Bram Moolenaarcc341812022-09-19 15:54:34 +01004253 arg->nfa_global, &arg->nfa_loopvar_info,
4254 ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004255 goto theend;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004256 }
4257 break;
4258
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01004259 // List functions
4260 case ISN_DEF:
4261 if (iptr->isn_arg.string == NULL)
4262 list_functions(NULL);
4263 else
4264 {
Bram Moolenaar14336722022-01-08 16:02:59 +00004265 exarg_T ea;
4266 garray_T lines_to_free;
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01004267
4268 CLEAR_FIELD(ea);
4269 ea.cmd = ea.arg = iptr->isn_arg.string;
Bram Moolenaar14336722022-01-08 16:02:59 +00004270 ga_init2(&lines_to_free, sizeof(char_u *), 50);
Bram Moolenaarffdaca92022-12-09 21:41:48 +00004271 define_function(&ea, NULL, &lines_to_free, FALSE);
Bram Moolenaar14336722022-01-08 16:02:59 +00004272 ga_clear_strings(&lines_to_free);
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01004273 }
4274 break;
4275
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004276 // jump if a condition is met
4277 case ISN_JUMP:
4278 {
4279 jumpwhen_T when = iptr->isn_arg.jump.jump_when;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004280 int error = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004281 int jump = TRUE;
4282
4283 if (when != JUMP_ALWAYS)
4284 {
4285 tv = STACK_TV_BOT(-1);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004286 if (when == JUMP_IF_COND_FALSE
Bram Moolenaar13106602020-10-04 16:06:05 +02004287 || when == JUMP_IF_FALSE
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004288 || when == JUMP_IF_COND_TRUE)
4289 {
4290 SOURCING_LNUM = iptr->isn_lnum;
4291 jump = tv_get_bool_chk(tv, &error);
4292 if (error)
4293 goto on_error;
4294 }
4295 else
4296 jump = tv2bool(tv);
Bram Moolenaarf6ced982022-04-28 12:00:49 +01004297 if (when == JUMP_IF_FALSE || when == JUMP_IF_COND_FALSE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004298 jump = !jump;
Bram Moolenaar777770f2020-02-06 21:27:08 +01004299 if (when == JUMP_IF_FALSE || !jump)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004300 {
4301 // drop the value from the stack
4302 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004303 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004304 }
4305 }
4306 if (jump)
Bram Moolenaar4c137212021-04-19 16:48:48 +02004307 ectx->ec_iidx = iptr->isn_arg.jump.jump_where;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004308 }
4309 break;
4310
Bram Moolenaarb46c0832022-09-15 17:19:37 +01004311 // "while": jump to end if a condition is false
4312 case ISN_WHILE:
4313 {
4314 int error = FALSE;
4315 int jump = TRUE;
4316
4317 tv = STACK_TV_BOT(-1);
4318 SOURCING_LNUM = iptr->isn_lnum;
4319 jump = !tv_get_bool_chk(tv, &error);
4320 if (error)
4321 goto on_error;
4322 // drop the value from the stack
4323 clear_tv(tv);
4324 --ectx->ec_stack.ga_len;
4325 if (jump)
4326 ectx->ec_iidx = iptr->isn_arg.whileloop.while_end;
4327
Bram Moolenaar87b4e5c2022-10-01 15:32:46 +01004328 // Store the current funcref count, may be used by
Bram Moolenaarcc341812022-09-19 15:54:34 +01004329 // ISN_ENDLOOP later
Bram Moolenaarb46c0832022-09-15 17:19:37 +01004330 tv = STACK_TV_VAR(
4331 iptr->isn_arg.whileloop.while_funcref_idx);
4332 tv->vval.v_number = ectx->ec_funcrefs.ga_len;
4333 }
4334 break;
4335
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02004336 // Jump if an argument with a default value was already set and not
4337 // v:none.
4338 case ISN_JUMP_IF_ARG_SET:
Bram Moolenaar65b0d162022-12-13 18:43:22 +00004339 case ISN_JUMP_IF_ARG_NOT_SET:
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02004340 tv = STACK_TV_VAR(iptr->isn_arg.jumparg.jump_arg_off);
Bram Moolenaar65b0d162022-12-13 18:43:22 +00004341 int arg_set = tv->v_type != VAR_UNKNOWN
4342 && !(tv->v_type == VAR_SPECIAL
4343 && tv->vval.v_number == VVAL_NONE);
4344 if (iptr->isn_type == ISN_JUMP_IF_ARG_SET ? arg_set : !arg_set)
Bram Moolenaar4c137212021-04-19 16:48:48 +02004345 ectx->ec_iidx = iptr->isn_arg.jumparg.jump_where;
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02004346 break;
4347
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004348 // top of a for loop
4349 case ISN_FOR:
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00004350 if (execute_for(iptr, ectx) == FAIL)
4351 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004352 break;
4353
Bram Moolenaarb46c0832022-09-15 17:19:37 +01004354 // end of a for or while loop
4355 case ISN_ENDLOOP:
4356 if (execute_endloop(iptr, ectx) == FAIL)
4357 goto theend;
4358 break;
4359
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004360 // start of ":try" block
4361 case ISN_TRY:
4362 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01004363 trycmd_T *trycmd = NULL;
4364
Bram Moolenaar35578162021-08-02 19:10:38 +02004365 if (GA_GROW_FAILS(&ectx->ec_trystack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004366 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004367 trycmd = ((trycmd_T *)ectx->ec_trystack.ga_data)
4368 + ectx->ec_trystack.ga_len;
4369 ++ectx->ec_trystack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004370 ++trylevel;
Bram Moolenaar8d4be892021-02-13 18:33:02 +01004371 CLEAR_POINTER(trycmd);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004372 trycmd->tcd_frame_idx = ectx->ec_frame_idx;
4373 trycmd->tcd_stack_len = ectx->ec_stack.ga_len;
Bram Moolenaara91a7132021-03-25 21:12:15 +01004374 trycmd->tcd_catch_idx =
Bram Moolenaar0d807102021-12-21 09:42:09 +00004375 iptr->isn_arg.tryref.try_ref->try_catch;
Bram Moolenaara91a7132021-03-25 21:12:15 +01004376 trycmd->tcd_finally_idx =
Bram Moolenaar0d807102021-12-21 09:42:09 +00004377 iptr->isn_arg.tryref.try_ref->try_finally;
Bram Moolenaara91a7132021-03-25 21:12:15 +01004378 trycmd->tcd_endtry_idx =
Bram Moolenaar0d807102021-12-21 09:42:09 +00004379 iptr->isn_arg.tryref.try_ref->try_endtry;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004380 }
4381 break;
4382
4383 case ISN_PUSHEXC:
4384 if (current_exception == NULL)
4385 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004386 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004387 iemsg("Evaluating catch while current_exception is NULL");
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004388 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004389 }
Bram Moolenaar35578162021-08-02 19:10:38 +02004390 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004391 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004392 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004393 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004394 tv->v_type = VAR_STRING;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02004395 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004396 tv->vval.v_string = vim_strsave(
4397 (char_u *)current_exception->value);
4398 break;
4399
4400 case ISN_CATCH:
4401 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004402 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar06651632022-04-27 17:54:25 +01004403 trycmd_T *trycmd;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004404
Bram Moolenaar4c137212021-04-19 16:48:48 +02004405 may_restore_cmdmod(&ectx->ec_funclocal);
Bram Moolenaar06651632022-04-27 17:54:25 +01004406 trycmd = ((trycmd_T *)trystack->ga_data)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004407 + trystack->ga_len - 1;
Bram Moolenaar06651632022-04-27 17:54:25 +01004408 trycmd->tcd_caught = TRUE;
4409 trycmd->tcd_did_throw = FALSE;
4410
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004411 did_emsg = got_int = did_throw = FALSE;
Bram Moolenaar1430cee2021-01-17 19:20:32 +01004412 force_abort = need_rethrow = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004413 catch_exception(current_exception);
4414 }
4415 break;
4416
Bram Moolenaarc150c092021-02-13 15:02:46 +01004417 case ISN_TRYCONT:
4418 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004419 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaarc150c092021-02-13 15:02:46 +01004420 trycont_T *trycont = &iptr->isn_arg.trycont;
4421 int i;
4422 trycmd_T *trycmd;
4423 int iidx = trycont->tct_where;
4424
4425 if (trystack->ga_len < trycont->tct_levels)
4426 {
4427 siemsg("TRYCONT: expected %d levels, found %d",
4428 trycont->tct_levels, trystack->ga_len);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004429 goto theend;
Bram Moolenaarc150c092021-02-13 15:02:46 +01004430 }
4431 // Make :endtry jump to any outer try block and the last
4432 // :endtry inside the loop to the loop start.
4433 for (i = trycont->tct_levels; i > 0; --i)
4434 {
4435 trycmd = ((trycmd_T *)trystack->ga_data)
4436 + trystack->ga_len - i;
Bram Moolenaar2e34c342021-03-14 12:13:33 +01004437 // Add one to tcd_cont to be able to jump to
4438 // instruction with index zero.
4439 trycmd->tcd_cont = iidx + 1;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01004440 iidx = trycmd->tcd_finally_idx == 0
4441 ? trycmd->tcd_endtry_idx : trycmd->tcd_finally_idx;
Bram Moolenaarc150c092021-02-13 15:02:46 +01004442 }
4443 // jump to :finally or :endtry of current try statement
Bram Moolenaar4c137212021-04-19 16:48:48 +02004444 ectx->ec_iidx = iidx;
Bram Moolenaarc150c092021-02-13 15:02:46 +01004445 }
4446 break;
4447
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01004448 case ISN_FINALLY:
4449 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004450 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01004451 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
4452 + trystack->ga_len - 1;
4453
4454 // Reset the index to avoid a return statement jumps here
4455 // again.
4456 trycmd->tcd_finally_idx = 0;
4457 break;
4458 }
4459
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004460 // end of ":try" block
4461 case ISN_ENDTRY:
4462 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004463 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar06651632022-04-27 17:54:25 +01004464 trycmd_T *trycmd;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004465
Bram Moolenaar06651632022-04-27 17:54:25 +01004466 --trystack->ga_len;
4467 --trylevel;
4468 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len;
4469 if (trycmd->tcd_did_throw)
4470 did_throw = TRUE;
4471 if (trycmd->tcd_caught && current_exception != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004472 {
Bram Moolenaar06651632022-04-27 17:54:25 +01004473 // discard the exception
4474 if (caught_stack == current_exception)
4475 caught_stack = caught_stack->caught;
4476 discard_current_exception();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004477 }
Bram Moolenaar06651632022-04-27 17:54:25 +01004478
4479 if (trycmd->tcd_return)
4480 goto func_return;
4481
4482 while (ectx->ec_stack.ga_len > trycmd->tcd_stack_len)
4483 {
4484 --ectx->ec_stack.ga_len;
4485 clear_tv(STACK_TV_BOT(0));
4486 }
4487 if (trycmd->tcd_cont != 0)
4488 // handling :continue: jump to outer try block or
4489 // start of the loop
4490 ectx->ec_iidx = trycmd->tcd_cont - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004491 }
4492 break;
4493
4494 case ISN_THROW:
Bram Moolenaar8f81b222021-01-14 21:47:06 +01004495 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004496 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar1e021e62020-10-16 20:25:23 +02004497
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01004498 if (trystack->ga_len == 0 && trylevel == 0 && emsg_silent)
4499 {
4500 // throwing an exception while using "silent!" causes
4501 // the function to abort but not display an error.
4502 tv = STACK_TV_BOT(-1);
4503 clear_tv(tv);
4504 tv->v_type = VAR_NUMBER;
4505 tv->vval.v_number = 0;
4506 goto done;
4507 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004508 --ectx->ec_stack.ga_len;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01004509 tv = STACK_TV_BOT(0);
4510 if (tv->vval.v_string == NULL
4511 || *skipwhite(tv->vval.v_string) == NUL)
4512 {
4513 vim_free(tv->vval.v_string);
4514 SOURCING_LNUM = iptr->isn_lnum;
4515 emsg(_(e_throw_with_empty_string));
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004516 goto theend;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01004517 }
4518
4519 // Inside a "catch" we need to first discard the caught
4520 // exception.
4521 if (trystack->ga_len > 0)
4522 {
4523 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
4524 + trystack->ga_len - 1;
4525 if (trycmd->tcd_caught && current_exception != NULL)
4526 {
4527 // discard the exception
4528 if (caught_stack == current_exception)
4529 caught_stack = caught_stack->caught;
4530 discard_current_exception();
4531 trycmd->tcd_caught = FALSE;
4532 }
4533 }
4534
Bram Moolenaar90a57162022-02-12 14:23:17 +00004535 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01004536 if (throw_exception(tv->vval.v_string, ET_USER, NULL)
4537 == FAIL)
4538 {
4539 vim_free(tv->vval.v_string);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004540 goto theend;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01004541 }
4542 did_throw = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004543 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004544 break;
4545
4546 // compare with special values
4547 case ISN_COMPAREBOOL:
4548 case ISN_COMPARESPECIAL:
4549 {
4550 typval_T *tv1 = STACK_TV_BOT(-2);
4551 typval_T *tv2 = STACK_TV_BOT(-1);
4552 varnumber_T arg1 = tv1->vval.v_number;
4553 varnumber_T arg2 = tv2->vval.v_number;
4554 int res;
4555
Bram Moolenaar06651632022-04-27 17:54:25 +01004556 if (iptr->isn_arg.op.op_type == EXPR_EQUAL)
4557 res = arg1 == arg2;
4558 else
4559 res = arg1 != arg2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004560
Bram Moolenaar4c137212021-04-19 16:48:48 +02004561 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004562 tv1->v_type = VAR_BOOL;
4563 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
4564 }
4565 break;
4566
Bram Moolenaar7a222242022-03-01 19:23:24 +00004567 case ISN_COMPARENULL:
4568 {
4569 typval_T *tv1 = STACK_TV_BOT(-2);
4570 typval_T *tv2 = STACK_TV_BOT(-1);
4571 int res;
4572
4573 res = typval_compare_null(tv1, tv2);
4574 if (res == MAYBE)
4575 goto on_error;
4576 if (iptr->isn_arg.op.op_type == EXPR_NEQUAL)
4577 res = !res;
4578 clear_tv(tv1);
4579 clear_tv(tv2);
4580 --ectx->ec_stack.ga_len;
4581 tv1->v_type = VAR_BOOL;
4582 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
4583 }
4584 break;
4585
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004586 // Operation with two number arguments
4587 case ISN_OPNR:
4588 case ISN_COMPARENR:
4589 {
4590 typval_T *tv1 = STACK_TV_BOT(-2);
4591 typval_T *tv2 = STACK_TV_BOT(-1);
4592 varnumber_T arg1 = tv1->vval.v_number;
4593 varnumber_T arg2 = tv2->vval.v_number;
Bram Moolenaarfbeefb12021-08-07 15:50:23 +02004594 varnumber_T res = 0;
4595 int div_zero = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004596
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004597 if (iptr->isn_arg.op.op_type == EXPR_LSHIFT
4598 || iptr->isn_arg.op.op_type == EXPR_RSHIFT)
4599 {
4600 if (arg2 < 0)
4601 {
4602 SOURCING_LNUM = iptr->isn_lnum;
dundargocc57b5bc2022-11-02 13:30:51 +00004603 emsg(_(e_bitshift_ops_must_be_positive));
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004604 goto on_error;
4605 }
4606 }
4607
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004608 switch (iptr->isn_arg.op.op_type)
4609 {
4610 case EXPR_MULT: res = arg1 * arg2; break;
Bram Moolenaarfbeefb12021-08-07 15:50:23 +02004611 case EXPR_DIV: if (arg2 == 0)
4612 div_zero = TRUE;
4613 else
4614 res = arg1 / arg2;
4615 break;
4616 case EXPR_REM: if (arg2 == 0)
4617 div_zero = TRUE;
4618 else
4619 res = arg1 % arg2;
4620 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004621 case EXPR_SUB: res = arg1 - arg2; break;
4622 case EXPR_ADD: res = arg1 + arg2; break;
4623
4624 case EXPR_EQUAL: res = arg1 == arg2; break;
4625 case EXPR_NEQUAL: res = arg1 != arg2; break;
4626 case EXPR_GREATER: res = arg1 > arg2; break;
4627 case EXPR_GEQUAL: res = arg1 >= arg2; break;
4628 case EXPR_SMALLER: res = arg1 < arg2; break;
4629 case EXPR_SEQUAL: res = arg1 <= arg2; break;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004630 case EXPR_LSHIFT: if (arg2 > MAX_LSHIFT_BITS)
4631 res = 0;
4632 else
Bram Moolenaar68e64d22022-05-22 22:07:52 +01004633 res = (uvarnumber_T)arg1 << arg2;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004634 break;
4635 case EXPR_RSHIFT: if (arg2 > MAX_LSHIFT_BITS)
4636 res = 0;
4637 else
Bram Moolenaar338bf582022-05-22 20:16:32 +01004638 res = (uvarnumber_T)arg1 >> arg2;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01004639 break;
Bram Moolenaarfbeefb12021-08-07 15:50:23 +02004640 default: break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004641 }
4642
Bram Moolenaar4c137212021-04-19 16:48:48 +02004643 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004644 if (iptr->isn_type == ISN_COMPARENR)
4645 {
4646 tv1->v_type = VAR_BOOL;
4647 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
4648 }
4649 else
4650 tv1->vval.v_number = res;
Bram Moolenaarfbeefb12021-08-07 15:50:23 +02004651 if (div_zero)
4652 {
4653 SOURCING_LNUM = iptr->isn_lnum;
4654 emsg(_(e_divide_by_zero));
4655 goto on_error;
4656 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004657 }
4658 break;
4659
4660 // Computation with two float arguments
4661 case ISN_OPFLOAT:
4662 case ISN_COMPAREFLOAT:
4663 {
4664 typval_T *tv1 = STACK_TV_BOT(-2);
4665 typval_T *tv2 = STACK_TV_BOT(-1);
4666 float_T arg1 = tv1->vval.v_float;
4667 float_T arg2 = tv2->vval.v_float;
4668 float_T res = 0;
4669 int cmp = FALSE;
4670
4671 switch (iptr->isn_arg.op.op_type)
4672 {
4673 case EXPR_MULT: res = arg1 * arg2; break;
4674 case EXPR_DIV: res = arg1 / arg2; break;
4675 case EXPR_SUB: res = arg1 - arg2; break;
4676 case EXPR_ADD: res = arg1 + arg2; break;
4677
4678 case EXPR_EQUAL: cmp = arg1 == arg2; break;
4679 case EXPR_NEQUAL: cmp = arg1 != arg2; break;
4680 case EXPR_GREATER: cmp = arg1 > arg2; break;
4681 case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
4682 case EXPR_SMALLER: cmp = arg1 < arg2; break;
4683 case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
4684 default: cmp = 0; break;
4685 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004686 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004687 if (iptr->isn_type == ISN_COMPAREFLOAT)
4688 {
4689 tv1->v_type = VAR_BOOL;
4690 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
4691 }
4692 else
4693 tv1->vval.v_float = res;
4694 }
4695 break;
4696
4697 case ISN_COMPARELIST:
Bram Moolenaar265f8112021-12-19 12:33:05 +00004698 case ISN_COMPAREDICT:
4699 case ISN_COMPAREFUNC:
4700 case ISN_COMPARESTRING:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004701 case ISN_COMPAREBLOB:
4702 {
4703 typval_T *tv1 = STACK_TV_BOT(-2);
4704 typval_T *tv2 = STACK_TV_BOT(-1);
Bram Moolenaar265f8112021-12-19 12:33:05 +00004705 exprtype_T exprtype = iptr->isn_arg.op.op_type;
4706 int ic = iptr->isn_arg.op.op_ic;
4707 int res = FALSE;
4708 int status = OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004709
Bram Moolenaar265f8112021-12-19 12:33:05 +00004710 SOURCING_LNUM = iptr->isn_lnum;
4711 if (iptr->isn_type == ISN_COMPARELIST)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004712 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00004713 status = typval_compare_list(tv1, tv2,
4714 exprtype, ic, &res);
4715 }
4716 else if (iptr->isn_type == ISN_COMPAREDICT)
4717 {
4718 status = typval_compare_dict(tv1, tv2,
4719 exprtype, ic, &res);
4720 }
4721 else if (iptr->isn_type == ISN_COMPAREFUNC)
4722 {
4723 status = typval_compare_func(tv1, tv2,
4724 exprtype, ic, &res);
4725 }
4726 else if (iptr->isn_type == ISN_COMPARESTRING)
4727 {
4728 status = typval_compare_string(tv1, tv2,
4729 exprtype, ic, &res);
4730 }
4731 else
4732 {
4733 status = typval_compare_blob(tv1, tv2, exprtype, &res);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004734 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004735 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004736 clear_tv(tv1);
4737 clear_tv(tv2);
4738 tv1->v_type = VAR_BOOL;
Bram Moolenaar265f8112021-12-19 12:33:05 +00004739 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
4740 if (status == FAIL)
4741 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004742 }
4743 break;
4744
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004745 case ISN_COMPAREANY:
4746 {
4747 typval_T *tv1 = STACK_TV_BOT(-2);
4748 typval_T *tv2 = STACK_TV_BOT(-1);
Bram Moolenaar657137c2021-01-09 15:45:23 +01004749 exprtype_T exprtype = iptr->isn_arg.op.op_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004750 int ic = iptr->isn_arg.op.op_ic;
Bram Moolenaar265f8112021-12-19 12:33:05 +00004751 int status;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004752
Bram Moolenaareb26f432020-09-14 16:50:05 +02004753 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar265f8112021-12-19 12:33:05 +00004754 status = typval_compare(tv1, tv2, exprtype, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004755 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004756 --ectx->ec_stack.ga_len;
Bram Moolenaar265f8112021-12-19 12:33:05 +00004757 if (status == FAIL)
4758 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004759 }
4760 break;
4761
4762 case ISN_ADDLIST:
4763 case ISN_ADDBLOB:
4764 {
4765 typval_T *tv1 = STACK_TV_BOT(-2);
4766 typval_T *tv2 = STACK_TV_BOT(-1);
4767
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004768 // add two lists or blobs
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004769 if (iptr->isn_type == ISN_ADDLIST)
Bram Moolenaar07802042021-09-09 23:01:14 +02004770 {
4771 if (iptr->isn_arg.op.op_type == EXPR_APPEND
4772 && tv1->vval.v_list != NULL)
4773 list_extend(tv1->vval.v_list, tv2->vval.v_list,
4774 NULL);
4775 else
4776 eval_addlist(tv1, tv2);
4777 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004778 else
4779 eval_addblob(tv1, tv2);
4780 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004781 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004782 }
4783 break;
4784
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004785 case ISN_LISTAPPEND:
4786 {
4787 typval_T *tv1 = STACK_TV_BOT(-2);
4788 typval_T *tv2 = STACK_TV_BOT(-1);
4789 list_T *l = tv1->vval.v_list;
4790
4791 // add an item to a list
Bram Moolenaar1f4a3452022-01-01 18:29:21 +00004792 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004793 if (l == NULL)
4794 {
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004795 emsg(_(e_cannot_add_to_null_list));
4796 goto on_error;
4797 }
Bram Moolenaar1f4a3452022-01-01 18:29:21 +00004798 if (value_check_lock(l->lv_lock, NULL, FALSE))
4799 goto on_error;
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004800 if (list_append_tv(l, tv2) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004801 goto theend;
Bram Moolenaar955347c2020-10-19 23:01:46 +02004802 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004803 --ectx->ec_stack.ga_len;
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004804 }
4805 break;
4806
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02004807 case ISN_BLOBAPPEND:
4808 {
4809 typval_T *tv1 = STACK_TV_BOT(-2);
4810 typval_T *tv2 = STACK_TV_BOT(-1);
4811 blob_T *b = tv1->vval.v_blob;
4812 int error = FALSE;
4813 varnumber_T n;
4814
4815 // add a number to a blob
4816 if (b == NULL)
4817 {
4818 SOURCING_LNUM = iptr->isn_lnum;
4819 emsg(_(e_cannot_add_to_null_blob));
4820 goto on_error;
4821 }
4822 n = tv_get_number_chk(tv2, &error);
4823 if (error)
4824 goto on_error;
4825 ga_append(&b->bv_ga, (int)n);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004826 --ectx->ec_stack.ga_len;
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02004827 }
4828 break;
4829
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004830 // Computation with two arguments of unknown type
4831 case ISN_OPANY:
4832 {
4833 typval_T *tv1 = STACK_TV_BOT(-2);
4834 typval_T *tv2 = STACK_TV_BOT(-1);
4835 varnumber_T n1, n2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004836 float_T f1 = 0, f2 = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004837 int error = FALSE;
4838
4839 if (iptr->isn_arg.op.op_type == EXPR_ADD)
4840 {
4841 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
4842 {
4843 eval_addlist(tv1, tv2);
4844 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004845 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004846 break;
4847 }
4848 else if (tv1->v_type == VAR_BLOB
4849 && tv2->v_type == VAR_BLOB)
4850 {
4851 eval_addblob(tv1, tv2);
4852 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004853 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004854 break;
4855 }
4856 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004857 if (tv1->v_type == VAR_FLOAT)
4858 {
4859 f1 = tv1->vval.v_float;
4860 n1 = 0;
4861 }
4862 else
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004863 {
Bram Moolenaarf665e972020-12-05 19:17:16 +01004864 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004865 n1 = tv_get_number_chk(tv1, &error);
4866 if (error)
Bram Moolenaard032f342020-07-18 18:13:02 +02004867 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004868 if (tv2->v_type == VAR_FLOAT)
4869 f1 = n1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004870 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004871 if (tv2->v_type == VAR_FLOAT)
4872 {
4873 f2 = tv2->vval.v_float;
4874 n2 = 0;
4875 }
4876 else
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004877 {
4878 n2 = tv_get_number_chk(tv2, &error);
4879 if (error)
Bram Moolenaard032f342020-07-18 18:13:02 +02004880 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004881 if (tv1->v_type == VAR_FLOAT)
4882 f2 = n2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004883 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004884 // if there is a float on either side the result is a float
4885 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
4886 {
4887 switch (iptr->isn_arg.op.op_type)
4888 {
4889 case EXPR_MULT: f1 = f1 * f2; break;
4890 case EXPR_DIV: f1 = f1 / f2; break;
4891 case EXPR_SUB: f1 = f1 - f2; break;
4892 case EXPR_ADD: f1 = f1 + f2; break;
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004893 default: SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00004894 emsg(_(e_cannot_use_percent_with_float));
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004895 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004896 }
4897 clear_tv(tv1);
4898 clear_tv(tv2);
4899 tv1->v_type = VAR_FLOAT;
4900 tv1->vval.v_float = f1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004901 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004902 }
4903 else
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004904 {
Bram Moolenaarb1f28572021-01-21 13:03:20 +01004905 int failed = FALSE;
4906
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004907 switch (iptr->isn_arg.op.op_type)
4908 {
4909 case EXPR_MULT: n1 = n1 * n2; break;
Bram Moolenaarb1f28572021-01-21 13:03:20 +01004910 case EXPR_DIV: n1 = num_divide(n1, n2, &failed);
4911 if (failed)
Bram Moolenaar99880f92021-01-20 21:23:14 +01004912 goto on_error;
4913 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004914 case EXPR_SUB: n1 = n1 - n2; break;
4915 case EXPR_ADD: n1 = n1 + n2; break;
Bram Moolenaarb1f28572021-01-21 13:03:20 +01004916 default: n1 = num_modulus(n1, n2, &failed);
4917 if (failed)
Bram Moolenaar99880f92021-01-20 21:23:14 +01004918 goto on_error;
4919 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004920 }
4921 clear_tv(tv1);
4922 clear_tv(tv2);
4923 tv1->v_type = VAR_NUMBER;
4924 tv1->vval.v_number = n1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004925 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004926 }
4927 }
4928 break;
4929
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004930 case ISN_STRINDEX:
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004931 case ISN_STRSLICE:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004932 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004933 int is_slice = iptr->isn_type == ISN_STRSLICE;
4934 varnumber_T n1 = 0, n2;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004935 char_u *res;
4936
4937 // string index: string is at stack-2, index at stack-1
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004938 // string slice: string is at stack-3, first index at
4939 // stack-2, second index at stack-1
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004940 if (is_slice)
4941 {
4942 tv = STACK_TV_BOT(-2);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004943 n1 = tv->vval.v_number;
4944 }
4945
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004946 tv = STACK_TV_BOT(-1);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004947 n2 = tv->vval.v_number;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004948
Bram Moolenaar4c137212021-04-19 16:48:48 +02004949 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004950 tv = STACK_TV_BOT(-1);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004951 if (is_slice)
4952 // Slice: Select the characters from the string
Bram Moolenaar6601b622021-01-13 21:47:15 +01004953 res = string_slice(tv->vval.v_string, n1, n2, FALSE);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004954 else
4955 // Index: The resulting variable is a string of a
Bram Moolenaar0289a092021-03-14 18:40:19 +01004956 // single character (including composing characters).
4957 // If the index is too big or negative the result is
4958 // empty.
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004959 res = char_from_string(tv->vval.v_string, n2);
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004960 vim_free(tv->vval.v_string);
4961 tv->vval.v_string = res;
4962 }
4963 break;
4964
4965 case ISN_LISTINDEX:
Bram Moolenaared591872020-08-15 22:14:53 +02004966 case ISN_LISTSLICE:
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004967 case ISN_BLOBINDEX:
4968 case ISN_BLOBSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004969 {
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004970 int is_slice = iptr->isn_type == ISN_LISTSLICE
4971 || iptr->isn_type == ISN_BLOBSLICE;
4972 int is_blob = iptr->isn_type == ISN_BLOBINDEX
4973 || iptr->isn_type == ISN_BLOBSLICE;
Bram Moolenaared591872020-08-15 22:14:53 +02004974 varnumber_T n1, n2;
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004975 typval_T *val_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004976
4977 // list index: list is at stack-2, index at stack-1
Bram Moolenaared591872020-08-15 22:14:53 +02004978 // list slice: list is at stack-3, indexes at stack-2 and
4979 // stack-1
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004980 // Same for blob.
4981 val_tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004982
4983 tv = STACK_TV_BOT(-1);
Bram Moolenaared591872020-08-15 22:14:53 +02004984 n1 = n2 = tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004985 clear_tv(tv);
Bram Moolenaared591872020-08-15 22:14:53 +02004986
4987 if (is_slice)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004988 {
Bram Moolenaared591872020-08-15 22:14:53 +02004989 tv = STACK_TV_BOT(-2);
Bram Moolenaared591872020-08-15 22:14:53 +02004990 n1 = tv->vval.v_number;
4991 clear_tv(tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004992 }
Bram Moolenaared591872020-08-15 22:14:53 +02004993
Bram Moolenaar4c137212021-04-19 16:48:48 +02004994 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaar435d8972020-07-05 16:42:13 +02004995 tv = STACK_TV_BOT(-1);
Bram Moolenaar1d634542020-08-18 13:41:50 +02004996 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004997 if (is_blob)
4998 {
4999 if (blob_slice_or_index(val_tv->vval.v_blob, is_slice,
5000 n1, n2, FALSE, tv) == FAIL)
5001 goto on_error;
5002 }
5003 else
5004 {
5005 if (list_slice_or_index(val_tv->vval.v_list, is_slice,
5006 n1, n2, FALSE, tv, TRUE) == FAIL)
5007 goto on_error;
5008 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005009 }
5010 break;
5011
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005012 case ISN_ANYINDEX:
5013 case ISN_ANYSLICE:
5014 {
5015 int is_slice = iptr->isn_type == ISN_ANYSLICE;
5016 typval_T *var1, *var2;
5017 int res;
5018
5019 // index: composite is at stack-2, index at stack-1
5020 // slice: composite is at stack-3, indexes at stack-2 and
5021 // stack-1
5022 tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
Bram Moolenaar3affe7a2020-08-18 20:34:13 +02005023 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005024 if (check_can_index(tv, TRUE, TRUE) == FAIL)
5025 goto on_error;
5026 var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1);
5027 var2 = is_slice ? STACK_TV_BOT(-1) : NULL;
Bram Moolenaar6601b622021-01-13 21:47:15 +01005028 res = eval_index_inner(tv, is_slice, var1, var2,
5029 FALSE, NULL, -1, TRUE);
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005030 clear_tv(var1);
5031 if (is_slice)
5032 clear_tv(var2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005033 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02005034 if (res == FAIL)
5035 goto on_error;
5036 }
5037 break;
5038
Bram Moolenaar9af78762020-06-16 11:34:42 +02005039 case ISN_SLICE:
5040 {
5041 list_T *list;
5042 int count = iptr->isn_arg.number;
5043
Bram Moolenaarc5b1c202020-06-18 22:43:27 +02005044 // type will have been checked to be a list
Bram Moolenaar9af78762020-06-16 11:34:42 +02005045 tv = STACK_TV_BOT(-1);
Bram Moolenaar9af78762020-06-16 11:34:42 +02005046 list = tv->vval.v_list;
5047
5048 // no error for short list, expect it to be checked earlier
5049 if (list != NULL && list->lv_len >= count)
5050 {
5051 list_T *newlist = list_slice(list,
5052 count, list->lv_len - 1);
5053
5054 if (newlist != NULL)
5055 {
5056 list_unref(list);
5057 tv->vval.v_list = newlist;
5058 ++newlist->lv_refcount;
5059 }
5060 }
5061 }
5062 break;
5063
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005064 case ISN_GETITEM:
5065 {
5066 listitem_T *li;
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02005067 getitem_T *gi = &iptr->isn_arg.getitem;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005068
Bram Moolenaarc785b9a2020-06-19 18:34:15 +02005069 // Get list item: list is at stack-1, push item.
5070 // List type and length is checked for when compiling.
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02005071 tv = STACK_TV_BOT(-1 - gi->gi_with_op);
5072 li = list_find(tv->vval.v_list, gi->gi_index);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005073
Bram Moolenaar35578162021-08-02 19:10:38 +02005074 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02005075 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005076 ++ectx->ec_stack.ga_len;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005077 copy_tv(&li->li_tv, STACK_TV_BOT(-1));
Bram Moolenaarf785aa12021-02-11 21:19:34 +01005078
5079 // Useful when used in unpack assignment. Reset at
5080 // ISN_DROP.
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02005081 ectx->ec_where.wt_index = gi->gi_index + 1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005082 ectx->ec_where.wt_variable = TRUE;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005083 }
5084 break;
5085
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005086 case ISN_MEMBER:
5087 {
5088 dict_T *dict;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005089 char_u *key;
5090 dictitem_T *di;
5091
5092 // dict member: dict is at stack-2, key at stack-1
5093 tv = STACK_TV_BOT(-2);
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02005094 // no need to check for VAR_DICT, CHECKTYPE will check.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005095 dict = tv->vval.v_dict;
5096
5097 tv = STACK_TV_BOT(-1);
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02005098 // no need to check for VAR_STRING, 2STRING will check.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005099 key = tv->vval.v_string;
Bram Moolenaar086fc9a2020-10-30 18:33:02 +01005100 if (key == NULL)
5101 key = (char_u *)"";
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02005102
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005103 if ((di = dict_find(dict, key, -1)) == NULL)
5104 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02005105 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00005106 semsg(_(e_key_not_present_in_dictionary), key);
Bram Moolenaar4029cab2020-12-05 18:13:27 +01005107
5108 // If :silent! is used we will continue, make sure the
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005109 // stack contents makes sense and the dict stack is
5110 // updated.
Bram Moolenaar4029cab2020-12-05 18:13:27 +01005111 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005112 --ectx->ec_stack.ga_len;
Bram Moolenaar4029cab2020-12-05 18:13:27 +01005113 tv = STACK_TV_BOT(-1);
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005114 (void) dict_stack_save(tv);
Bram Moolenaar4029cab2020-12-05 18:13:27 +01005115 tv->v_type = VAR_NUMBER;
5116 tv->vval.v_number = 0;
Bram Moolenaaraf0df472020-12-02 20:51:22 +01005117 goto on_fatal_error;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005118 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005119 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005120 --ectx->ec_stack.ga_len;
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005121 // Put the dict used on the dict stack, it might be used by
5122 // a dict function later.
Bram Moolenaar50788ef2020-07-05 16:51:26 +02005123 tv = STACK_TV_BOT(-1);
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005124 if (dict_stack_save(tv) == FAIL)
5125 goto on_fatal_error;
Bram Moolenaar50788ef2020-07-05 16:51:26 +02005126 copy_tv(&di->di_tv, tv);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005127 }
5128 break;
5129
5130 // dict member with string key
5131 case ISN_STRINGMEMBER:
5132 {
5133 dict_T *dict;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005134 dictitem_T *di;
5135
5136 tv = STACK_TV_BOT(-1);
5137 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
5138 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02005139 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00005140 emsg(_(e_dictionary_required));
Bram Moolenaard032f342020-07-18 18:13:02 +02005141 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005142 }
5143 dict = tv->vval.v_dict;
5144
5145 if ((di = dict_find(dict, iptr->isn_arg.string, -1))
5146 == NULL)
5147 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02005148 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar381692b2022-02-02 20:01:27 +00005149 semsg(_(e_key_not_present_in_dictionary),
5150 iptr->isn_arg.string);
Bram Moolenaard032f342020-07-18 18:13:02 +02005151 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005152 }
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005153 // Put the dict used on the dict stack, it might be used by
5154 // a dict function later.
5155 if (dict_stack_save(tv) == FAIL)
5156 goto on_fatal_error;
5157
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005158 copy_tv(&di->di_tv, tv);
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005159 }
5160 break;
5161
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +00005162 case ISN_GET_OBJ_MEMBER:
Bram Moolenaarffdaca92022-12-09 21:41:48 +00005163 {
5164 tv = STACK_TV_BOT(-1);
5165 if (tv->v_type != VAR_OBJECT)
5166 {
5167 SOURCING_LNUM = iptr->isn_lnum;
5168 garray_T type_list;
5169 ga_init2(&type_list, sizeof(type_T *), 10);
5170 type_T *type = typval2type(tv, get_copyID(),
5171 &type_list, TVTT_DO_MEMBER);
5172 char *tofree = NULL;
5173 char *typename = type_name(type, &tofree);
5174 semsg(_(e_object_required_found_str), typename);
5175 vim_free(tofree);
5176 clear_type_list(&type_list);
5177 goto on_error;
5178 }
5179 int idx = iptr->isn_arg.number;
5180 object_T *obj = tv->vval.v_object;
5181 // the members are located right after the object struct
5182 typval_T *mtv = ((typval_T *)(obj + 1)) + idx;
Bram Moolenaar590162c2022-12-24 21:24:06 +00005183 copy_tv(mtv, tv);
Bram Moolenaarffdaca92022-12-09 21:41:48 +00005184
5185 // Unreference the object after getting the member, it may
5186 // be freed.
5187 object_unref(obj);
5188 }
5189 break;
5190
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +00005191 case ISN_STORE_THIS:
5192 {
5193 int idx = iptr->isn_arg.number;
5194 object_T *obj = STACK_TV_VAR(0)->vval.v_object;
5195 // the members are located right after the object struct
5196 typval_T *mtv = ((typval_T *)(obj + 1)) + idx;
5197 clear_tv(mtv);
5198 *mtv = *STACK_TV_BOT(-1);
5199 --ectx->ec_stack.ga_len;
5200 }
5201 break;
5202
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005203 case ISN_CLEARDICT:
5204 dict_stack_drop();
5205 break;
5206
5207 case ISN_USEDICT:
5208 {
5209 typval_T *dict_tv = dict_stack_get_tv();
5210
5211 // Turn "dict.Func" into a partial for "Func" bound to
5212 // "dict". Don't do this when "Func" is already a partial
5213 // that was bound explicitly (pt_auto is FALSE).
5214 tv = STACK_TV_BOT(-1);
5215 if (dict_tv != NULL
5216 && dict_tv->v_type == VAR_DICT
5217 && dict_tv->vval.v_dict != NULL
5218 && (tv->v_type == VAR_FUNC
5219 || (tv->v_type == VAR_PARTIAL
5220 && (tv->vval.v_partial->pt_auto
5221 || tv->vval.v_partial->pt_dict == NULL))))
5222 dict_tv->vval.v_dict =
5223 make_partial(dict_tv->vval.v_dict, tv);
5224 dict_stack_drop();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005225 }
5226 break;
5227
5228 case ISN_NEGATENR:
5229 tv = STACK_TV_BOT(-1);
Bram Moolenaar0c7f2612022-02-17 19:44:07 +00005230 // CHECKTYPE should have checked the variable type
Bram Moolenaarc58164c2020-03-29 18:40:30 +02005231 if (tv->v_type == VAR_FLOAT)
5232 tv->vval.v_float = -tv->vval.v_float;
5233 else
Bram Moolenaarc58164c2020-03-29 18:40:30 +02005234 tv->vval.v_number = -tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005235 break;
5236
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005237 case ISN_CHECKTYPE:
5238 {
5239 checktype_T *ct = &iptr->isn_arg.type;
Bram Moolenaarbd3a9d22022-05-17 16:12:39 +01005240 int save_wt_variable = ectx->ec_where.wt_variable;
Bram Moolenaarb1040dc2022-05-18 11:00:48 +01005241 int r;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005242
Bram Moolenaarb3005ce2021-01-22 17:51:06 +01005243 tv = STACK_TV_BOT((int)ct->ct_off);
Bram Moolenaar5e654232020-09-16 15:22:00 +02005244 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005245 if (!ectx->ec_where.wt_variable)
5246 ectx->ec_where.wt_index = ct->ct_arg_idx;
Bram Moolenaarbd3a9d22022-05-17 16:12:39 +01005247 ectx->ec_where.wt_variable = ct->ct_is_var;
Bram Moolenaarb1040dc2022-05-18 11:00:48 +01005248 r = check_typval_type(ct->ct_type, tv, ectx->ec_where);
Bram Moolenaarbd3a9d22022-05-17 16:12:39 +01005249 ectx->ec_where.wt_variable = save_wt_variable;
Bram Moolenaarb1040dc2022-05-18 11:00:48 +01005250 if (r == FAIL)
5251 goto on_error;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005252 if (!ectx->ec_where.wt_variable)
5253 ectx->ec_where.wt_index = 0;
Bram Moolenaar5e654232020-09-16 15:22:00 +02005254
5255 // number 0 is FALSE, number 1 is TRUE
5256 if (tv->v_type == VAR_NUMBER
5257 && ct->ct_type->tt_type == VAR_BOOL
5258 && (tv->vval.v_number == 0
5259 || tv->vval.v_number == 1))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005260 {
Bram Moolenaar5e654232020-09-16 15:22:00 +02005261 tv->v_type = VAR_BOOL;
5262 tv->vval.v_number = tv->vval.v_number
Bram Moolenaardadaddd2020-09-12 19:11:23 +02005263 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005264 }
5265 }
5266 break;
5267
Bram Moolenaar9af78762020-06-16 11:34:42 +02005268 case ISN_CHECKLEN:
5269 {
5270 int min_len = iptr->isn_arg.checklen.cl_min_len;
5271 list_T *list = NULL;
5272
5273 tv = STACK_TV_BOT(-1);
5274 if (tv->v_type == VAR_LIST)
5275 list = tv->vval.v_list;
5276 if (list == NULL || list->lv_len < min_len
5277 || (list->lv_len > min_len
5278 && !iptr->isn_arg.checklen.cl_more_OK))
5279 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02005280 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005281 semsg(_(e_expected_nr_items_but_got_nr),
Bram Moolenaar9af78762020-06-16 11:34:42 +02005282 min_len, list == NULL ? 0 : list->lv_len);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02005283 goto on_error;
Bram Moolenaar9af78762020-06-16 11:34:42 +02005284 }
5285 }
5286 break;
5287
Bram Moolenaaraa210a32021-01-02 15:41:03 +01005288 case ISN_SETTYPE:
Bram Moolenaar381692b2022-02-02 20:01:27 +00005289 set_tv_type(STACK_TV_BOT(-1), iptr->isn_arg.type.ct_type);
Bram Moolenaaraa210a32021-01-02 15:41:03 +01005290 break;
5291
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005292 case ISN_2BOOL:
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005293 case ISN_COND2BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005294 {
5295 int n;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005296 int error = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005297
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005298 if (iptr->isn_type == ISN_2BOOL)
5299 {
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005300 tv = STACK_TV_BOT(iptr->isn_arg.tobool.offset);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005301 n = tv2bool(tv);
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005302 if (iptr->isn_arg.tobool.invert)
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005303 n = !n;
5304 }
5305 else
5306 {
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005307 tv = STACK_TV_BOT(-1);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005308 SOURCING_LNUM = iptr->isn_lnum;
5309 n = tv_get_bool_chk(tv, &error);
5310 if (error)
5311 goto on_error;
5312 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005313 clear_tv(tv);
5314 tv->v_type = VAR_BOOL;
5315 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
5316 }
5317 break;
5318
5319 case ISN_2STRING:
Bram Moolenaar418f1df2020-08-12 21:34:49 +02005320 case ISN_2STRING_ANY:
Bram Moolenaar0acbf5a2021-01-05 20:58:25 +01005321 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02005322 if (do_2string(STACK_TV_BOT(iptr->isn_arg.tostring.offset),
5323 iptr->isn_type == ISN_2STRING_ANY,
5324 iptr->isn_arg.tostring.tolerant) == FAIL)
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01005325 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005326 break;
5327
Bram Moolenaar08597872020-12-10 19:43:40 +01005328 case ISN_RANGE:
5329 {
5330 exarg_T ea;
5331 char *errormsg;
5332
Bram Moolenaarece0b872021-01-08 20:40:45 +01005333 ea.line2 = 0;
Bram Moolenaard1510ee2021-01-04 16:15:58 +01005334 ea.addr_count = 0;
Bram Moolenaar08597872020-12-10 19:43:40 +01005335 ea.addr_type = ADDR_LINES;
5336 ea.cmd = iptr->isn_arg.string;
Bram Moolenaarece0b872021-01-08 20:40:45 +01005337 ea.skip = FALSE;
Bram Moolenaar08597872020-12-10 19:43:40 +01005338 if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
Bram Moolenaarece0b872021-01-08 20:40:45 +01005339 goto on_error;
Bram Moolenaara28639e2021-01-19 22:48:09 +01005340
Bram Moolenaar35578162021-08-02 19:10:38 +02005341 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02005342 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005343 ++ectx->ec_stack.ga_len;
Bram Moolenaara28639e2021-01-19 22:48:09 +01005344 tv = STACK_TV_BOT(-1);
5345 tv->v_type = VAR_NUMBER;
5346 tv->v_lock = 0;
Bram Moolenaar06651632022-04-27 17:54:25 +01005347 tv->vval.v_number = ea.line2;
Bram Moolenaar08597872020-12-10 19:43:40 +01005348 }
5349 break;
5350
Bram Moolenaarc3516f72020-09-08 22:45:35 +02005351 case ISN_PUT:
5352 {
5353 int regname = iptr->isn_arg.put.put_regname;
5354 linenr_T lnum = iptr->isn_arg.put.put_lnum;
5355 char_u *expr = NULL;
5356 int dir = FORWARD;
5357
Bram Moolenaar08597872020-12-10 19:43:40 +01005358 if (lnum < -2)
5359 {
5360 // line number was put on the stack by ISN_RANGE
5361 tv = STACK_TV_BOT(-1);
5362 curwin->w_cursor.lnum = tv->vval.v_number;
5363 if (lnum == LNUM_VARIABLE_RANGE_ABOVE)
5364 dir = BACKWARD;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005365 --ectx->ec_stack.ga_len;
Bram Moolenaar08597872020-12-10 19:43:40 +01005366 }
5367 else if (lnum == -2)
Bram Moolenaarc3516f72020-09-08 22:45:35 +02005368 // :put! above cursor
5369 dir = BACKWARD;
5370 else if (lnum >= 0)
Bram Moolenaar4e713ba2022-02-07 15:31:37 +00005371 {
5372 curwin->w_cursor.lnum = lnum;
5373 if (lnum == 0)
5374 // check_cursor() below will move to line 1
5375 dir = BACKWARD;
5376 }
Bram Moolenaara28639e2021-01-19 22:48:09 +01005377
5378 if (regname == '=')
5379 {
5380 tv = STACK_TV_BOT(-1);
5381 if (tv->v_type == VAR_STRING)
5382 expr = tv->vval.v_string;
5383 else
5384 {
5385 expr = typval2string(tv, TRUE); // allocates value
5386 clear_tv(tv);
5387 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005388 --ectx->ec_stack.ga_len;
Bram Moolenaara28639e2021-01-19 22:48:09 +01005389 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02005390 check_cursor();
5391 do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
5392 vim_free(expr);
5393 }
5394 break;
5395
Bram Moolenaar02194d22020-10-24 23:08:38 +02005396 case ISN_CMDMOD:
Bram Moolenaar4c137212021-04-19 16:48:48 +02005397 ectx->ec_funclocal.floc_save_cmdmod = cmdmod;
5398 ectx->ec_funclocal.floc_restore_cmdmod = TRUE;
5399 ectx->ec_funclocal.floc_restore_cmdmod_stacklen =
5400 ectx->ec_stack.ga_len;
Bram Moolenaar02194d22020-10-24 23:08:38 +02005401 cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod;
5402 apply_cmdmod(&cmdmod);
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02005403 break;
5404
Bram Moolenaar02194d22020-10-24 23:08:38 +02005405 case ISN_CMDMOD_REV:
5406 // filter regprog is owned by the instruction, don't free it
5407 cmdmod.cmod_filter_regmatch.regprog = NULL;
5408 undo_cmdmod(&cmdmod);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005409 cmdmod = ectx->ec_funclocal.floc_save_cmdmod;
5410 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02005411 break;
5412
Bram Moolenaar792f7862020-11-23 08:31:18 +01005413 case ISN_UNPACK:
5414 {
5415 int count = iptr->isn_arg.unpack.unp_count;
5416 int semicolon = iptr->isn_arg.unpack.unp_semicolon;
5417 list_T *l;
5418 listitem_T *li;
5419 int i;
5420
5421 // Check there is a valid list to unpack.
5422 tv = STACK_TV_BOT(-1);
5423 if (tv->v_type != VAR_LIST)
5424 {
5425 SOURCING_LNUM = iptr->isn_lnum;
5426 emsg(_(e_for_argument_must_be_sequence_of_lists));
5427 goto on_error;
5428 }
5429 l = tv->vval.v_list;
5430 if (l == NULL
5431 || l->lv_len < (semicolon ? count - 1 : count))
5432 {
5433 SOURCING_LNUM = iptr->isn_lnum;
5434 emsg(_(e_list_value_does_not_have_enough_items));
5435 goto on_error;
5436 }
5437 else if (!semicolon && l->lv_len > count)
5438 {
5439 SOURCING_LNUM = iptr->isn_lnum;
5440 emsg(_(e_list_value_has_more_items_than_targets));
5441 goto on_error;
5442 }
5443
5444 CHECK_LIST_MATERIALIZE(l);
Bram Moolenaar35578162021-08-02 19:10:38 +02005445 if (GA_GROW_FAILS(&ectx->ec_stack, count - 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02005446 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005447 ectx->ec_stack.ga_len += count - 1;
Bram Moolenaar792f7862020-11-23 08:31:18 +01005448
5449 // Variable after semicolon gets a list with the remaining
5450 // items.
5451 if (semicolon)
5452 {
5453 list_T *rem_list =
5454 list_alloc_with_items(l->lv_len - count + 1);
5455
5456 if (rem_list == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02005457 goto theend;
Bram Moolenaar792f7862020-11-23 08:31:18 +01005458 tv = STACK_TV_BOT(-count);
5459 tv->vval.v_list = rem_list;
5460 ++rem_list->lv_refcount;
5461 tv->v_lock = 0;
5462 li = l->lv_first;
5463 for (i = 0; i < count - 1; ++i)
5464 li = li->li_next;
5465 for (i = 0; li != NULL; ++i)
5466 {
Bram Moolenaar61efa162022-03-18 13:10:48 +00005467 typval_T tvcopy;
5468
5469 copy_tv(&li->li_tv, &tvcopy);
5470 list_set_item(rem_list, i, &tvcopy);
Bram Moolenaar792f7862020-11-23 08:31:18 +01005471 li = li->li_next;
5472 }
5473 --count;
5474 }
5475
5476 // Produce the values in reverse order, first item last.
5477 li = l->lv_first;
5478 for (i = 0; i < count; ++i)
5479 {
5480 tv = STACK_TV_BOT(-i - 1);
5481 copy_tv(&li->li_tv, tv);
5482 li = li->li_next;
5483 }
5484
5485 list_unref(l);
5486 }
5487 break;
5488
Bram Moolenaarb2049902021-01-24 12:53:53 +01005489 case ISN_PROF_START:
5490 case ISN_PROF_END:
5491 {
Bram Moolenaarf002a412021-01-24 13:34:18 +01005492#ifdef FEAT_PROFILE
Bram Moolenaarca16c602022-09-06 18:57:08 +01005493 funccall_T cookie;
5494 ufunc_T *cur_ufunc =
Bram Moolenaarb2049902021-01-24 12:53:53 +01005495 (((dfunc_T *)def_functions.ga_data)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02005496 + ectx->ec_dfunc_idx)->df_ufunc;
Bram Moolenaarb2049902021-01-24 12:53:53 +01005497
Bram Moolenaarca16c602022-09-06 18:57:08 +01005498 cookie.fc_func = cur_ufunc;
Bram Moolenaarb2049902021-01-24 12:53:53 +01005499 if (iptr->isn_type == ISN_PROF_START)
5500 {
5501 func_line_start(&cookie, iptr->isn_lnum);
5502 // if we get here the instruction is executed
5503 func_line_exec(&cookie);
5504 }
5505 else
5506 func_line_end(&cookie);
Bram Moolenaarf002a412021-01-24 13:34:18 +01005507#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01005508 }
5509 break;
5510
Bram Moolenaare99d4222021-06-13 14:01:26 +02005511 case ISN_DEBUG:
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02005512 handle_debug(iptr, ectx);
Bram Moolenaare99d4222021-06-13 14:01:26 +02005513 break;
5514
Bram Moolenaar389df252020-07-09 21:20:47 +02005515 case ISN_SHUFFLE:
5516 {
Bram Moolenaar792f7862020-11-23 08:31:18 +01005517 typval_T tmp_tv;
5518 int item = iptr->isn_arg.shuffle.shfl_item;
5519 int up = iptr->isn_arg.shuffle.shfl_up;
Bram Moolenaar389df252020-07-09 21:20:47 +02005520
5521 tmp_tv = *STACK_TV_BOT(-item);
5522 for ( ; up > 0 && item > 1; --up)
5523 {
5524 *STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1);
5525 --item;
5526 }
5527 *STACK_TV_BOT(-item) = tmp_tv;
5528 }
5529 break;
5530
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005531 case ISN_DROP:
Bram Moolenaar4c137212021-04-19 16:48:48 +02005532 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005533 clear_tv(STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005534 ectx->ec_where.wt_index = 0;
5535 ectx->ec_where.wt_variable = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005536 break;
5537 }
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02005538 continue;
5539
Bram Moolenaard032f342020-07-18 18:13:02 +02005540func_return:
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02005541 // Restore previous function. If the frame pointer is where we started
5542 // then there is none and we are done.
Bram Moolenaar4c137212021-04-19 16:48:48 +02005543 if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
Bram Moolenaard032f342020-07-18 18:13:02 +02005544 goto done;
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02005545
Bram Moolenaar4c137212021-04-19 16:48:48 +02005546 if (func_return(ectx) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02005547 // only fails when out of memory
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02005548 goto theend;
Bram Moolenaarc7db5772020-07-21 20:55:50 +02005549 continue;
Bram Moolenaard032f342020-07-18 18:13:02 +02005550
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02005551on_error:
Bram Moolenaaraf0df472020-12-02 20:51:22 +01005552 // Jump here for an error that does not require aborting execution.
Bram Moolenaar56602ba2020-12-05 21:22:08 +01005553 // If "emsg_silent" is set then ignore the error, unless it was set
5554 // when calling the function.
Bram Moolenaar4c137212021-04-19 16:48:48 +02005555 if (did_emsg_cumul + did_emsg == ectx->ec_did_emsg_before
Bram Moolenaar56602ba2020-12-05 21:22:08 +01005556 && emsg_silent && did_emsg_def == 0)
Bram Moolenaarf9041332021-01-21 19:41:16 +01005557 {
5558 // If a sequence of instructions causes an error while ":silent!"
5559 // was used, restore the stack length and jump ahead to restoring
5560 // the cmdmod.
Bram Moolenaar4c137212021-04-19 16:48:48 +02005561 if (ectx->ec_funclocal.floc_restore_cmdmod)
Bram Moolenaarf9041332021-01-21 19:41:16 +01005562 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02005563 while (ectx->ec_stack.ga_len
5564 > ectx->ec_funclocal.floc_restore_cmdmod_stacklen)
Bram Moolenaarf9041332021-01-21 19:41:16 +01005565 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02005566 --ectx->ec_stack.ga_len;
Bram Moolenaarf9041332021-01-21 19:41:16 +01005567 clear_tv(STACK_TV_BOT(0));
5568 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005569 while (ectx->ec_instr[ectx->ec_iidx].isn_type != ISN_CMDMOD_REV)
5570 ++ectx->ec_iidx;
Bram Moolenaarf9041332021-01-21 19:41:16 +01005571 }
Bram Moolenaarcd030c42020-10-30 21:49:40 +01005572 continue;
Bram Moolenaarf9041332021-01-21 19:41:16 +01005573 }
Bram Moolenaaraf0df472020-12-02 20:51:22 +01005574on_fatal_error:
5575 // Jump here for an error that messes up the stack.
Bram Moolenaar171fb922020-10-28 16:54:47 +01005576 // If we are not inside a try-catch started here, abort execution.
Bram Moolenaar4c137212021-04-19 16:48:48 +02005577 if (trylevel <= ectx->ec_trylevel_at_start)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02005578 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005579 }
5580
5581done:
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02005582 ret = OK;
5583theend:
Bram Moolenaar58779852022-09-06 18:31:14 +01005584 may_invoke_defer_funcs(ectx);
Bram Moolenaar1d84f762022-09-03 21:35:53 +01005585
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005586 dict_stack_clear(dict_stack_len_at_start);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02005587 ectx->ec_trylevel_at_start = save_trylevel_at_start;
5588 return ret;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005589}
5590
5591/*
Bram Moolenaar806a2732022-09-04 15:40:36 +01005592 * Execute the instructions from a VAR_INSTR typval and put the result in
Bram Moolenaarf18332f2021-05-07 17:55:55 +02005593 * "rettv".
5594 * Return OK or FAIL.
5595 */
5596 int
5597exe_typval_instr(typval_T *tv, typval_T *rettv)
5598{
5599 ectx_T *ectx = tv->vval.v_instr->instr_ectx;
5600 isn_T *save_instr = ectx->ec_instr;
5601 int save_iidx = ectx->ec_iidx;
5602 int res;
5603
LemonBoyf3b48952022-05-05 13:53:03 +01005604 // Initialize rettv so that it is safe for caller to invoke clear_tv(rettv)
5605 // even when the compilation fails.
5606 rettv->v_type = VAR_UNKNOWN;
5607
Bram Moolenaarf18332f2021-05-07 17:55:55 +02005608 ectx->ec_instr = tv->vval.v_instr->instr_instr;
5609 res = exec_instructions(ectx);
5610 if (res == OK)
5611 {
5612 *rettv = *STACK_TV_BOT(-1);
5613 --ectx->ec_stack.ga_len;
5614 }
5615
5616 ectx->ec_instr = save_instr;
5617 ectx->ec_iidx = save_iidx;
5618
5619 return res;
5620}
5621
5622/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02005623 * Execute the instructions from an ISN_SUBSTITUTE command, which are in
5624 * "substitute_instr".
5625 */
5626 char_u *
5627exe_substitute_instr(void)
5628{
5629 ectx_T *ectx = substitute_instr->subs_ectx;
5630 isn_T *save_instr = ectx->ec_instr;
5631 int save_iidx = ectx->ec_iidx;
5632 char_u *res;
5633
5634 ectx->ec_instr = substitute_instr->subs_instr;
5635 if (exec_instructions(ectx) == OK)
Bram Moolenaar90193e62021-04-04 20:49:50 +02005636 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02005637 typval_T *tv = STACK_TV_BOT(-1);
5638
Bram Moolenaar27523602021-06-05 21:36:19 +02005639 res = typval2string(tv, TRUE);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005640 --ectx->ec_stack.ga_len;
5641 clear_tv(tv);
Bram Moolenaar90193e62021-04-04 20:49:50 +02005642 }
5643 else
5644 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02005645 substitute_instr->subs_status = FAIL;
5646 res = vim_strsave((char_u *)"");
Bram Moolenaar90193e62021-04-04 20:49:50 +02005647 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005648
Bram Moolenaar4c137212021-04-19 16:48:48 +02005649 ectx->ec_instr = save_instr;
5650 ectx->ec_iidx = save_iidx;
5651
5652 return res;
5653}
5654
5655/*
5656 * Call a "def" function from old Vim script.
5657 * Return OK or FAIL.
5658 */
5659 int
5660call_def_function(
5661 ufunc_T *ufunc,
5662 int argc_arg, // nr of arguments
5663 typval_T *argv, // arguments
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005664 int flags, // DEF_ flags
Bram Moolenaar4c137212021-04-19 16:48:48 +02005665 partial_T *partial, // optional partial for context
Bram Moolenaarffdaca92022-12-09 21:41:48 +00005666 object_T *object, // object, e.g. for this.Func()
Bram Moolenaar58779852022-09-06 18:31:14 +01005667 funccall_T *funccal,
Bram Moolenaar4c137212021-04-19 16:48:48 +02005668 typval_T *rettv) // return value
5669{
5670 ectx_T ectx; // execution context
5671 int argc = argc_arg;
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005672 int partial_argc = partial == NULL
5673 || (flags & DEF_USE_PT_ARGV) == 0
5674 ? 0 : partial->pt_argc;
5675 int total_argc = argc + partial_argc;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005676 typval_T *tv;
5677 int idx;
5678 int ret = FAIL;
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005679 int defcount = ufunc->uf_args.ga_len - total_argc;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005680 sctx_T save_current_sctx = current_sctx;
5681 int did_emsg_before = did_emsg_cumul + did_emsg;
5682 int save_suppress_errthrow = suppress_errthrow;
5683 msglist_T **saved_msg_list = NULL;
5684 msglist_T *private_msg_list = NULL;
5685 int save_emsg_silent_def = emsg_silent_def;
5686 int save_did_emsg_def = did_emsg_def;
5687 int orig_funcdepth;
Bram Moolenaare99d4222021-06-13 14:01:26 +02005688 int orig_nesting_level = ex_nesting_level;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005689
5690// Get pointer to item in the stack.
5691#undef STACK_TV
5692#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
5693
5694// Get pointer to item at the bottom of the stack, -1 is the bottom.
5695#undef STACK_TV_BOT
5696#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
5697
5698// Get pointer to a local variable on the stack. Negative for arguments.
5699#undef STACK_TV_VAR
5700#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
5701
5702 if (ufunc->uf_def_status == UF_NOT_COMPILED
5703 || ufunc->uf_def_status == UF_COMPILE_ERROR
Bram Moolenaar139575d2022-03-15 19:29:30 +00005704 || (func_needs_compiling(ufunc, get_compile_type(ufunc))
5705 && compile_def_function(ufunc, FALSE,
5706 get_compile_type(ufunc), NULL) == FAIL))
Bram Moolenaar4c137212021-04-19 16:48:48 +02005707 {
5708 if (did_emsg_cumul + did_emsg == did_emsg_before)
5709 semsg(_(e_function_is_not_compiled_str),
5710 printable_func_name(ufunc));
5711 return FAIL;
5712 }
5713
5714 {
5715 // Check the function was really compiled.
5716 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5717 + ufunc->uf_dfunc_idx;
Bram Moolenaarcc341812022-09-19 15:54:34 +01005718 if (dfunc->df_ufunc == NULL)
5719 {
5720 semsg(_(e_function_was_deleted_str), printable_func_name(ufunc));
5721 return FAIL;
5722 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005723 if (INSTRUCTIONS(dfunc) == NULL)
5724 {
5725 iemsg("using call_def_function() on not compiled function");
5726 return FAIL;
5727 }
5728 }
5729
5730 // If depth of calling is getting too high, don't execute the function.
5731 orig_funcdepth = funcdepth_get();
5732 if (funcdepth_increment() == FAIL)
5733 return FAIL;
5734
5735 CLEAR_FIELD(ectx);
5736 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
5737 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
Bram Moolenaar35578162021-08-02 19:10:38 +02005738 if (GA_GROW_FAILS(&ectx.ec_stack, 20))
Bram Moolenaar4c137212021-04-19 16:48:48 +02005739 {
5740 funcdepth_decrement();
5741 return FAIL;
5742 }
5743 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
5744 ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
5745 ectx.ec_did_emsg_before = did_emsg_before;
Bram Moolenaare99d4222021-06-13 14:01:26 +02005746 ++ex_nesting_level;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005747
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005748 idx = total_argc - ufunc->uf_args.ga_len;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005749 if (idx > 0 && ufunc->uf_va_name == NULL)
5750 {
Matvey Tarasovd14bb1a2022-06-29 13:18:27 +01005751 semsg(NGETTEXT(e_one_argument_too_many, e_nr_arguments_too_many,
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005752 idx), idx);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005753 goto failed_early;
5754 }
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005755 idx = total_argc - ufunc->uf_args.ga_len + ufunc->uf_def_args.ga_len;
Bram Moolenaarc6d71532021-06-05 18:49:38 +02005756 if (idx < 0)
Bram Moolenaar8da6d6d2021-06-05 18:15:09 +02005757 {
Matvey Tarasovd14bb1a2022-06-29 13:18:27 +01005758 semsg(NGETTEXT(e_one_argument_too_few, e_nr_arguments_too_few,
Bram Moolenaar98aff652022-09-06 21:02:35 +01005759 -idx), -idx);
Bram Moolenaar8da6d6d2021-06-05 18:15:09 +02005760 goto failed_early;
5761 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005762
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005763 // Put values from the partial and arguments on the stack, but no more than
5764 // what the function expects. A lambda can be called with more arguments
5765 // than it uses.
5766 for (idx = 0; idx < total_argc
Bram Moolenaar4c137212021-04-19 16:48:48 +02005767 && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len);
5768 ++idx)
5769 {
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005770 int argv_idx = idx - partial_argc;
5771
5772 tv = idx < partial_argc ? partial->pt_argv + idx : argv + argv_idx;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005773 if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005774 && tv->v_type == VAR_SPECIAL
5775 && tv->vval.v_number == VVAL_NONE)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005776 {
5777 // Use the default value.
5778 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
5779 }
5780 else
5781 {
5782 if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
5783 && check_typval_arg_type(
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005784 ufunc->uf_arg_types[idx], tv,
5785 NULL, argv_idx + 1) == FAIL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005786 goto failed_early;
Bram Moolenaarc9c967d2022-09-07 16:48:46 +01005787 copy_tv(tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005788 }
5789 ++ectx.ec_stack.ga_len;
5790 }
5791
5792 // Turn varargs into a list. Empty list if no args.
5793 if (ufunc->uf_va_name != NULL)
5794 {
5795 int vararg_count = argc - ufunc->uf_args.ga_len;
5796
5797 if (vararg_count < 0)
5798 vararg_count = 0;
5799 else
5800 argc -= vararg_count;
5801 if (exe_newlist(vararg_count, &ectx) == FAIL)
5802 goto failed_early;
5803
5804 // Check the type of the list items.
5805 tv = STACK_TV_BOT(-1);
5806 if (ufunc->uf_va_type != NULL
5807 && ufunc->uf_va_type != &t_list_any
5808 && ufunc->uf_va_type->tt_member != &t_any
5809 && tv->vval.v_list != NULL)
5810 {
5811 type_T *expected = ufunc->uf_va_type->tt_member;
5812 listitem_T *li = tv->vval.v_list->lv_first;
5813
5814 for (idx = 0; idx < vararg_count; ++idx)
5815 {
5816 if (check_typval_arg_type(expected, &li->li_tv,
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02005817 NULL, argc + idx + 1) == FAIL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005818 goto failed_early;
5819 li = li->li_next;
5820 }
5821 }
5822
5823 if (defcount > 0)
5824 // Move varargs list to below missing default arguments.
5825 *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1);
5826 --ectx.ec_stack.ga_len;
5827 }
5828
5829 // Make space for omitted arguments, will store default value below.
5830 // Any varargs list goes after them.
5831 if (defcount > 0)
5832 for (idx = 0; idx < defcount; ++idx)
5833 {
5834 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
5835 ++ectx.ec_stack.ga_len;
5836 }
5837 if (ufunc->uf_va_name != NULL)
5838 ++ectx.ec_stack.ga_len;
5839
5840 // Frame pointer points to just after arguments.
5841 ectx.ec_frame_idx = ectx.ec_stack.ga_len;
5842 ectx.ec_initial_frame_idx = ectx.ec_frame_idx;
5843
5844 {
5845 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5846 + ufunc->uf_dfunc_idx;
5847 ufunc_T *base_ufunc = dfunc->df_ufunc;
5848
5849 // "uf_partial" is on the ufunc that "df_ufunc" points to, as is done
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01005850 // by copy_lambda_to_global_func().
Bram Moolenaar4c137212021-04-19 16:48:48 +02005851 if (partial != NULL || base_ufunc->uf_partial != NULL)
5852 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005853 ectx.ec_outer_ref = ALLOC_CLEAR_ONE(outer_ref_T);
5854 if (ectx.ec_outer_ref == NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005855 goto failed_early;
5856 if (partial != NULL)
5857 {
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +00005858 outer_T *outer = get_pt_outer(partial);
5859
Bram Moolenaar6d313be2022-09-22 16:36:25 +01005860 if (outer->out_stack == NULL && outer->out_loop_size == 0)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005861 {
Bram Moolenaar6d313be2022-09-22 16:36:25 +01005862 // no stack was set
Bram Moolenaarfe1bfc92022-02-06 13:55:03 +00005863 if (current_ectx != NULL)
5864 {
5865 if (current_ectx->ec_outer_ref != NULL
5866 && current_ectx->ec_outer_ref->or_outer != NULL)
5867 ectx.ec_outer_ref->or_outer =
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005868 current_ectx->ec_outer_ref->or_outer;
Bram Moolenaarfe1bfc92022-02-06 13:55:03 +00005869 }
Bram Moolenaar0cdfb7c2022-09-17 15:44:52 +01005870 // else: should there be an error here?
Bram Moolenaar4c137212021-04-19 16:48:48 +02005871 }
5872 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005873 {
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +00005874 ectx.ec_outer_ref->or_outer = outer;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005875 ++partial->pt_refcount;
5876 ectx.ec_outer_ref->or_partial = partial;
5877 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005878 }
5879 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005880 {
5881 ectx.ec_outer_ref->or_outer = &base_ufunc->uf_partial->pt_outer;
5882 ++base_ufunc->uf_partial->pt_refcount;
5883 ectx.ec_outer_ref->or_partial = base_ufunc->uf_partial;
5884 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005885 }
5886 }
5887
5888 // dummy frame entries
5889 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
5890 {
5891 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
5892 ++ectx.ec_stack.ga_len;
5893 }
5894
5895 {
5896 // Reserve space for local variables and any closure reference count.
5897 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5898 + ufunc->uf_dfunc_idx;
5899
Bram Moolenaar5cd64792021-12-25 18:23:24 +00005900 // Initialize variables to zero. That avoids having to generate
5901 // initializing instructions for "var nr: number", "var x: any", etc.
Bram Moolenaar4c137212021-04-19 16:48:48 +02005902 for (idx = 0; idx < dfunc->df_varcount; ++idx)
Bram Moolenaar5cd64792021-12-25 18:23:24 +00005903 {
5904 STACK_TV_VAR(idx)->v_type = VAR_NUMBER;
5905 STACK_TV_VAR(idx)->vval.v_number = 0;
5906 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005907 ectx.ec_stack.ga_len += dfunc->df_varcount;
Bram Moolenaarffdaca92022-12-09 21:41:48 +00005908
5909 if (object != NULL)
5910 {
5911 // the object is always the variable at index zero
5912 tv = STACK_TV_VAR(0);
5913 tv->v_type = VAR_OBJECT;
5914 tv->vval.v_object = object;
5915 }
5916
Bram Moolenaar4c137212021-04-19 16:48:48 +02005917 if (dfunc->df_has_closure)
5918 {
Bram Moolenaarcc341812022-09-19 15:54:34 +01005919 // Initialize the variable that counts how many closures were
5920 // created. This is used in handle_closure_in_use().
Bram Moolenaar4c137212021-04-19 16:48:48 +02005921 STACK_TV_VAR(idx)->v_type = VAR_NUMBER;
5922 STACK_TV_VAR(idx)->vval.v_number = 0;
5923 ++ectx.ec_stack.ga_len;
5924 }
5925
5926 ectx.ec_instr = INSTRUCTIONS(dfunc);
5927 }
5928
Bram Moolenaar58779852022-09-06 18:31:14 +01005929 // Store the execution context in funccal, used by invoke_all_defer().
5930 if (funccal != NULL)
5931 funccal->fc_ectx = &ectx;
5932
Bram Moolenaar4c137212021-04-19 16:48:48 +02005933 // Following errors are in the function, not the caller.
5934 // Commands behave like vim9script.
5935 estack_push_ufunc(ufunc, 1);
5936 current_sctx = ufunc->uf_script_ctx;
5937 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5938
5939 // Use a specific location for storing error messages to be converted to an
5940 // exception.
5941 saved_msg_list = msg_list;
5942 msg_list = &private_msg_list;
5943
5944 // Do turn errors into exceptions.
5945 suppress_errthrow = FALSE;
5946
5947 // Do not delete the function while executing it.
5948 ++ufunc->uf_calls;
5949
5950 // When ":silent!" was used before calling then we still abort the
5951 // function. If ":silent!" is used in the function then we don't.
5952 emsg_silent_def = emsg_silent;
5953 did_emsg_def = 0;
5954
5955 ectx.ec_where.wt_index = 0;
5956 ectx.ec_where.wt_variable = FALSE;
5957
Bram Moolenaar5800c792022-09-22 17:34:01 +01005958 /*
5959 * Execute the instructions until done.
5960 */
Bram Moolenaar4c137212021-04-19 16:48:48 +02005961 ret = exec_instructions(&ectx);
5962 if (ret == OK)
5963 {
5964 // function finished, get result from the stack.
5965 if (ufunc->uf_ret_type == &t_void)
5966 {
5967 rettv->v_type = VAR_VOID;
5968 }
5969 else
5970 {
5971 tv = STACK_TV_BOT(-1);
5972 *rettv = *tv;
5973 tv->v_type = VAR_UNKNOWN;
5974 }
5975 }
5976
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01005977 // When failed need to unwind the call stack.
Bram Moolenaar58779852022-09-06 18:31:14 +01005978 unwind_def_callstack(&ectx);
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02005979
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02005980 // Deal with any remaining closures, they may be in use somewhere.
5981 if (ectx.ec_funcrefs.ga_len > 0)
Bram Moolenaarf112f302020-12-20 17:47:52 +01005982 {
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02005983 handle_closure_in_use(&ectx, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00005984 ga_clear(&ectx.ec_funcrefs);
Bram Moolenaarf112f302020-12-20 17:47:52 +01005985 }
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02005986
Bram Moolenaaree8580e2020-08-28 17:19:07 +02005987 estack_pop();
5988 current_sctx = save_current_sctx;
5989
Bram Moolenaar2336c372021-12-06 15:06:54 +00005990 if (--ufunc->uf_calls <= 0 && ufunc->uf_refcount <= 0)
5991 // Function was unreferenced while being used, free it now.
5992 func_clear_free(ufunc, FALSE);
Bram Moolenaarc970e422021-03-17 15:03:04 +01005993
Bram Moolenaar352134b2020-10-17 22:04:08 +02005994 if (*msg_list != NULL && saved_msg_list != NULL)
5995 {
5996 msglist_T **plist = saved_msg_list;
5997
5998 // Append entries from the current msg_list (uncaught exceptions) to
5999 // the saved msg_list.
6000 while (*plist != NULL)
6001 plist = &(*plist)->next;
6002
6003 *plist = *msg_list;
6004 }
6005 msg_list = saved_msg_list;
6006
Bram Moolenaar4c137212021-04-19 16:48:48 +02006007 if (ectx.ec_funclocal.floc_restore_cmdmod)
Bram Moolenaar02194d22020-10-24 23:08:38 +02006008 {
6009 cmdmod.cmod_filter_regmatch.regprog = NULL;
6010 undo_cmdmod(&cmdmod);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006011 cmdmod = ectx.ec_funclocal.floc_save_cmdmod;
Bram Moolenaar02194d22020-10-24 23:08:38 +02006012 }
Bram Moolenaar56602ba2020-12-05 21:22:08 +01006013 emsg_silent_def = save_emsg_silent_def;
6014 did_emsg_def += save_did_emsg_def;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02006015
Bram Moolenaaree8580e2020-08-28 17:19:07 +02006016failed_early:
Bram Moolenaar0d1f55c2022-04-05 17:30:29 +01006017 // Free all arguments and local variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006018 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
Bram Moolenaar1936c762022-09-28 15:19:10 +01006019 {
6020 tv = STACK_TV(idx);
6021 if (tv->v_type != VAR_NUMBER && tv->v_type != VAR_UNKNOWN)
6022 clear_tv(tv);
6023 }
Bram Moolenaare99d4222021-06-13 14:01:26 +02006024 ex_nesting_level = orig_nesting_level;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02006025
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006026 vim_free(ectx.ec_stack.ga_data);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006027 vim_free(ectx.ec_trystack.ga_data);
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02006028 if (ectx.ec_outer_ref != NULL)
Bram Moolenaar0186e582021-01-10 18:33:11 +01006029 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02006030 if (ectx.ec_outer_ref->or_outer_allocated)
6031 vim_free(ectx.ec_outer_ref->or_outer);
6032 partial_unref(ectx.ec_outer_ref->or_partial);
6033 vim_free(ectx.ec_outer_ref);
Bram Moolenaar0186e582021-01-10 18:33:11 +01006034 }
6035
Bram Moolenaar77e5dcc2020-09-17 21:29:03 +02006036 // Not sure if this is necessary.
6037 suppress_errthrow = save_suppress_errthrow;
6038
Bram Moolenaarb5841b92021-07-15 18:09:53 +02006039 if (ret != OK && did_emsg_cumul + did_emsg == did_emsg_before
6040 && !need_rethrow)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006041 semsg(_(e_unknown_error_while_executing_str),
Bram Moolenaar682d0a12020-07-19 20:48:59 +02006042 printable_func_name(ufunc));
Bram Moolenaar0ba48e82020-11-17 18:23:19 +01006043 funcdepth_restore(orig_funcdepth);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006044 return ret;
6045}
6046
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006047/*
Bram Moolenaar58779852022-09-06 18:31:14 +01006048 * Called when a def function has finished (possibly failed).
6049 * Invoke all the function returns to clean up and invoke deferred functions,
6050 * except the toplevel one.
6051 */
6052 void
6053unwind_def_callstack(ectx_T *ectx)
6054{
6055 while (ectx->ec_frame_idx != ectx->ec_initial_frame_idx)
6056 func_return(ectx);
6057}
6058
6059/*
dundargocc57b5bc2022-11-02 13:30:51 +00006060 * Invoke any deferred functions for the top function in "ectx".
Bram Moolenaar58779852022-09-06 18:31:14 +01006061 */
6062 void
6063may_invoke_defer_funcs(ectx_T *ectx)
6064{
6065 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
6066
6067 if (dfunc->df_defer_var_idx > 0)
6068 invoke_defer_funcs(ectx);
6069}
6070
6071/*
Bram Moolenaarcc341812022-09-19 15:54:34 +01006072 * Return loopvarinfo in a printable form in allocated memory.
6073 */
6074 static char_u *
6075printable_loopvarinfo(loopvarinfo_T *lvi)
6076{
6077 garray_T ga;
6078 int depth;
6079
6080 ga_init2(&ga, 1, 100);
6081 for (depth = 0; depth < lvi->lvi_depth; ++depth)
6082 {
6083 if (ga_grow(&ga, 50) == FAIL)
6084 break;
6085 if (lvi->lvi_loop[depth].var_idx == 0)
Bram Moolenaarc9e4a6f2022-09-19 16:08:04 +01006086 STRCPY((char *)ga.ga_data + ga.ga_len, " -");
Bram Moolenaarcc341812022-09-19 15:54:34 +01006087 else
Bram Moolenaarc9e4a6f2022-09-19 16:08:04 +01006088 vim_snprintf((char *)ga.ga_data + ga.ga_len, 50, " $%d-$%d",
Bram Moolenaarcc341812022-09-19 15:54:34 +01006089 lvi->lvi_loop[depth].var_idx,
6090 lvi->lvi_loop[depth].var_idx
6091 + lvi->lvi_loop[depth].var_count - 1);
Bram Moolenaarc9e4a6f2022-09-19 16:08:04 +01006092 ga.ga_len = (int)STRLEN(ga.ga_data);
Bram Moolenaarcc341812022-09-19 15:54:34 +01006093 }
6094 return ga.ga_data;
6095}
6096
6097/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02006098 * List instructions "instr" up to "instr_count" or until ISN_FINISH.
6099 * "ufunc" has the source lines, NULL for the instructions of ISN_SUBSTITUTE.
6100 * "pfx" is prefixed to every line.
6101 */
6102 static void
6103list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
6104{
6105 int line_idx = 0;
6106 int prev_current = 0;
6107 int current;
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02006108 int def_arg_idx = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006109
6110 for (current = 0; current < instr_count; ++current)
6111 {
6112 isn_T *iptr = &instr[current];
6113 char *line;
6114
6115 if (ufunc != NULL)
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02006116 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02006117 while (line_idx < iptr->isn_lnum
6118 && line_idx < ufunc->uf_lines.ga_len)
6119 {
6120 if (current > prev_current)
6121 {
6122 msg_puts("\n\n");
6123 prev_current = current;
6124 }
6125 line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
6126 if (line != NULL)
6127 msg(line);
6128 }
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02006129 if (iptr->isn_type == ISN_JUMP_IF_ARG_SET)
6130 {
6131 int first_def_arg = ufunc->uf_args.ga_len
6132 - ufunc->uf_def_args.ga_len;
6133
6134 if (def_arg_idx > 0)
6135 msg_puts("\n\n");
6136 msg_start();
6137 msg_puts(" ");
6138 msg_puts(((char **)(ufunc->uf_args.ga_data))[
6139 first_def_arg + def_arg_idx]);
6140 msg_puts(" = ");
6141 msg_puts(((char **)(ufunc->uf_def_args.ga_data))[def_arg_idx++]);
6142 msg_clr_eos();
6143 msg_end();
6144 }
6145 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02006146
6147 switch (iptr->isn_type)
6148 {
Bram Moolenaar00b28d62022-12-08 15:32:33 +00006149 case ISN_CONSTRUCT:
6150 smsg("%s%4d NEW %s size %d", pfx, current,
6151 iptr->isn_arg.construct.construct_class->class_name,
6152 (int)iptr->isn_arg.construct.construct_size);
6153 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006154 case ISN_EXEC:
6155 smsg("%s%4d EXEC %s", pfx, current, iptr->isn_arg.string);
6156 break;
Bram Moolenaar20677332021-06-06 17:02:53 +02006157 case ISN_EXEC_SPLIT:
6158 smsg("%s%4d EXEC_SPLIT %s", pfx, current, iptr->isn_arg.string);
6159 break;
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00006160 case ISN_EXECRANGE:
6161 smsg("%s%4d EXECRANGE %s", pfx, current, iptr->isn_arg.string);
6162 break;
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02006163 case ISN_LEGACY_EVAL:
6164 smsg("%s%4d EVAL legacy %s", pfx, current,
6165 iptr->isn_arg.string);
6166 break;
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02006167 case ISN_REDIRSTART:
6168 smsg("%s%4d REDIR", pfx, current);
6169 break;
6170 case ISN_REDIREND:
6171 smsg("%s%4d REDIR END%s", pfx, current,
6172 iptr->isn_arg.number ? " append" : "");
6173 break;
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02006174 case ISN_CEXPR_AUCMD:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02006175#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02006176 smsg("%s%4d CEXPR pre %s", pfx, current,
6177 cexpr_get_auname(iptr->isn_arg.number));
Bram Moolenaarb7c97812021-05-05 22:51:39 +02006178#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02006179 break;
6180 case ISN_CEXPR_CORE:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02006181#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02006182 {
6183 cexprref_T *cer = iptr->isn_arg.cexpr.cexpr_ref;
6184
6185 smsg("%s%4d CEXPR core %s%s \"%s\"", pfx, current,
6186 cexpr_get_auname(cer->cer_cmdidx),
6187 cer->cer_forceit ? "!" : "",
6188 cer->cer_cmdline);
6189 }
Bram Moolenaarb7c97812021-05-05 22:51:39 +02006190#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02006191 break;
Bram Moolenaarf18332f2021-05-07 17:55:55 +02006192 case ISN_INSTR:
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01006193 smsg("%s%4d INSTR", pfx, current);
6194 list_instructions(" ", iptr->isn_arg.instr, INT_MAX, NULL);
6195 msg(" -------------");
6196 break;
6197 case ISN_SOURCE:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02006198 {
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01006199 scriptitem_T *si = SCRIPT_ITEM(iptr->isn_arg.number);
6200
6201 smsg("%s%4d SOURCE %s", pfx, current, si->sn_name);
Bram Moolenaarf18332f2021-05-07 17:55:55 +02006202 }
6203 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006204 case ISN_SUBSTITUTE:
6205 {
6206 subs_T *subs = &iptr->isn_arg.subs;
6207
6208 smsg("%s%4d SUBSTITUTE %s", pfx, current, subs->subs_cmd);
6209 list_instructions(" ", subs->subs_instr, INT_MAX, NULL);
6210 msg(" -------------");
6211 }
6212 break;
6213 case ISN_EXECCONCAT:
6214 smsg("%s%4d EXECCONCAT %lld", pfx, current,
6215 (varnumber_T)iptr->isn_arg.number);
6216 break;
6217 case ISN_ECHO:
6218 {
6219 echo_T *echo = &iptr->isn_arg.echo;
6220
6221 smsg("%s%4d %s %d", pfx, current,
6222 echo->echo_with_white ? "ECHO" : "ECHON",
6223 echo->echo_count);
6224 }
6225 break;
6226 case ISN_EXECUTE:
6227 smsg("%s%4d EXECUTE %lld", pfx, current,
Bram Moolenaar7de62622021-08-07 15:05:47 +02006228 (varnumber_T)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006229 break;
6230 case ISN_ECHOMSG:
6231 smsg("%s%4d ECHOMSG %lld", pfx, current,
Bram Moolenaar7de62622021-08-07 15:05:47 +02006232 (varnumber_T)(iptr->isn_arg.number));
6233 break;
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01006234 case ISN_ECHOWINDOW:
Bram Moolenaarbdc09a12022-10-07 14:31:45 +01006235 if (iptr->isn_arg.echowin.ewin_time > 0)
6236 smsg("%s%4d ECHOWINDOW %d (%ld sec)", pfx, current,
6237 iptr->isn_arg.echowin.ewin_count,
6238 iptr->isn_arg.echowin.ewin_time);
6239 else
6240 smsg("%s%4d ECHOWINDOW %d", pfx, current,
6241 iptr->isn_arg.echowin.ewin_count);
Bram Moolenaar7d7ad7b2022-09-01 16:00:53 +01006242 break;
Bram Moolenaar7de62622021-08-07 15:05:47 +02006243 case ISN_ECHOCONSOLE:
6244 smsg("%s%4d ECHOCONSOLE %lld", pfx, current,
6245 (varnumber_T)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006246 break;
6247 case ISN_ECHOERR:
6248 smsg("%s%4d ECHOERR %lld", pfx, current,
Bram Moolenaar7de62622021-08-07 15:05:47 +02006249 (varnumber_T)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006250 break;
6251 case ISN_LOAD:
6252 {
6253 if (iptr->isn_arg.number < 0)
6254 smsg("%s%4d LOAD arg[%lld]", pfx, current,
6255 (varnumber_T)(iptr->isn_arg.number
6256 + STACK_FRAME_SIZE));
6257 else
6258 smsg("%s%4d LOAD $%lld", pfx, current,
6259 (varnumber_T)(iptr->isn_arg.number));
6260 }
6261 break;
6262 case ISN_LOADOUTER:
6263 {
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01006264 isn_outer_T *outer = &iptr->isn_arg.outer;
6265
6266 if (outer->outer_idx < 0)
Bram Moolenaar4c137212021-04-19 16:48:48 +02006267 smsg("%s%4d LOADOUTER level %d arg[%d]", pfx, current,
Bram Moolenaarcc341812022-09-19 15:54:34 +01006268 outer->outer_depth,
6269 outer->outer_idx + STACK_FRAME_SIZE);
6270 else if (outer->outer_depth < 0)
6271 smsg("%s%4d LOADOUTER $%d in loop level %d",
6272 pfx, current,
6273 outer->outer_idx,
6274 -outer->outer_depth);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006275 else
6276 smsg("%s%4d LOADOUTER level %d $%d", pfx, current,
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01006277 outer->outer_depth,
6278 outer->outer_idx);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006279 }
6280 break;
6281 case ISN_LOADV:
6282 smsg("%s%4d LOADV v:%s", pfx, current,
6283 get_vim_var_name(iptr->isn_arg.number));
6284 break;
6285 case ISN_LOADSCRIPT:
6286 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006287 scriptref_T *sref = iptr->isn_arg.script.scriptref;
6288 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
6289 svar_T *sv;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006290
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006291 sv = get_script_svar(sref, -1);
6292 if (sv == NULL)
6293 smsg("%s%4d LOADSCRIPT [deleted] from %s",
6294 pfx, current, si->sn_name);
6295 else
6296 smsg("%s%4d LOADSCRIPT %s-%d from %s", pfx, current,
Bram Moolenaar4c137212021-04-19 16:48:48 +02006297 sv->sv_name,
6298 sref->sref_idx,
6299 si->sn_name);
6300 }
6301 break;
6302 case ISN_LOADS:
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01006303 case ISN_LOADEXPORT:
Bram Moolenaar4c137212021-04-19 16:48:48 +02006304 {
6305 scriptitem_T *si = SCRIPT_ITEM(
6306 iptr->isn_arg.loadstore.ls_sid);
6307
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01006308 smsg("%s%4d %s s:%s from %s", pfx, current,
6309 iptr->isn_type == ISN_LOADS ? "LOADS"
6310 : "LOADEXPORT",
6311 iptr->isn_arg.loadstore.ls_name, si->sn_name);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006312 }
6313 break;
6314 case ISN_LOADAUTO:
6315 smsg("%s%4d LOADAUTO %s", pfx, current, iptr->isn_arg.string);
6316 break;
6317 case ISN_LOADG:
6318 smsg("%s%4d LOADG g:%s", pfx, current, iptr->isn_arg.string);
6319 break;
6320 case ISN_LOADB:
6321 smsg("%s%4d LOADB b:%s", pfx, current, iptr->isn_arg.string);
6322 break;
6323 case ISN_LOADW:
6324 smsg("%s%4d LOADW w:%s", pfx, current, iptr->isn_arg.string);
6325 break;
6326 case ISN_LOADT:
6327 smsg("%s%4d LOADT t:%s", pfx, current, iptr->isn_arg.string);
6328 break;
6329 case ISN_LOADGDICT:
6330 smsg("%s%4d LOAD g:", pfx, current);
6331 break;
6332 case ISN_LOADBDICT:
6333 smsg("%s%4d LOAD b:", pfx, current);
6334 break;
6335 case ISN_LOADWDICT:
6336 smsg("%s%4d LOAD w:", pfx, current);
6337 break;
6338 case ISN_LOADTDICT:
6339 smsg("%s%4d LOAD t:", pfx, current);
6340 break;
6341 case ISN_LOADOPT:
6342 smsg("%s%4d LOADOPT %s", pfx, current, iptr->isn_arg.string);
6343 break;
6344 case ISN_LOADENV:
6345 smsg("%s%4d LOADENV %s", pfx, current, iptr->isn_arg.string);
6346 break;
6347 case ISN_LOADREG:
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006348 smsg("%s%4d LOADREG @%c", pfx, current,
6349 (int)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006350 break;
6351
6352 case ISN_STORE:
6353 if (iptr->isn_arg.number < 0)
6354 smsg("%s%4d STORE arg[%lld]", pfx, current,
6355 iptr->isn_arg.number + STACK_FRAME_SIZE);
6356 else
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006357 smsg("%s%4d STORE $%lld", pfx, current,
6358 iptr->isn_arg.number);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006359 break;
6360 case ISN_STOREOUTER:
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01006361 {
6362 isn_outer_T *outer = &iptr->isn_arg.outer;
6363
6364 if (outer->outer_depth == OUTER_LOOP_DEPTH)
6365 smsg("%s%4d STOREOUTER level 1 $%d in loop",
6366 pfx, current, outer->outer_idx);
6367 else
6368 smsg("%s%4d STOREOUTER level %d $%d", pfx, current,
6369 outer->outer_depth, outer->outer_idx);
6370 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02006371 break;
6372 case ISN_STOREV:
6373 smsg("%s%4d STOREV v:%s", pfx, current,
6374 get_vim_var_name(iptr->isn_arg.number));
6375 break;
6376 case ISN_STOREAUTO:
6377 smsg("%s%4d STOREAUTO %s", pfx, current, iptr->isn_arg.string);
6378 break;
6379 case ISN_STOREG:
6380 smsg("%s%4d STOREG %s", pfx, current, iptr->isn_arg.string);
6381 break;
6382 case ISN_STOREB:
6383 smsg("%s%4d STOREB %s", pfx, current, iptr->isn_arg.string);
6384 break;
6385 case ISN_STOREW:
6386 smsg("%s%4d STOREW %s", pfx, current, iptr->isn_arg.string);
6387 break;
6388 case ISN_STORET:
6389 smsg("%s%4d STORET %s", pfx, current, iptr->isn_arg.string);
6390 break;
6391 case ISN_STORES:
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01006392 case ISN_STOREEXPORT:
Bram Moolenaar4c137212021-04-19 16:48:48 +02006393 {
6394 scriptitem_T *si = SCRIPT_ITEM(
6395 iptr->isn_arg.loadstore.ls_sid);
6396
Bram Moolenaarc0ceeeb2022-03-30 21:12:27 +01006397 smsg("%s%4d %s %s in %s", pfx, current,
6398 iptr->isn_type == ISN_STORES
6399 ? "STORES" : "STOREEXPORT",
Bram Moolenaar4c137212021-04-19 16:48:48 +02006400 iptr->isn_arg.loadstore.ls_name, si->sn_name);
6401 }
6402 break;
6403 case ISN_STORESCRIPT:
6404 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006405 scriptref_T *sref = iptr->isn_arg.script.scriptref;
6406 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
6407 svar_T *sv;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006408
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006409 sv = get_script_svar(sref, -1);
6410 if (sv == NULL)
6411 smsg("%s%4d STORESCRIPT [deleted] in %s",
6412 pfx, current, si->sn_name);
6413 else
6414 smsg("%s%4d STORESCRIPT %s-%d in %s", pfx, current,
Bram Moolenaar4c137212021-04-19 16:48:48 +02006415 sv->sv_name,
6416 sref->sref_idx,
6417 si->sn_name);
6418 }
6419 break;
6420 case ISN_STOREOPT:
Bram Moolenaardcb53be2021-12-09 14:23:43 +00006421 case ISN_STOREFUNCOPT:
6422 smsg("%s%4d %s &%s", pfx, current,
6423 iptr->isn_type == ISN_STOREOPT ? "STOREOPT" : "STOREFUNCOPT",
Bram Moolenaar4c137212021-04-19 16:48:48 +02006424 iptr->isn_arg.storeopt.so_name);
6425 break;
6426 case ISN_STOREENV:
6427 smsg("%s%4d STOREENV $%s", pfx, current, iptr->isn_arg.string);
6428 break;
6429 case ISN_STOREREG:
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006430 smsg("%s%4d STOREREG @%c", pfx, current,
6431 (int)iptr->isn_arg.number);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006432 break;
6433 case ISN_STORENR:
6434 smsg("%s%4d STORE %lld in $%d", pfx, current,
6435 iptr->isn_arg.storenr.stnr_val,
6436 iptr->isn_arg.storenr.stnr_idx);
6437 break;
6438
6439 case ISN_STOREINDEX:
6440 smsg("%s%4d STOREINDEX %s", pfx, current,
6441 vartype_name(iptr->isn_arg.vartype));
6442 break;
6443
6444 case ISN_STORERANGE:
6445 smsg("%s%4d STORERANGE", pfx, current);
6446 break;
6447
Bram Moolenaard505d172022-12-18 21:42:55 +00006448 case ISN_LOAD_CLASSMEMBER:
6449 case ISN_STORE_CLASSMEMBER:
6450 {
6451 class_T *cl = iptr->isn_arg.classmember.cm_class;
6452 int idx = iptr->isn_arg.classmember.cm_idx;
6453 ocmember_T *ocm = &cl->class_class_members[idx];
6454 smsg("%s%4d %s CLASSMEMBER %s.%s", pfx, current,
6455 iptr->isn_type == ISN_LOAD_CLASSMEMBER
6456 ? "LOAD" : "STORE",
6457 cl->class_name, ocm->ocm_name);
6458 }
6459 break;
6460
Bram Moolenaar4c137212021-04-19 16:48:48 +02006461 // constants
6462 case ISN_PUSHNR:
6463 smsg("%s%4d PUSHNR %lld", pfx, current,
6464 (varnumber_T)(iptr->isn_arg.number));
6465 break;
6466 case ISN_PUSHBOOL:
6467 case ISN_PUSHSPEC:
6468 smsg("%s%4d PUSH %s", pfx, current,
6469 get_var_special_name(iptr->isn_arg.number));
6470 break;
6471 case ISN_PUSHF:
Bram Moolenaar4c137212021-04-19 16:48:48 +02006472 smsg("%s%4d PUSHF %g", pfx, current, iptr->isn_arg.fnumber);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006473 break;
6474 case ISN_PUSHS:
6475 smsg("%s%4d PUSHS \"%s\"", pfx, current, iptr->isn_arg.string);
6476 break;
6477 case ISN_PUSHBLOB:
6478 {
6479 char_u *r;
6480 char_u numbuf[NUMBUFLEN];
6481 char_u *tofree;
6482
6483 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
6484 smsg("%s%4d PUSHBLOB %s", pfx, current, r);
6485 vim_free(tofree);
6486 }
6487 break;
6488 case ISN_PUSHFUNC:
6489 {
6490 char *name = (char *)iptr->isn_arg.string;
6491
6492 smsg("%s%4d PUSHFUNC \"%s\"", pfx, current,
6493 name == NULL ? "[none]" : name);
6494 }
6495 break;
6496 case ISN_PUSHCHANNEL:
6497#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar397a87a2022-03-20 21:14:15 +00006498 smsg("%s%4d PUSHCHANNEL 0", pfx, current);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006499#endif
6500 break;
6501 case ISN_PUSHJOB:
6502#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar397a87a2022-03-20 21:14:15 +00006503 smsg("%s%4d PUSHJOB \"no process\"", pfx, current);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006504#endif
6505 break;
6506 case ISN_PUSHEXC:
6507 smsg("%s%4d PUSH v:exception", pfx, current);
6508 break;
Bram Moolenaar06b77222022-01-25 15:51:56 +00006509 case ISN_AUTOLOAD:
6510 smsg("%s%4d AUTOLOAD %s", pfx, current, iptr->isn_arg.string);
6511 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006512 case ISN_UNLET:
6513 smsg("%s%4d UNLET%s %s", pfx, current,
6514 iptr->isn_arg.unlet.ul_forceit ? "!" : "",
6515 iptr->isn_arg.unlet.ul_name);
6516 break;
6517 case ISN_UNLETENV:
6518 smsg("%s%4d UNLETENV%s $%s", pfx, current,
6519 iptr->isn_arg.unlet.ul_forceit ? "!" : "",
6520 iptr->isn_arg.unlet.ul_name);
6521 break;
6522 case ISN_UNLETINDEX:
6523 smsg("%s%4d UNLETINDEX", pfx, current);
6524 break;
6525 case ISN_UNLETRANGE:
6526 smsg("%s%4d UNLETRANGE", pfx, current);
6527 break;
Bram Moolenaaraacc9662021-08-13 19:40:51 +02006528 case ISN_LOCKUNLOCK:
6529 smsg("%s%4d LOCKUNLOCK %s", pfx, current, iptr->isn_arg.string);
6530 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006531 case ISN_LOCKCONST:
6532 smsg("%s%4d LOCKCONST", pfx, current);
6533 break;
6534 case ISN_NEWLIST:
6535 smsg("%s%4d NEWLIST size %lld", pfx, current,
Bram Moolenaar1936c762022-09-28 15:19:10 +01006536 (varnumber_T)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006537 break;
6538 case ISN_NEWDICT:
6539 smsg("%s%4d NEWDICT size %lld", pfx, current,
Bram Moolenaar1936c762022-09-28 15:19:10 +01006540 (varnumber_T)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006541 break;
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00006542 case ISN_NEWPARTIAL:
6543 smsg("%s%4d NEWPARTIAL", pfx, current);
6544 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006545
6546 // function call
6547 case ISN_BCALL:
6548 {
6549 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc;
6550
6551 smsg("%s%4d BCALL %s(argc %d)", pfx, current,
6552 internal_func_name(cbfunc->cbf_idx),
6553 cbfunc->cbf_argcount);
6554 }
6555 break;
6556 case ISN_DCALL:
6557 {
6558 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc;
6559 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
6560 + cdfunc->cdf_idx;
6561
6562 smsg("%s%4d DCALL %s(argc %d)", pfx, current,
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006563 printable_func_name(df->df_ufunc),
6564 cdfunc->cdf_argcount);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006565 }
6566 break;
6567 case ISN_UCALL:
6568 {
6569 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
6570
6571 smsg("%s%4d UCALL %s(argc %d)", pfx, current,
6572 cufunc->cuf_name, cufunc->cuf_argcount);
6573 }
6574 break;
6575 case ISN_PCALL:
6576 {
6577 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc;
6578
6579 smsg("%s%4d PCALL%s (argc %d)", pfx, current,
6580 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
6581 }
6582 break;
6583 case ISN_PCALL_END:
6584 smsg("%s%4d PCALL end", pfx, current);
6585 break;
Bram Moolenaar1d84f762022-09-03 21:35:53 +01006586 case ISN_DEFER:
6587 smsg("%s%4d DEFER %d args", pfx, current,
6588 (int)iptr->isn_arg.defer.defer_argcount);
6589 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006590 case ISN_RETURN:
6591 smsg("%s%4d RETURN", pfx, current);
6592 break;
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02006593 case ISN_RETURN_VOID:
6594 smsg("%s%4d RETURN void", pfx, current);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006595 break;
Bram Moolenaar00b28d62022-12-08 15:32:33 +00006596 case ISN_RETURN_OBJECT:
6597 smsg("%s%4d RETURN object", pfx, current);
6598 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006599 case ISN_FUNCREF:
6600 {
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01006601 funcref_T *funcref = &iptr->isn_arg.funcref;
6602 funcref_extra_T *extra = funcref->fr_extra;
6603 char_u *name;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006604
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01006605 if (extra == NULL || extra->fre_func_name == NULL)
Bram Moolenaar38453522021-11-28 22:00:12 +00006606 {
6607 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
6608 + funcref->fr_dfunc_idx;
6609 name = df->df_ufunc->uf_name;
6610 }
6611 else
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01006612 name = extra->fre_func_name;
Bram Moolenaarcc341812022-09-19 15:54:34 +01006613 if (extra == NULL || extra->fre_loopvar_info.lvi_depth == 0)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01006614 smsg("%s%4d FUNCREF %s", pfx, current, name);
6615 else
Bram Moolenaarcc341812022-09-19 15:54:34 +01006616 {
6617 char_u *info = printable_loopvarinfo(
6618 &extra->fre_loopvar_info);
6619
6620 smsg("%s%4d FUNCREF %s vars %s", pfx, current,
6621 name, info);
6622 vim_free(info);
6623 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02006624 }
6625 break;
6626
6627 case ISN_NEWFUNC:
6628 {
Bram Moolenaarcc341812022-09-19 15:54:34 +01006629 newfuncarg_T *arg = iptr->isn_arg.newfunc.nf_arg;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006630
Bram Moolenaarcc341812022-09-19 15:54:34 +01006631 if (arg->nfa_loopvar_info.lvi_depth == 0)
Bram Moolenaar8fa745e2022-09-16 19:04:24 +01006632 smsg("%s%4d NEWFUNC %s %s", pfx, current,
6633 arg->nfa_lambda, arg->nfa_global);
6634 else
Bram Moolenaarcc341812022-09-19 15:54:34 +01006635 {
6636 char_u *info = printable_loopvarinfo(
6637 &arg->nfa_loopvar_info);
6638
6639 smsg("%s%4d NEWFUNC %s %s vars %s", pfx, current,
6640 arg->nfa_lambda, arg->nfa_global, info);
6641 vim_free(info);
6642 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02006643 }
6644 break;
6645
6646 case ISN_DEF:
6647 {
6648 char_u *name = iptr->isn_arg.string;
6649
6650 smsg("%s%4d DEF %s", pfx, current,
6651 name == NULL ? (char_u *)"" : name);
6652 }
6653 break;
6654
6655 case ISN_JUMP:
6656 {
6657 char *when = "?";
6658
6659 switch (iptr->isn_arg.jump.jump_when)
6660 {
6661 case JUMP_ALWAYS:
6662 when = "JUMP";
6663 break;
Bram Moolenaar1a7ee4d2021-09-16 16:15:07 +02006664 case JUMP_NEVER:
6665 iemsg("JUMP_NEVER should not be used");
6666 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006667 case JUMP_AND_KEEP_IF_TRUE:
6668 when = "JUMP_AND_KEEP_IF_TRUE";
6669 break;
6670 case JUMP_IF_FALSE:
6671 when = "JUMP_IF_FALSE";
6672 break;
Bram Moolenaarb46c0832022-09-15 17:19:37 +01006673 case JUMP_WHILE_FALSE:
6674 when = "JUMP_WHILE_FALSE"; // unused
6675 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006676 case JUMP_IF_COND_FALSE:
6677 when = "JUMP_IF_COND_FALSE";
6678 break;
6679 case JUMP_IF_COND_TRUE:
6680 when = "JUMP_IF_COND_TRUE";
6681 break;
6682 }
6683 smsg("%s%4d %s -> %d", pfx, current, when,
6684 iptr->isn_arg.jump.jump_where);
6685 }
6686 break;
6687
6688 case ISN_JUMP_IF_ARG_SET:
6689 smsg("%s%4d JUMP_IF_ARG_SET arg[%d] -> %d", pfx, current,
6690 iptr->isn_arg.jumparg.jump_arg_off + STACK_FRAME_SIZE,
6691 iptr->isn_arg.jump.jump_where);
6692 break;
6693
Bram Moolenaar65b0d162022-12-13 18:43:22 +00006694 case ISN_JUMP_IF_ARG_NOT_SET:
6695 smsg("%s%4d JUMP_IF_ARG_NOT_SET arg[%d] -> %d", pfx, current,
6696 iptr->isn_arg.jumparg.jump_arg_off + STACK_FRAME_SIZE,
6697 iptr->isn_arg.jump.jump_where);
6698 break;
6699
Bram Moolenaar4c137212021-04-19 16:48:48 +02006700 case ISN_FOR:
6701 {
6702 forloop_T *forloop = &iptr->isn_arg.forloop;
6703
6704 smsg("%s%4d FOR $%d -> %d", pfx, current,
Bram Moolenaarcc341812022-09-19 15:54:34 +01006705 forloop->for_loop_idx, forloop->for_end);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006706 }
6707 break;
6708
Bram Moolenaarb46c0832022-09-15 17:19:37 +01006709 case ISN_ENDLOOP:
6710 {
6711 endloop_T *endloop = &iptr->isn_arg.endloop;
6712
Bram Moolenaarcc341812022-09-19 15:54:34 +01006713 smsg("%s%4d ENDLOOP ref $%d save $%d-$%d depth %d",
6714 pfx, current,
Bram Moolenaarb46c0832022-09-15 17:19:37 +01006715 endloop->end_funcref_idx,
6716 endloop->end_var_idx,
Bram Moolenaarcc341812022-09-19 15:54:34 +01006717 endloop->end_var_idx + endloop->end_var_count - 1,
6718 endloop->end_depth);
Bram Moolenaarb46c0832022-09-15 17:19:37 +01006719 }
6720 break;
6721
6722 case ISN_WHILE:
6723 {
6724 whileloop_T *whileloop = &iptr->isn_arg.whileloop;
6725
6726 smsg("%s%4d WHILE $%d -> %d", pfx, current,
6727 whileloop->while_funcref_idx,
6728 whileloop->while_end);
6729 }
6730 break;
6731
Bram Moolenaar4c137212021-04-19 16:48:48 +02006732 case ISN_TRY:
6733 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00006734 try_T *try = &iptr->isn_arg.tryref;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006735
6736 if (try->try_ref->try_finally == 0)
6737 smsg("%s%4d TRY catch -> %d, endtry -> %d",
6738 pfx, current,
6739 try->try_ref->try_catch,
6740 try->try_ref->try_endtry);
6741 else
6742 smsg("%s%4d TRY catch -> %d, finally -> %d, endtry -> %d",
6743 pfx, current,
6744 try->try_ref->try_catch,
6745 try->try_ref->try_finally,
6746 try->try_ref->try_endtry);
6747 }
6748 break;
6749 case ISN_CATCH:
Bram Moolenaar4c137212021-04-19 16:48:48 +02006750 smsg("%s%4d CATCH", pfx, current);
6751 break;
6752 case ISN_TRYCONT:
6753 {
6754 trycont_T *trycont = &iptr->isn_arg.trycont;
6755
6756 smsg("%s%4d TRY-CONTINUE %d level%s -> %d", pfx, current,
6757 trycont->tct_levels,
6758 trycont->tct_levels == 1 ? "" : "s",
6759 trycont->tct_where);
6760 }
6761 break;
6762 case ISN_FINALLY:
6763 smsg("%s%4d FINALLY", pfx, current);
6764 break;
6765 case ISN_ENDTRY:
6766 smsg("%s%4d ENDTRY", pfx, current);
6767 break;
6768 case ISN_THROW:
6769 smsg("%s%4d THROW", pfx, current);
6770 break;
6771
6772 // expression operations on number
6773 case ISN_OPNR:
6774 case ISN_OPFLOAT:
6775 case ISN_OPANY:
6776 {
6777 char *what;
6778 char *ins;
6779
6780 switch (iptr->isn_arg.op.op_type)
6781 {
6782 case EXPR_MULT: what = "*"; break;
6783 case EXPR_DIV: what = "/"; break;
6784 case EXPR_REM: what = "%"; break;
6785 case EXPR_SUB: what = "-"; break;
6786 case EXPR_ADD: what = "+"; break;
Yegappan Lakshmanana061f342022-05-22 19:13:49 +01006787 case EXPR_LSHIFT: what = "<<"; break;
6788 case EXPR_RSHIFT: what = ">>"; break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006789 default: what = "???"; break;
6790 }
6791 switch (iptr->isn_type)
6792 {
6793 case ISN_OPNR: ins = "OPNR"; break;
6794 case ISN_OPFLOAT: ins = "OPFLOAT"; break;
6795 case ISN_OPANY: ins = "OPANY"; break;
6796 default: ins = "???"; break;
6797 }
6798 smsg("%s%4d %s %s", pfx, current, ins, what);
6799 }
6800 break;
6801
6802 case ISN_COMPAREBOOL:
6803 case ISN_COMPARESPECIAL:
Bram Moolenaar7a222242022-03-01 19:23:24 +00006804 case ISN_COMPARENULL:
Bram Moolenaar4c137212021-04-19 16:48:48 +02006805 case ISN_COMPARENR:
6806 case ISN_COMPAREFLOAT:
6807 case ISN_COMPARESTRING:
6808 case ISN_COMPAREBLOB:
6809 case ISN_COMPARELIST:
6810 case ISN_COMPAREDICT:
6811 case ISN_COMPAREFUNC:
6812 case ISN_COMPAREANY:
6813 {
6814 char *p;
6815 char buf[10];
6816 char *type;
6817
6818 switch (iptr->isn_arg.op.op_type)
6819 {
6820 case EXPR_EQUAL: p = "=="; break;
6821 case EXPR_NEQUAL: p = "!="; break;
6822 case EXPR_GREATER: p = ">"; break;
6823 case EXPR_GEQUAL: p = ">="; break;
6824 case EXPR_SMALLER: p = "<"; break;
6825 case EXPR_SEQUAL: p = "<="; break;
6826 case EXPR_MATCH: p = "=~"; break;
6827 case EXPR_IS: p = "is"; break;
6828 case EXPR_ISNOT: p = "isnot"; break;
6829 case EXPR_NOMATCH: p = "!~"; break;
6830 default: p = "???"; break;
6831 }
6832 STRCPY(buf, p);
6833 if (iptr->isn_arg.op.op_ic == TRUE)
6834 strcat(buf, "?");
6835 switch(iptr->isn_type)
6836 {
6837 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
6838 case ISN_COMPARESPECIAL:
6839 type = "COMPARESPECIAL"; break;
Bram Moolenaar7a222242022-03-01 19:23:24 +00006840 case ISN_COMPARENULL: type = "COMPARENULL"; break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006841 case ISN_COMPARENR: type = "COMPARENR"; break;
6842 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
6843 case ISN_COMPARESTRING:
6844 type = "COMPARESTRING"; break;
6845 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
6846 case ISN_COMPARELIST: type = "COMPARELIST"; break;
6847 case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
6848 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
6849 case ISN_COMPAREANY: type = "COMPAREANY"; break;
6850 default: type = "???"; break;
6851 }
6852
6853 smsg("%s%4d %s %s", pfx, current, type, buf);
6854 }
6855 break;
6856
6857 case ISN_ADDLIST: smsg("%s%4d ADDLIST", pfx, current); break;
6858 case ISN_ADDBLOB: smsg("%s%4d ADDBLOB", pfx, current); break;
6859
6860 // expression operations
LemonBoy372bcce2022-04-25 12:43:20 +01006861 case ISN_CONCAT:
6862 smsg("%s%4d CONCAT size %lld", pfx, current,
6863 (varnumber_T)(iptr->isn_arg.number));
6864 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006865 case ISN_STRINDEX: smsg("%s%4d STRINDEX", pfx, current); break;
6866 case ISN_STRSLICE: smsg("%s%4d STRSLICE", pfx, current); break;
6867 case ISN_BLOBINDEX: smsg("%s%4d BLOBINDEX", pfx, current); break;
6868 case ISN_BLOBSLICE: smsg("%s%4d BLOBSLICE", pfx, current); break;
6869 case ISN_LISTAPPEND: smsg("%s%4d LISTAPPEND", pfx, current); break;
6870 case ISN_BLOBAPPEND: smsg("%s%4d BLOBAPPEND", pfx, current); break;
6871 case ISN_LISTINDEX: smsg("%s%4d LISTINDEX", pfx, current); break;
6872 case ISN_LISTSLICE: smsg("%s%4d LISTSLICE", pfx, current); break;
6873 case ISN_ANYINDEX: smsg("%s%4d ANYINDEX", pfx, current); break;
6874 case ISN_ANYSLICE: smsg("%s%4d ANYSLICE", pfx, current); break;
6875 case ISN_SLICE: smsg("%s%4d SLICE %lld",
Bram Moolenaar4f0884d2021-08-11 21:49:23 +02006876 pfx, current, iptr->isn_arg.number); break;
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02006877 case ISN_GETITEM: smsg("%s%4d ITEM %lld%s", pfx, current,
6878 iptr->isn_arg.getitem.gi_index,
6879 iptr->isn_arg.getitem.gi_with_op ?
6880 " with op" : ""); break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02006881 case ISN_MEMBER: smsg("%s%4d MEMBER", pfx, current); break;
6882 case ISN_STRINGMEMBER: smsg("%s%4d MEMBER %s", pfx, current,
6883 iptr->isn_arg.string); break;
Bram Moolenaar7ce7daf2022-12-10 18:42:12 +00006884 case ISN_GET_OBJ_MEMBER: smsg("%s%4d OBJ_MEMBER %d", pfx, current,
6885 (int)iptr->isn_arg.number); break;
6886 case ISN_STORE_THIS: smsg("%s%4d STORE_THIS %d", pfx, current,
Bram Moolenaarffdaca92022-12-09 21:41:48 +00006887 (int)iptr->isn_arg.number); break;
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02006888 case ISN_CLEARDICT: smsg("%s%4d CLEARDICT", pfx, current); break;
6889 case ISN_USEDICT: smsg("%s%4d USEDICT", pfx, current); break;
6890
Bram Moolenaar4c137212021-04-19 16:48:48 +02006891 case ISN_NEGATENR: smsg("%s%4d NEGATENR", pfx, current); break;
6892
Bram Moolenaar4c137212021-04-19 16:48:48 +02006893 case ISN_CHECKTYPE:
6894 {
Bram Moolenaarbd3a9d22022-05-17 16:12:39 +01006895 checktype_T *ct = &iptr->isn_arg.type;
Bram Moolenaarc6951a72022-12-29 20:56:24 +00006896 char *tofree = NULL;
6897 char *typename;
6898
6899 if (ct->ct_type->tt_type == VAR_FLOAT
6900 && (ct->ct_type->tt_flags & TTFLAG_NUMBER_OK))
6901 typename = "float|number";
6902 else
6903 typename = type_name(ct->ct_type, &tofree);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006904
6905 if (ct->ct_arg_idx == 0)
6906 smsg("%s%4d CHECKTYPE %s stack[%d]", pfx, current,
Bram Moolenaarc6951a72022-12-29 20:56:24 +00006907 typename,
Bram Moolenaar4c137212021-04-19 16:48:48 +02006908 (int)ct->ct_off);
6909 else
Bram Moolenaarbd3a9d22022-05-17 16:12:39 +01006910 smsg("%s%4d CHECKTYPE %s stack[%d] %s %d",
Bram Moolenaar4f0884d2021-08-11 21:49:23 +02006911 pfx, current,
Bram Moolenaarc6951a72022-12-29 20:56:24 +00006912 typename,
Bram Moolenaar4c137212021-04-19 16:48:48 +02006913 (int)ct->ct_off,
Bram Moolenaarbd3a9d22022-05-17 16:12:39 +01006914 ct->ct_is_var ? "var": "arg",
Bram Moolenaar4c137212021-04-19 16:48:48 +02006915 (int)ct->ct_arg_idx);
6916 vim_free(tofree);
6917 break;
6918 }
6919 case ISN_CHECKLEN: smsg("%s%4d CHECKLEN %s%d", pfx, current,
6920 iptr->isn_arg.checklen.cl_more_OK ? ">= " : "",
6921 iptr->isn_arg.checklen.cl_min_len);
6922 break;
6923 case ISN_SETTYPE:
6924 {
6925 char *tofree;
6926
6927 smsg("%s%4d SETTYPE %s", pfx, current,
6928 type_name(iptr->isn_arg.type.ct_type, &tofree));
6929 vim_free(tofree);
6930 break;
6931 }
6932 case ISN_COND2BOOL: smsg("%s%4d COND2BOOL", pfx, current); break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006933 case ISN_2BOOL: if (iptr->isn_arg.tobool.invert)
6934 smsg("%s%4d INVERT %d (!val)", pfx, current,
6935 iptr->isn_arg.tobool.offset);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006936 else
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006937 smsg("%s%4d 2BOOL %d (!!val)", pfx, current,
6938 iptr->isn_arg.tobool.offset);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006939 break;
6940 case ISN_2STRING: smsg("%s%4d 2STRING stack[%lld]", pfx, current,
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006941 (varnumber_T)(iptr->isn_arg.tostring.offset));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006942 break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006943 case ISN_2STRING_ANY: smsg("%s%4d 2STRING_ANY stack[%lld]",
6944 pfx, current,
6945 (varnumber_T)(iptr->isn_arg.tostring.offset));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006946 break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006947 case ISN_RANGE: smsg("%s%4d RANGE %s", pfx, current,
6948 iptr->isn_arg.string);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006949 break;
6950 case ISN_PUT:
Bram Moolenaar6ed545e2022-05-09 20:09:23 +01006951 if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE_ABOVE)
Bram Moolenaar4c137212021-04-19 16:48:48 +02006952 smsg("%s%4d PUT %c above range",
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006953 pfx, current, iptr->isn_arg.put.put_regname);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006954 else if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE)
6955 smsg("%s%4d PUT %c range",
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006956 pfx, current, iptr->isn_arg.put.put_regname);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006957 else
6958 smsg("%s%4d PUT %c %ld", pfx, current,
6959 iptr->isn_arg.put.put_regname,
6960 (long)iptr->isn_arg.put.put_lnum);
6961 break;
6962
Bram Moolenaar4c137212021-04-19 16:48:48 +02006963 case ISN_CMDMOD:
6964 {
6965 char_u *buf;
6966 size_t len = produce_cmdmods(
6967 NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
6968
6969 buf = alloc(len + 1);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02006970 if (likely(buf != NULL))
Bram Moolenaar4c137212021-04-19 16:48:48 +02006971 {
6972 (void)produce_cmdmods(
6973 buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
6974 smsg("%s%4d CMDMOD %s", pfx, current, buf);
6975 vim_free(buf);
6976 }
6977 break;
6978 }
6979 case ISN_CMDMOD_REV: smsg("%s%4d CMDMOD_REV", pfx, current); break;
6980
6981 case ISN_PROF_START:
Bram Moolenaare99d4222021-06-13 14:01:26 +02006982 smsg("%s%4d PROFILE START line %d", pfx, current,
6983 iptr->isn_lnum);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006984 break;
6985
6986 case ISN_PROF_END:
6987 smsg("%s%4d PROFILE END", pfx, current);
6988 break;
6989
Bram Moolenaare99d4222021-06-13 14:01:26 +02006990 case ISN_DEBUG:
Bram Moolenaar8cec9272021-06-23 20:20:53 +02006991 smsg("%s%4d DEBUG line %d-%d varcount %lld", pfx, current,
6992 iptr->isn_arg.debug.dbg_break_lnum + 1,
6993 iptr->isn_lnum,
6994 iptr->isn_arg.debug.dbg_var_names_len);
Bram Moolenaare99d4222021-06-13 14:01:26 +02006995 break;
6996
Bram Moolenaar4c137212021-04-19 16:48:48 +02006997 case ISN_UNPACK: smsg("%s%4d UNPACK %d%s", pfx, current,
6998 iptr->isn_arg.unpack.unp_count,
6999 iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");
7000 break;
7001 case ISN_SHUFFLE: smsg("%s%4d SHUFFLE %d up %d", pfx, current,
7002 iptr->isn_arg.shuffle.shfl_item,
7003 iptr->isn_arg.shuffle.shfl_up);
7004 break;
7005 case ISN_DROP: smsg("%s%4d DROP", pfx, current); break;
7006
7007 case ISN_FINISH: // End of list of instructions for ISN_SUBSTITUTE.
7008 return;
7009 }
7010
7011 out_flush(); // output one line at a time
7012 ui_breakcheck();
7013 if (got_int)
7014 break;
7015 }
7016}
7017
7018/*
Bram Moolenaar4ee9d8e2021-06-13 18:38:48 +02007019 * Handle command line completion for the :disassemble command.
7020 */
7021 void
7022set_context_in_disassemble_cmd(expand_T *xp, char_u *arg)
7023{
7024 char_u *p;
7025
7026 // Default: expand user functions, "debug" and "profile"
7027 xp->xp_context = EXPAND_DISASSEMBLE;
7028 xp->xp_pattern = arg;
7029
7030 // first argument already typed: only user function names
7031 if (*arg != NUL && *(p = skiptowhite(arg)) != NUL)
7032 {
7033 xp->xp_context = EXPAND_USER_FUNC;
7034 xp->xp_pattern = skipwhite(p);
7035 }
7036}
7037
7038/*
7039 * Function given to ExpandGeneric() to obtain the list of :disassemble
7040 * arguments.
7041 */
7042 char_u *
7043get_disassemble_argument(expand_T *xp, int idx)
7044{
7045 if (idx == 0)
7046 return (char_u *)"debug";
7047 if (idx == 1)
7048 return (char_u *)"profile";
7049 return get_user_func_name(xp, idx - 2);
7050}
7051
7052/*
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01007053 * ":disassemble".
Bram Moolenaar777770f2020-02-06 21:27:08 +01007054 * We don't really need this at runtime, but we do have tests that require it,
7055 * so always include this.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007056 */
7057 void
7058ex_disassemble(exarg_T *eap)
7059{
Bram Moolenaar21456cd2020-02-13 21:29:32 +01007060 char_u *arg = eap->arg;
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01007061 ufunc_T *ufunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007062 dfunc_T *dfunc;
Bram Moolenaardafef512022-05-21 21:55:55 +01007063 isn_T *instr = NULL; // init to shut up gcc warning
7064 int instr_count = 0; // init to shut up gcc warning
Bram Moolenaar5a01caa2022-05-21 18:56:58 +01007065 compiletype_T compile_type = CT_NONE;
Bram Moolenaare99d4222021-06-13 14:01:26 +02007066
Bram Moolenaarf79d9dd2022-05-21 15:39:02 +01007067 ufunc = find_func_by_name(arg, &compile_type);
Bram Moolenaara26b9702020-04-18 19:53:28 +02007068 if (ufunc == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007069 return;
Bram Moolenaare99d4222021-06-13 14:01:26 +02007070 if (func_needs_compiling(ufunc, compile_type)
7071 && compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02007072 return;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007073 if (ufunc->uf_def_status != UF_COMPILED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007074 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02007075 semsg(_(e_function_is_not_compiled_str), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007076 return;
7077 }
Bram Moolenaar6db660b2021-08-01 14:08:54 +02007078 msg((char *)printable_func_name(ufunc));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007079
7080 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
Bram Moolenaare99d4222021-06-13 14:01:26 +02007081 switch (compile_type)
7082 {
7083 case CT_PROFILE:
Bram Moolenaarf002a412021-01-24 13:34:18 +01007084#ifdef FEAT_PROFILE
Bram Moolenaare99d4222021-06-13 14:01:26 +02007085 instr = dfunc->df_instr_prof;
7086 instr_count = dfunc->df_instr_prof_count;
7087 break;
Bram Moolenaarf002a412021-01-24 13:34:18 +01007088#endif
Bram Moolenaare99d4222021-06-13 14:01:26 +02007089 // FALLTHROUGH
7090 case CT_NONE:
7091 instr = dfunc->df_instr;
7092 instr_count = dfunc->df_instr_count;
7093 break;
7094 case CT_DEBUG:
7095 instr = dfunc->df_instr_debug;
7096 instr_count = dfunc->df_instr_debug_count;
7097 break;
7098 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007099
Bram Moolenaar4c137212021-04-19 16:48:48 +02007100 list_instructions("", instr, instr_count, ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007101}
7102
7103/*
Bram Moolenaar13106602020-10-04 16:06:05 +02007104 * Return TRUE when "tv" is not falsy: non-zero, non-empty string, non-empty
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007105 * list, etc. Mostly like what JavaScript does, except that empty list and
7106 * empty dictionary are FALSE.
7107 */
7108 int
7109tv2bool(typval_T *tv)
7110{
7111 switch (tv->v_type)
7112 {
7113 case VAR_NUMBER:
7114 return tv->vval.v_number != 0;
7115 case VAR_FLOAT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007116 return tv->vval.v_float != 0.0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007117 case VAR_PARTIAL:
7118 return tv->vval.v_partial != NULL;
7119 case VAR_FUNC:
7120 case VAR_STRING:
7121 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
7122 case VAR_LIST:
7123 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
7124 case VAR_DICT:
7125 return tv->vval.v_dict != NULL
7126 && tv->vval.v_dict->dv_hashtab.ht_used > 0;
7127 case VAR_BOOL:
7128 case VAR_SPECIAL:
7129 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
7130 case VAR_JOB:
7131#ifdef FEAT_JOB_CHANNEL
7132 return tv->vval.v_job != NULL;
7133#else
7134 break;
7135#endif
7136 case VAR_CHANNEL:
7137#ifdef FEAT_JOB_CHANNEL
7138 return tv->vval.v_channel != NULL;
7139#else
7140 break;
7141#endif
7142 case VAR_BLOB:
7143 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
7144 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02007145 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007146 case VAR_VOID:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02007147 case VAR_INSTR:
Bram Moolenaar00b28d62022-12-08 15:32:33 +00007148 case VAR_CLASS:
7149 case VAR_OBJECT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007150 break;
7151 }
7152 return FALSE;
7153}
7154
Bram Moolenaarea2d4072020-11-12 12:08:51 +01007155 void
7156emsg_using_string_as(typval_T *tv, int as_number)
7157{
7158 semsg(_(as_number ? e_using_string_as_number_str
7159 : e_using_string_as_bool_str),
7160 tv->vval.v_string == NULL
7161 ? (char_u *)"" : tv->vval.v_string);
7162}
7163
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007164/*
7165 * If "tv" is a string give an error and return FAIL.
7166 */
7167 int
7168check_not_string(typval_T *tv)
7169{
7170 if (tv->v_type == VAR_STRING)
7171 {
Bram Moolenaarea2d4072020-11-12 12:08:51 +01007172 emsg_using_string_as(tv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007173 clear_tv(tv);
7174 return FAIL;
7175 }
7176 return OK;
7177}
7178
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007179
7180#endif // FEAT_EVAL