blob: 2d6a3feadd54d2c4b3d891ed32d8b1fc2c2782f0 [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
67// 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)
74
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 Moolenaar8a7d6542020-01-26 15:56:19 +0100104// Get pointer to item relative to the bottom of the stack, -1 is the last one.
Bram Moolenaar11107ba2020-08-15 21:10:16 +0200105#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 +0100106
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200107 void
108to_string_error(vartype_T vartype)
109{
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200110 semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype));
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200111}
112
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100113/*
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100114 * Return the number of arguments, including optional arguments and any vararg.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100115 */
116 static int
117ufunc_argcount(ufunc_T *ufunc)
118{
119 return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0);
120}
121
122/*
Bram Moolenaarfe270812020-04-11 22:31:27 +0200123 * Create a new list from "count" items at the bottom of the stack.
124 * When "count" is zero an empty list is added to the stack.
125 */
126 static int
127exe_newlist(int count, ectx_T *ectx)
128{
129 list_T *list = list_alloc_with_items(count);
130 int idx;
131 typval_T *tv;
132
133 if (list == NULL)
134 return FAIL;
135 for (idx = 0; idx < count; ++idx)
136 list_set_item(list, idx, STACK_TV_BOT(idx - count));
137
138 if (count > 0)
139 ectx->ec_stack.ga_len -= count - 1;
Bram Moolenaar35578162021-08-02 19:10:38 +0200140 else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarfe270812020-04-11 22:31:27 +0200141 return FAIL;
142 else
143 ++ectx->ec_stack.ga_len;
144 tv = STACK_TV_BOT(-1);
145 tv->v_type = VAR_LIST;
146 tv->vval.v_list = list;
147 ++list->lv_refcount;
148 return OK;
149}
150
151/*
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200152 * If debug_tick changed check if "ufunc" has a breakpoint and update
153 * "uf_has_breakpoint".
154 */
Bram Moolenaar96923b72022-03-15 15:57:04 +0000155 void
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200156update_has_breakpoint(ufunc_T *ufunc)
157{
158 if (ufunc->uf_debug_tick != debug_tick)
159 {
160 linenr_T breakpoint;
161
162 ufunc->uf_debug_tick = debug_tick;
163 breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name, 0);
164 ufunc->uf_has_breakpoint = breakpoint > 0;
165 }
166}
167
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +0200168static garray_T dict_stack = GA_EMPTY;
169
170/*
171 * Put a value on the dict stack. This consumes "tv".
172 */
173 static int
174dict_stack_save(typval_T *tv)
175{
176 if (dict_stack.ga_growsize == 0)
Bram Moolenaar04935fb2022-01-08 16:19:22 +0000177 ga_init2(&dict_stack, sizeof(typval_T), 10);
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +0200178 if (ga_grow(&dict_stack, 1) == FAIL)
179 return FAIL;
180 ((typval_T *)dict_stack.ga_data)[dict_stack.ga_len] = *tv;
181 ++dict_stack.ga_len;
182 return OK;
183}
184
185/*
186 * Get the typval at top of the dict stack.
187 */
188 static typval_T *
189dict_stack_get_tv(void)
190{
191 if (dict_stack.ga_len == 0)
192 return NULL;
193 return ((typval_T *)dict_stack.ga_data) + dict_stack.ga_len - 1;
194}
195
196/*
197 * Get the dict at top of the dict stack.
198 */
199 static dict_T *
200dict_stack_get_dict(void)
201{
202 typval_T *tv;
203
204 if (dict_stack.ga_len == 0)
205 return NULL;
206 tv = ((typval_T *)dict_stack.ga_data) + dict_stack.ga_len - 1;
207 if (tv->v_type == VAR_DICT)
208 return tv->vval.v_dict;
209 return NULL;
210}
211
212/*
213 * Drop an item from the dict stack.
214 */
215 static void
216dict_stack_drop(void)
217{
218 if (dict_stack.ga_len == 0)
219 {
220 iemsg("Dict stack underflow");
221 return;
222 }
223 --dict_stack.ga_len;
224 clear_tv(((typval_T *)dict_stack.ga_data) + dict_stack.ga_len);
225}
226
227/*
228 * Drop items from the dict stack until the length is equal to "len".
229 */
230 static void
231dict_stack_clear(int len)
232{
233 while (dict_stack.ga_len > len)
234 dict_stack_drop();
235}
236
Bram Moolenaar4f8f5422021-06-20 19:28:14 +0200237/*
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +0000238 * Get a pointer to useful "pt_outer" of "pt".
239 */
240 static outer_T *
241get_pt_outer(partial_T *pt)
242{
243 partial_T *ptref = pt->pt_outer_partial;
244
245 if (ptref == NULL)
246 return &pt->pt_outer;
247
248 // partial using partial (recursively)
249 while (ptref->pt_outer_partial != NULL)
250 ptref = ptref->pt_outer_partial;
251 return &ptref->pt_outer;
252}
253
254/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100255 * Call compiled function "cdf_idx" from compiled code.
Bram Moolenaarab360522021-01-10 14:02:28 +0100256 * This adds a stack frame and sets the instruction pointer to the start of the
257 * called function.
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200258 * If "pt" is not null use "pt->pt_outer" for ec_outer_ref->or_outer.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100259 *
260 * Stack has:
261 * - current arguments (already there)
262 * - omitted optional argument (default values) added here
263 * - stack frame:
264 * - pointer to calling function
265 * - Index of next instruction in calling function
266 * - previous frame pointer
267 * - reserved space for local variables
268 */
269 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100270call_dfunc(
271 int cdf_idx,
272 partial_T *pt,
273 int argcount_arg,
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100274 ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100275{
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100276 int argcount = argcount_arg;
277 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
278 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200279 int did_emsg_before = did_emsg_cumul + did_emsg;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100280 int arg_to_add;
281 int vararg_count = 0;
282 int varcount;
283 int idx;
284 estack_T *entry;
285 funclocal_T *floc = NULL;
Bram Moolenaar648594e2021-07-11 17:55:01 +0200286 int res = OK;
Bram Moolenaar139575d2022-03-15 19:29:30 +0000287 compiletype_T compile_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100288
289 if (dfunc->df_deleted)
290 {
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100291 // don't use ufunc->uf_name, it may have been freed
Bram Moolenaar460ae5d2022-01-01 14:19:49 +0000292 emsg_funcname(e_function_was_deleted_str,
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100293 dfunc->df_name == NULL ? (char_u *)"unknown" : dfunc->df_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100294 return FAIL;
295 }
296
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100297#ifdef FEAT_PROFILE
Bram Moolenaar12d26532021-02-19 19:13:21 +0100298 if (do_profiling == PROF_YES)
299 {
Bram Moolenaar35578162021-08-02 19:10:38 +0200300 if (GA_GROW_OK(&profile_info_ga, 1))
Bram Moolenaar12d26532021-02-19 19:13:21 +0100301 {
302 profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data)
303 + profile_info_ga.ga_len;
304 ++profile_info_ga.ga_len;
305 CLEAR_POINTER(info);
306 profile_may_start_func(info, ufunc,
307 (((dfunc_T *)def_functions.ga_data)
308 + ectx->ec_dfunc_idx)->df_ufunc);
309 }
Bram Moolenaar12d26532021-02-19 19:13:21 +0100310 }
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100311#endif
312
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200313 // When debugging and using "cont" switches to the not-debugged
314 // instructions, may need to still compile them.
Bram Moolenaar139575d2022-03-15 19:29:30 +0000315 compile_type = get_compile_type(ufunc);
316 if (func_needs_compiling(ufunc, compile_type))
Bram Moolenaar648594e2021-07-11 17:55:01 +0200317 {
Bram Moolenaar139575d2022-03-15 19:29:30 +0000318 res = compile_def_function(ufunc, FALSE, compile_type, NULL);
Bram Moolenaar648594e2021-07-11 17:55:01 +0200319
320 // compile_def_function() may cause def_functions.ga_data to change
321 dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
322 }
323 if (res == FAIL || INSTRUCTIONS(dfunc) == NULL)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +0200324 {
325 if (did_emsg_cumul + did_emsg == did_emsg_before)
326 semsg(_(e_function_is_not_compiled_str),
327 printable_func_name(ufunc));
328 return FAIL;
329 }
330
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200331 if (ufunc->uf_va_name != NULL)
332 {
Bram Moolenaarfe270812020-04-11 22:31:27 +0200333 // Need to make a list out of the vararg arguments.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200334 // Stack at time of call with 2 varargs:
335 // normal_arg
336 // optional_arg
337 // vararg_1
338 // vararg_2
Bram Moolenaarfe270812020-04-11 22:31:27 +0200339 // After creating the list:
340 // normal_arg
341 // optional_arg
342 // vararg-list
343 // With missing optional arguments we get:
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200344 // normal_arg
Bram Moolenaarfe270812020-04-11 22:31:27 +0200345 // After creating the list
346 // normal_arg
347 // (space for optional_arg)
348 // vararg-list
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200349 vararg_count = argcount - ufunc->uf_args.ga_len;
350 if (vararg_count < 0)
351 vararg_count = 0;
352 else
353 argcount -= vararg_count;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200354 if (exe_newlist(vararg_count, ectx) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200355 return FAIL;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200356
357 vararg_count = 1;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200358 }
359
Bram Moolenaarfe270812020-04-11 22:31:27 +0200360 arg_to_add = ufunc->uf_args.ga_len - argcount;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200361 if (arg_to_add < 0)
362 {
Bram Moolenaar79e8db92020-08-14 22:16:33 +0200363 if (arg_to_add == -1)
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200364 emsg(_(e_one_argument_too_many));
Bram Moolenaar79e8db92020-08-14 22:16:33 +0200365 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200366 semsg(_(e_nr_arguments_too_many), -arg_to_add);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200367 return FAIL;
368 }
Bram Moolenaarcd1cda22022-02-16 21:48:25 +0000369 else if (arg_to_add > ufunc->uf_def_args.ga_len)
370 {
371 int missing = arg_to_add - ufunc->uf_def_args.ga_len;
372
373 if (missing == 1)
374 emsg(_(e_one_argument_too_few));
375 else
376 semsg(_(e_nr_arguments_too_few), missing);
377 return FAIL;
378 }
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200379
380 // Reserve space for:
381 // - missing arguments
382 // - stack frame
383 // - local variables
384 // - if needed: a counter for number of closures created in
385 // ectx->ec_funcrefs.
386 varcount = dfunc->df_varcount + dfunc->df_has_closure;
Bram Moolenaar35578162021-08-02 19:10:38 +0200387 if (GA_GROW_FAILS(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE + varcount))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100388 return FAIL;
389
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100390 // If depth of calling is getting too high, don't execute the function.
391 if (funcdepth_increment() == FAIL)
392 return FAIL;
Bram Moolenaare99d4222021-06-13 14:01:26 +0200393 ++ex_nesting_level;
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100394
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100395 // Only make a copy of funclocal if it contains something to restore.
Bram Moolenaar4c137212021-04-19 16:48:48 +0200396 if (ectx->ec_funclocal.floc_restore_cmdmod)
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100397 {
398 floc = ALLOC_ONE(funclocal_T);
399 if (floc == NULL)
400 return FAIL;
Bram Moolenaar4c137212021-04-19 16:48:48 +0200401 *floc = ectx->ec_funclocal;
402 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100403 }
404
Bram Moolenaarfe270812020-04-11 22:31:27 +0200405 // Move the vararg-list to below the missing optional arguments.
406 if (vararg_count > 0 && arg_to_add > 0)
407 *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100408
409 // Reserve space for omitted optional arguments, filled in soon.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200410 for (idx = 0; idx < arg_to_add; ++idx)
Bram Moolenaarfe270812020-04-11 22:31:27 +0200411 STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200412 ectx->ec_stack.ga_len += arg_to_add;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100413
414 // Store current execution state in stack frame for ISN_RETURN.
Bram Moolenaar0186e582021-01-10 18:33:11 +0100415 STACK_TV_BOT(STACK_FRAME_FUNC_OFF)->vval.v_number = ectx->ec_dfunc_idx;
416 STACK_TV_BOT(STACK_FRAME_IIDX_OFF)->vval.v_number = ectx->ec_iidx;
Bram Moolenaar5930ddc2021-04-26 20:32:59 +0200417 STACK_TV_BOT(STACK_FRAME_INSTR_OFF)->vval.v_string = (void *)ectx->ec_instr;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200418 STACK_TV_BOT(STACK_FRAME_OUTER_OFF)->vval.v_string =
419 (void *)ectx->ec_outer_ref;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100420 STACK_TV_BOT(STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string = (void *)floc;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100421 STACK_TV_BOT(STACK_FRAME_IDX_OFF)->vval.v_number = ectx->ec_frame_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200422 ectx->ec_frame_idx = ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100423
424 // Initialize local variables
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200425 for (idx = 0; idx < dfunc->df_varcount; ++idx)
Bram Moolenaar5cd64792021-12-25 18:23:24 +0000426 {
427 typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + idx);
428
429 tv->v_type = VAR_NUMBER;
430 tv->vval.v_number = 0;
431 }
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200432 if (dfunc->df_has_closure)
433 {
434 typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + dfunc->df_varcount);
435
436 tv->v_type = VAR_NUMBER;
437 tv->vval.v_number = 0;
438 }
439 ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100440
Bram Moolenaar0d3de8c2021-01-22 20:46:27 +0100441 if (pt != NULL || ufunc->uf_partial != NULL
442 || (ufunc->uf_flags & FC_CLOSURE))
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100443 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200444 outer_ref_T *ref = ALLOC_CLEAR_ONE(outer_ref_T);
Bram Moolenaar0186e582021-01-10 18:33:11 +0100445
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200446 if (ref == NULL)
Bram Moolenaar0186e582021-01-10 18:33:11 +0100447 return FAIL;
448 if (pt != NULL)
449 {
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +0000450 ref->or_outer = get_pt_outer(pt);
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200451 ++pt->pt_refcount;
452 ref->or_partial = pt;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100453 }
454 else if (ufunc->uf_partial != NULL)
455 {
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +0000456 ref->or_outer = get_pt_outer(ufunc->uf_partial);
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200457 ++ufunc->uf_partial->pt_refcount;
458 ref->or_partial = ufunc->uf_partial;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100459 }
460 else
461 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200462 ref->or_outer = ALLOC_CLEAR_ONE(outer_T);
Dominique Pelle5a9e5842021-07-24 19:32:12 +0200463 if (unlikely(ref->or_outer == NULL))
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200464 {
465 vim_free(ref);
466 return FAIL;
467 }
468 ref->or_outer_allocated = TRUE;
469 ref->or_outer->out_stack = &ectx->ec_stack;
470 ref->or_outer->out_frame_idx = ectx->ec_frame_idx;
471 if (ectx->ec_outer_ref != NULL)
472 ref->or_outer->out_up = ectx->ec_outer_ref->or_outer;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100473 }
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200474 ectx->ec_outer_ref = ref;
Bram Moolenaarab360522021-01-10 14:02:28 +0100475 }
Bram Moolenaar0186e582021-01-10 18:33:11 +0100476 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200477 ectx->ec_outer_ref = NULL;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +0100478
Bram Moolenaarc970e422021-03-17 15:03:04 +0100479 ++ufunc->uf_calls;
480
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100481 // Set execution state to the start of the called function.
482 ectx->ec_dfunc_idx = cdf_idx;
Bram Moolenaare5ea3462021-01-25 21:01:48 +0100483 ectx->ec_instr = INSTRUCTIONS(dfunc);
Bram Moolenaarb2049902021-01-24 12:53:53 +0100484 entry = estack_push_ufunc(ufunc, 1);
Bram Moolenaarc620c052020-07-08 15:16:19 +0200485 if (entry != NULL)
486 {
487 // Set the script context to the script where the function was defined.
Bram Moolenaarc70fe462021-04-17 17:59:19 +0200488 // Save the current context so it can be restored on return.
489 entry->es_save_sctx = current_sctx;
490 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaarc620c052020-07-08 15:16:19 +0200491 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100492
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +0200493 // Start execution at the first instruction.
494 ectx->ec_iidx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100495
496 return OK;
497}
498
499// Get pointer to item in the stack.
500#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
501
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000502// Double linked list of funcstack_T in use.
503static funcstack_T *first_funcstack = NULL;
504
505 static void
506add_funcstack_to_list(funcstack_T *funcstack)
507{
508 // Link in list of funcstacks.
509 if (first_funcstack != NULL)
510 first_funcstack->fs_prev = funcstack;
511 funcstack->fs_next = first_funcstack;
512 funcstack->fs_prev = NULL;
513 first_funcstack = funcstack;
514}
515
516 static void
517remove_funcstack_from_list(funcstack_T *funcstack)
518{
519 if (funcstack->fs_prev == NULL)
520 first_funcstack = funcstack->fs_next;
521 else
522 funcstack->fs_prev->fs_next = funcstack->fs_next;
523 if (funcstack->fs_next != NULL)
524 funcstack->fs_next->fs_prev = funcstack->fs_prev;
525}
526
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100527/*
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200528 * Used when returning from a function: Check if any closure is still
529 * referenced. If so then move the arguments and variables to a separate piece
530 * of stack to be used when the closure is called.
531 * When "free_arguments" is TRUE the arguments are to be freed.
532 * Returns FAIL when out of memory.
533 */
534 static int
535handle_closure_in_use(ectx_T *ectx, int free_arguments)
536{
537 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
538 + ectx->ec_dfunc_idx;
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200539 int argcount;
540 int top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200541 int idx;
542 typval_T *tv;
543 int closure_in_use = FALSE;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200544 garray_T *gap = &ectx->ec_funcrefs;
545 varnumber_T closure_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200546
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200547 if (dfunc->df_ufunc == NULL)
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200548 return OK; // function was freed
549 if (dfunc->df_has_closure == 0)
550 return OK; // no closures
551 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + dfunc->df_varcount);
552 closure_count = tv->vval.v_number;
553 if (closure_count == 0)
554 return OK; // no funcrefs created
555
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200556 argcount = ufunc_argcount(dfunc->df_ufunc);
557 top = ectx->ec_frame_idx - argcount;
558
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200559 // Check if any created closure is still in use.
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200560 for (idx = 0; idx < closure_count; ++idx)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200561 {
Bram Moolenaarc70bdab2020-09-26 19:59:38 +0200562 partial_T *pt;
563 int off = gap->ga_len - closure_count + idx;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200564
Bram Moolenaarc70bdab2020-09-26 19:59:38 +0200565 if (off < 0)
566 continue; // count is off or already done
567 pt = ((partial_T **)gap->ga_data)[off];
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200568 if (pt->pt_refcount > 1)
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200569 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200570 int refcount = pt->pt_refcount;
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200571 int i;
572
Dominique Pelleaf4a61a2021-12-27 17:21:41 +0000573 // A Reference in a local variable doesn't count, it gets
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200574 // unreferenced on return.
575 for (i = 0; i < dfunc->df_varcount; ++i)
576 {
577 typval_T *stv = STACK_TV(ectx->ec_frame_idx
578 + STACK_FRAME_SIZE + i);
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200579 if (stv->v_type == VAR_PARTIAL && pt == stv->vval.v_partial)
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200580 --refcount;
581 }
582 if (refcount > 1)
583 {
584 closure_in_use = TRUE;
585 break;
586 }
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200587 }
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200588 }
589
590 if (closure_in_use)
591 {
592 funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T);
593 typval_T *stack;
594
595 // A closure is using the arguments and/or local variables.
596 // Move them to the called function.
597 if (funcstack == NULL)
598 return FAIL;
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000599
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200600 funcstack->fs_var_offset = argcount + STACK_FRAME_SIZE;
601 funcstack->fs_ga.ga_len = funcstack->fs_var_offset + dfunc->df_varcount;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200602 stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len);
603 funcstack->fs_ga.ga_data = stack;
604 if (stack == NULL)
605 {
606 vim_free(funcstack);
607 return FAIL;
608 }
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000609 add_funcstack_to_list(funcstack);
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200610
611 // Move or copy the arguments.
612 for (idx = 0; idx < argcount; ++idx)
613 {
614 tv = STACK_TV(top + idx);
615 if (free_arguments)
616 {
617 *(stack + idx) = *tv;
618 tv->v_type = VAR_UNKNOWN;
619 }
620 else
621 copy_tv(tv, stack + idx);
622 }
623 // Move the local variables.
624 for (idx = 0; idx < dfunc->df_varcount; ++idx)
625 {
626 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx);
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200627
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200628 // A partial created for a local function, that is also used as a
629 // local variable, has a reference count for the variable, thus
630 // will never go down to zero. When all these refcounts are one
631 // then the funcstack is unused. We need to count how many we have
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000632 // so we know when to check.
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200633 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
634 {
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200635 int i;
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200636
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200637 for (i = 0; i < closure_count; ++i)
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200638 if (tv->vval.v_partial == ((partial_T **)gap->ga_data)[
639 gap->ga_len - closure_count + i])
640 ++funcstack->fs_min_refcount;
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200641 }
642
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200643 *(stack + funcstack->fs_var_offset + idx) = *tv;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200644 tv->v_type = VAR_UNKNOWN;
645 }
646
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200647 for (idx = 0; idx < closure_count; ++idx)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200648 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200649 partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len
650 - closure_count + idx];
651 if (pt->pt_refcount > 1)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200652 {
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200653 ++funcstack->fs_refcount;
654 pt->pt_funcstack = funcstack;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100655 pt->pt_outer.out_stack = &funcstack->fs_ga;
656 pt->pt_outer.out_frame_idx = ectx->ec_frame_idx - top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200657 }
658 }
659 }
660
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200661 for (idx = 0; idx < closure_count; ++idx)
662 partial_unref(((partial_T **)gap->ga_data)[gap->ga_len
663 - closure_count + idx]);
664 gap->ga_len -= closure_count;
665 if (gap->ga_len == 0)
666 ga_clear(gap);
667
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200668 return OK;
669}
670
671/*
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200672 * Called when a partial is freed or its reference count goes down to one. The
673 * funcstack may be the only reference to the partials in the local variables.
674 * Go over all of them, the funcref and can be freed if all partials
675 * referencing the funcstack have a reference count of one.
676 */
677 void
678funcstack_check_refcount(funcstack_T *funcstack)
679{
680 int i;
681 garray_T *gap = &funcstack->fs_ga;
682 int done = 0;
683
684 if (funcstack->fs_refcount > funcstack->fs_min_refcount)
685 return;
686 for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i)
687 {
688 typval_T *tv = ((typval_T *)gap->ga_data) + i;
689
690 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL
691 && tv->vval.v_partial->pt_funcstack == funcstack
692 && tv->vval.v_partial->pt_refcount == 1)
693 ++done;
694 }
695 if (done == funcstack->fs_min_refcount)
696 {
697 typval_T *stack = gap->ga_data;
698
699 // All partials referencing the funcstack have a reference count of
700 // one, thus the funcstack is no longer of use.
701 for (i = 0; i < gap->ga_len; ++i)
702 clear_tv(stack + i);
703 vim_free(stack);
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000704 remove_funcstack_from_list(funcstack);
Bram Moolenaar85d5e2b2020-10-10 14:13:01 +0200705 vim_free(funcstack);
706 }
707}
708
709/*
Bram Moolenaar7509ad82021-12-14 18:14:37 +0000710 * For garbage collecting: set references in all variables referenced by
711 * all funcstacks.
712 */
713 int
714set_ref_in_funcstacks(int copyID)
715{
716 funcstack_T *funcstack;
717
718 for (funcstack = first_funcstack; funcstack != NULL;
719 funcstack = funcstack->fs_next)
720 {
721 typval_T *stack = funcstack->fs_ga.ga_data;
722 int i;
723
724 for (i = 0; i < funcstack->fs_ga.ga_len; ++i)
725 if (set_ref_in_item(stack + i, copyID, NULL, NULL))
726 return TRUE; // abort
727 }
728 return FALSE;
729}
730
731/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100732 * Return from the current function.
733 */
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200734 static int
Bram Moolenaar4c137212021-04-19 16:48:48 +0200735func_return(ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100736{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100737 int idx;
Bram Moolenaar34c54eb2020-11-25 19:15:19 +0100738 int ret_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200739 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
740 + ectx->ec_dfunc_idx;
741 int argcount = ufunc_argcount(dfunc->df_ufunc);
742 int top = ectx->ec_frame_idx - argcount;
Bram Moolenaarc620c052020-07-08 15:16:19 +0200743 estack_T *entry;
Bram Moolenaar12d26532021-02-19 19:13:21 +0100744 int prev_dfunc_idx = STACK_TV(ectx->ec_frame_idx
745 + STACK_FRAME_FUNC_OFF)->vval.v_number;
Bram Moolenaarb06b50d2021-04-26 21:39:25 +0200746 funclocal_T *floc;
747#ifdef FEAT_PROFILE
Bram Moolenaar12d26532021-02-19 19:13:21 +0100748 dfunc_T *prev_dfunc = ((dfunc_T *)def_functions.ga_data)
749 + prev_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100750
Bram Moolenaar12d26532021-02-19 19:13:21 +0100751 if (do_profiling == PROF_YES)
752 {
753 ufunc_T *caller = prev_dfunc->df_ufunc;
754
755 if (dfunc->df_ufunc->uf_profiling
756 || (caller != NULL && caller->uf_profiling))
757 {
758 profile_may_end_func(((profinfo_T *)profile_info_ga.ga_data)
759 + profile_info_ga.ga_len - 1, dfunc->df_ufunc, caller);
760 --profile_info_ga.ga_len;
761 }
762 }
763#endif
Bram Moolenaar919c12c2021-12-14 14:29:16 +0000764
765 // No check for uf_refcount being zero, cannot think of a way that would
766 // happen.
Bram Moolenaarc970e422021-03-17 15:03:04 +0100767 --dfunc->df_ufunc->uf_calls;
768
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100769 // execution context goes one level up
Bram Moolenaarc620c052020-07-08 15:16:19 +0200770 entry = estack_pop();
771 if (entry != NULL)
Bram Moolenaarc70fe462021-04-17 17:59:19 +0200772 current_sctx = entry->es_save_sctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100773
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200774 if (handle_closure_in_use(ectx, TRUE) == FAIL)
775 return FAIL;
776
777 // Clear the arguments.
778 for (idx = top; idx < ectx->ec_frame_idx; ++idx)
779 clear_tv(STACK_TV(idx));
780
781 // Clear local variables and temp values, but not the return value.
782 for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100783 idx < ectx->ec_stack.ga_len - 1; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100784 clear_tv(STACK_TV(idx));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100785
Bram Moolenaar34c54eb2020-11-25 19:15:19 +0100786 // The return value should be on top of the stack. However, when aborting
787 // it may not be there and ec_frame_idx is the top of the stack.
788 ret_idx = ectx->ec_stack.ga_len - 1;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100789 if (ret_idx == ectx->ec_frame_idx + STACK_FRAME_IDX_OFF)
Bram Moolenaar34c54eb2020-11-25 19:15:19 +0100790 ret_idx = 0;
791
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200792 if (ectx->ec_outer_ref != NULL)
793 {
794 if (ectx->ec_outer_ref->or_outer_allocated)
795 vim_free(ectx->ec_outer_ref->or_outer);
796 partial_unref(ectx->ec_outer_ref->or_partial);
797 vim_free(ectx->ec_outer_ref);
798 }
Bram Moolenaar0186e582021-01-10 18:33:11 +0100799
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100800 // Restore the previous frame.
Bram Moolenaar12d26532021-02-19 19:13:21 +0100801 ectx->ec_dfunc_idx = prev_dfunc_idx;
Bram Moolenaar0186e582021-01-10 18:33:11 +0100802 ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx
803 + STACK_FRAME_IIDX_OFF)->vval.v_number;
Bram Moolenaar5930ddc2021-04-26 20:32:59 +0200804 ectx->ec_instr = (void *)STACK_TV(ectx->ec_frame_idx
805 + STACK_FRAME_INSTR_OFF)->vval.v_string;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200806 ectx->ec_outer_ref = (void *)STACK_TV(ectx->ec_frame_idx
Bram Moolenaar0186e582021-01-10 18:33:11 +0100807 + STACK_FRAME_OUTER_OFF)->vval.v_string;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100808 floc = (void *)STACK_TV(ectx->ec_frame_idx
809 + STACK_FRAME_FUNCLOCAL_OFF)->vval.v_string;
Bram Moolenaar5366e1a2020-10-01 13:01:34 +0200810 // restoring ec_frame_idx must be last
Bram Moolenaar0186e582021-01-10 18:33:11 +0100811 ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx
812 + STACK_FRAME_IDX_OFF)->vval.v_number;
Bram Moolenaard386e922021-04-25 14:48:49 +0200813
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100814 if (floc == NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +0200815 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100816 else
817 {
Bram Moolenaar4c137212021-04-19 16:48:48 +0200818 ectx->ec_funclocal = *floc;
Bram Moolenaar2fecb532021-03-24 22:00:56 +0100819 vim_free(floc);
820 }
821
Bram Moolenaar34c54eb2020-11-25 19:15:19 +0100822 if (ret_idx > 0)
823 {
824 // Reset the stack to the position before the call, with a spot for the
825 // return value, moved there from above the frame.
826 ectx->ec_stack.ga_len = top + 1;
827 *STACK_TV_BOT(-1) = *STACK_TV(ret_idx);
828 }
829 else
830 // Reset the stack to the position before the call.
831 ectx->ec_stack.ga_len = top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200832
Bram Moolenaar0ba48e82020-11-17 18:23:19 +0100833 funcdepth_decrement();
Bram Moolenaare99d4222021-06-13 14:01:26 +0200834 --ex_nesting_level;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200835 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100836}
837
838#undef STACK_TV
839
840/*
841 * Prepare arguments and rettv for calling a builtin or user function.
842 */
843 static int
844call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
845{
846 int idx;
847 typval_T *tv;
848
849 // Move arguments from bottom of the stack to argvars[] and add terminator.
850 for (idx = 0; idx < argcount; ++idx)
851 argvars[idx] = *STACK_TV_BOT(idx - argcount);
852 argvars[argcount].v_type = VAR_UNKNOWN;
853
854 // Result replaces the arguments on the stack.
855 if (argcount > 0)
856 ectx->ec_stack.ga_len -= argcount - 1;
Bram Moolenaar35578162021-08-02 19:10:38 +0200857 else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100858 return FAIL;
859 else
860 ++ectx->ec_stack.ga_len;
861
862 // Default return value is zero.
863 tv = STACK_TV_BOT(-1);
864 tv->v_type = VAR_NUMBER;
865 tv->vval.v_number = 0;
866
867 return OK;
868}
869
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200870// Ugly global to avoid passing the execution context around through many
871// layers.
872static ectx_T *current_ectx = NULL;
873
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100874/*
875 * Call a builtin function by index.
876 */
877 static int
878call_bfunc(int func_idx, int argcount, ectx_T *ectx)
879{
880 typval_T argvars[MAX_FUNC_ARGS];
881 int idx;
Bram Moolenaar171fb922020-10-28 16:54:47 +0100882 int did_emsg_before = did_emsg;
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200883 ectx_T *prev_ectx = current_ectx;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +0200884 char *save_func_name = ectx->ec_where.wt_func_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100885
886 if (call_prepare(argcount, argvars, ectx) == FAIL)
887 return FAIL;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +0200888 ectx->ec_where.wt_func_name = internal_func_name(func_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100889
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200890 // Call the builtin function. Set "current_ectx" so that when it
891 // recursively invokes call_def_function() a closure context can be set.
892 current_ectx = ectx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100893 call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1));
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200894 current_ectx = prev_ectx;
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +0200895 ectx->ec_where.wt_func_name = save_func_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100896
897 // Clear the arguments.
898 for (idx = 0; idx < argcount; ++idx)
899 clear_tv(&argvars[idx]);
Bram Moolenaar015f4262020-05-05 21:25:22 +0200900
Bram Moolenaar57f799e2020-12-12 20:42:19 +0100901 if (did_emsg > did_emsg_before)
Bram Moolenaar015f4262020-05-05 21:25:22 +0200902 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100903 return OK;
904}
905
906/*
907 * Execute a user defined function.
Bram Moolenaarab360522021-01-10 14:02:28 +0100908 * If the function is compiled this will add a stack frame and set the
909 * instruction pointer at the start of the function.
910 * Otherwise the function is called here.
Bram Moolenaarc04f2a42021-06-09 19:30:03 +0200911 * If "pt" is not null use "pt->pt_outer" for ec_outer_ref->or_outer.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100912 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100913 */
914 static int
Bram Moolenaar0186e582021-01-10 18:33:11 +0100915call_ufunc(
916 ufunc_T *ufunc,
917 partial_T *pt,
918 int argcount,
919 ectx_T *ectx,
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +0200920 isn_T *iptr,
921 dict_T *selfdict)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100922{
923 typval_T argvars[MAX_FUNC_ARGS];
924 funcexe_T funcexe;
925 int error;
926 int idx;
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100927 int did_emsg_before = did_emsg;
Bram Moolenaar139575d2022-03-15 19:29:30 +0000928 compiletype_T compile_type = get_compile_type(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100929
Bram Moolenaare99d4222021-06-13 14:01:26 +0200930 if (func_needs_compiling(ufunc, compile_type)
931 && compile_def_function(ufunc, FALSE, compile_type, NULL)
932 == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +0200933 return FAIL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +0200934 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100935 {
Bram Moolenaar52c124d2020-12-20 21:43:35 +0100936 error = check_user_func_argcount(ufunc, argcount);
Bram Moolenaar50824712020-12-20 21:10:17 +0100937 if (error != FCERR_UNKNOWN)
938 {
939 if (error == FCERR_TOOMANY)
Bram Moolenaare1242042021-12-16 20:56:57 +0000940 semsg(_(e_too_many_arguments_for_function_str), ufunc->uf_name);
Bram Moolenaar50824712020-12-20 21:10:17 +0100941 else
Bram Moolenaare1242042021-12-16 20:56:57 +0000942 semsg(_(e_not_enough_arguments_for_function_str),
943 ufunc->uf_name);
Bram Moolenaar50824712020-12-20 21:10:17 +0100944 return FAIL;
945 }
946
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100947 // The function has been compiled, can call it quickly. For a function
948 // that was defined later: we can call it directly next time.
949 if (iptr != NULL)
950 {
Bram Moolenaar20431c92020-03-20 18:39:46 +0100951 delete_instr(iptr);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100952 iptr->isn_type = ISN_DCALL;
953 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
954 iptr->isn_arg.dfunc.cdf_argcount = argcount;
955 }
Bram Moolenaar4c137212021-04-19 16:48:48 +0200956 return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, ectx);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100957 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100958
959 if (call_prepare(argcount, argvars, ectx) == FAIL)
960 return FAIL;
Bram Moolenaara80faa82020-04-12 19:37:17 +0200961 CLEAR_FIELD(funcexe);
Bram Moolenaar851f86b2021-12-13 14:26:44 +0000962 funcexe.fe_evaluate = TRUE;
963 funcexe.fe_selfdict = selfdict != NULL ? selfdict : dict_stack_get_dict();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100964
965 // Call the user function. Result goes in last position on the stack.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100966 error = call_user_func_check(ufunc, argcount, argvars,
Bram Moolenaar851f86b2021-12-13 14:26:44 +0000967 STACK_TV_BOT(-1), &funcexe, funcexe.fe_selfdict);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100968
969 // Clear the arguments.
970 for (idx = 0; idx < argcount; ++idx)
971 clear_tv(&argvars[idx]);
972
973 if (error != FCERR_NONE)
974 {
Bram Moolenaar2ef91562021-12-11 16:14:07 +0000975 user_func_error(error, ufunc->uf_name, &funcexe);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100976 return FAIL;
977 }
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100978 if (did_emsg > did_emsg_before)
Bram Moolenaared677f52020-08-12 16:38:10 +0200979 // Error other than from calling the function itself.
980 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100981 return OK;
982}
983
984/*
Bram Moolenaara91a7132021-03-25 21:12:15 +0100985 * If command modifiers were applied restore them.
986 */
987 static void
988may_restore_cmdmod(funclocal_T *funclocal)
989{
990 if (funclocal->floc_restore_cmdmod)
991 {
992 cmdmod.cmod_filter_regmatch.regprog = NULL;
993 undo_cmdmod(&cmdmod);
994 cmdmod = funclocal->floc_save_cmdmod;
995 funclocal->floc_restore_cmdmod = FALSE;
996 }
997}
998
999/*
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001000 * Return TRUE if an error was given (not caught in try/catch) or CTRL-C was
1001 * pressed.
Bram Moolenaara1773442020-08-12 15:21:22 +02001002 */
1003 static int
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001004vim9_aborting(int prev_uncaught_emsg)
Bram Moolenaara1773442020-08-12 15:21:22 +02001005{
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001006 return uncaught_emsg > prev_uncaught_emsg || got_int || did_throw;
Bram Moolenaara1773442020-08-12 15:21:22 +02001007}
1008
1009/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001010 * Execute a function by "name".
1011 * This can be a builtin function or a user function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001012 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001013 * Returns FAIL if not found without an error message.
1014 */
1015 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001016call_by_name(
1017 char_u *name,
1018 int argcount,
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001019 ectx_T *ectx,
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001020 isn_T *iptr,
1021 dict_T *selfdict)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001022{
1023 ufunc_T *ufunc;
1024
1025 if (builtin_function(name, -1))
1026 {
1027 int func_idx = find_internal_func(name);
1028
Bram Moolenaar1983f1a2022-02-28 20:55:02 +00001029 if (func_idx < 0) // Impossible?
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001030 return FAIL;
Bram Moolenaar389df252020-07-09 21:20:47 +02001031 if (check_internal_func(func_idx, argcount) < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001032 return FAIL;
1033 return call_bfunc(func_idx, argcount, ectx);
1034 }
1035
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00001036 ufunc = find_func(name, FALSE);
Bram Moolenaara1773442020-08-12 15:21:22 +02001037
1038 if (ufunc == NULL)
1039 {
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001040 int prev_uncaught_emsg = uncaught_emsg;
Bram Moolenaara1773442020-08-12 15:21:22 +02001041
1042 if (script_autoload(name, TRUE))
1043 // loaded a package, search for the function again
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00001044 ufunc = find_func(name, FALSE);
Bram Moolenaar88c89c72021-08-14 14:01:05 +02001045
1046 if (vim9_aborting(prev_uncaught_emsg))
Bram Moolenaara1773442020-08-12 15:21:22 +02001047 return FAIL; // bail out if loading the script caused an error
1048 }
1049
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001050 if (ufunc != NULL)
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001051 {
Bram Moolenaar6ce46b92021-08-07 15:35:36 +02001052 if (ufunc->uf_arg_types != NULL || ufunc->uf_va_type != NULL)
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001053 {
1054 int i;
1055 typval_T *argv = STACK_TV_BOT(0) - argcount;
1056
1057 // The function can change at runtime, check that the argument
1058 // types are correct.
1059 for (i = 0; i < argcount; ++i)
1060 {
Bram Moolenaare3ffcd92021-03-08 21:47:13 +01001061 type_T *type = NULL;
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001062
Bram Moolenaar6ce46b92021-08-07 15:35:36 +02001063 if (i < ufunc->uf_args.ga_len && ufunc->uf_arg_types != NULL)
Bram Moolenaare3ffcd92021-03-08 21:47:13 +01001064 type = ufunc->uf_arg_types[i];
1065 else if (ufunc->uf_va_type != NULL)
1066 type = ufunc->uf_va_type->tt_member;
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001067 if (type != NULL && check_typval_arg_type(type,
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02001068 &argv[i], NULL, i + 1) == FAIL)
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001069 return FAIL;
1070 }
1071 }
1072
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001073 return call_ufunc(ufunc, NULL, argcount, ectx, iptr, selfdict);
Bram Moolenaar04947cc2021-03-06 19:26:46 +01001074 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001075
1076 return FAIL;
1077}
1078
1079 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001080call_partial(
1081 typval_T *tv,
1082 int argcount_arg,
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001083 ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001084{
Bram Moolenaara90afb92020-07-15 22:38:56 +02001085 int argcount = argcount_arg;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001086 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001087 int called_emsg_before = called_emsg;
Bram Moolenaarcb6cbf22021-01-12 17:17:01 +01001088 int res = FAIL;
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001089 dict_T *selfdict = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001090
1091 if (tv->v_type == VAR_PARTIAL)
1092 {
Bram Moolenaara90afb92020-07-15 22:38:56 +02001093 partial_T *pt = tv->vval.v_partial;
1094 int i;
1095
1096 if (pt->pt_argc > 0)
1097 {
1098 // Make space for arguments from the partial, shift the "argcount"
1099 // arguments up.
Bram Moolenaar35578162021-08-02 19:10:38 +02001100 if (GA_GROW_FAILS(&ectx->ec_stack, pt->pt_argc))
Bram Moolenaara90afb92020-07-15 22:38:56 +02001101 return FAIL;
1102 for (i = 1; i <= argcount; ++i)
1103 *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i);
1104 ectx->ec_stack.ga_len += pt->pt_argc;
1105 argcount += pt->pt_argc;
1106
1107 // copy the arguments from the partial onto the stack
1108 for (i = 0; i < pt->pt_argc; ++i)
1109 copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i));
1110 }
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001111 selfdict = pt->pt_dict;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001112
1113 if (pt->pt_func != NULL)
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001114 return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL, selfdict);
Bram Moolenaarf7779c62020-05-03 15:38:16 +02001115
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001116 name = pt->pt_name;
1117 }
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001118 else if (tv->v_type == VAR_FUNC)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001119 name = tv->vval.v_string;
Bram Moolenaar95006e32020-08-29 17:47:08 +02001120 if (name != NULL)
1121 {
1122 char_u fname_buf[FLEN_FIXED + 1];
1123 char_u *tofree = NULL;
1124 int error = FCERR_NONE;
1125 char_u *fname;
1126
1127 // May need to translate <SNR>123_ to K_SNR.
1128 fname = fname_trans_sid(name, fname_buf, &tofree, &error);
1129 if (error != FCERR_NONE)
1130 res = FAIL;
1131 else
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001132 res = call_by_name(fname, argcount, ectx, NULL, selfdict);
Bram Moolenaar95006e32020-08-29 17:47:08 +02001133 vim_free(tofree);
1134 }
1135
Bram Moolenaarcb6cbf22021-01-12 17:17:01 +01001136 if (res == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001137 {
1138 if (called_emsg == called_emsg_before)
Bram Moolenaare1242042021-12-16 20:56:57 +00001139 semsg(_(e_unknown_function_str),
Bram Moolenaar015f4262020-05-05 21:25:22 +02001140 name == NULL ? (char_u *)"[unknown]" : name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001141 return FAIL;
1142 }
1143 return OK;
1144}
1145
1146/*
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001147 * Check if "lock" is VAR_LOCKED or VAR_FIXED. If so give an error and return
1148 * TRUE.
1149 */
1150 static int
1151error_if_locked(int lock, char *error)
1152{
1153 if (lock & (VAR_LOCKED | VAR_FIXED))
1154 {
1155 emsg(_(error));
1156 return TRUE;
1157 }
1158 return FALSE;
1159}
1160
1161/*
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01001162 * Give an error if "tv" is not a number and return FAIL.
1163 */
1164 static int
1165check_for_number(typval_T *tv)
1166{
1167 if (tv->v_type != VAR_NUMBER)
1168 {
1169 semsg(_(e_expected_str_but_got_str),
1170 vartype_name(VAR_NUMBER), vartype_name(tv->v_type));
1171 return FAIL;
1172 }
1173 return OK;
1174}
1175
1176/*
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001177 * Store "tv" in variable "name".
1178 * This is for s: and g: variables.
1179 */
1180 static void
1181store_var(char_u *name, typval_T *tv)
1182{
1183 funccal_entry_T entry;
Bram Moolenaard877a572021-04-01 19:42:48 +02001184 int flags = ASSIGN_DECL;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001185
Bram Moolenaard877a572021-04-01 19:42:48 +02001186 if (tv->v_lock)
1187 flags |= ASSIGN_CONST;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001188 save_funccal(&entry);
Bram Moolenaard5f400c2022-01-06 21:10:28 +00001189 set_var_const(name, 0, NULL, tv, FALSE, flags, 0);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001190 restore_funccal();
1191}
1192
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001193/*
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001194 * Convert "tv" to a string.
1195 * Return FAIL if not allowed.
1196 */
1197 static int
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001198do_2string(typval_T *tv, int is_2string_any, int tolerant)
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001199{
1200 if (tv->v_type != VAR_STRING)
1201 {
1202 char_u *str;
1203
1204 if (is_2string_any)
1205 {
1206 switch (tv->v_type)
1207 {
1208 case VAR_SPECIAL:
1209 case VAR_BOOL:
1210 case VAR_NUMBER:
1211 case VAR_FLOAT:
1212 case VAR_BLOB: break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001213
1214 case VAR_LIST:
1215 if (tolerant)
1216 {
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001217 char_u *s, *e, *p;
1218 garray_T ga;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001219
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001220 ga_init2(&ga, sizeof(char_u *), 1);
1221
1222 // Convert to NL separated items, then
1223 // escape the items and replace the NL with
1224 // a space.
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001225 str = typval2string(tv, TRUE);
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001226 if (str == NULL)
1227 return FAIL;
1228 s = str;
1229 while ((e = vim_strchr(s, '\n')) != NULL)
1230 {
1231 *e = NUL;
Bram Moolenaar21c1a0c2021-10-17 17:20:23 +01001232 p = vim_strsave_fnameescape(s,
1233 VSE_NONE);
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001234 if (p != NULL)
1235 {
1236 ga_concat(&ga, p);
1237 ga_concat(&ga, (char_u *)" ");
1238 vim_free(p);
1239 }
1240 s = e + 1;
1241 }
1242 vim_free(str);
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001243 clear_tv(tv);
1244 tv->v_type = VAR_STRING;
Bram Moolenaarb288ba92021-06-05 17:10:55 +02001245 tv->vval.v_string = ga.ga_data;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02001246 return OK;
1247 }
1248 // FALLTHROUGH
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001249 default: to_string_error(tv->v_type);
1250 return FAIL;
1251 }
1252 }
Bram Moolenaar34453202021-01-31 13:08:38 +01001253 str = typval_tostring(tv, TRUE);
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01001254 clear_tv(tv);
1255 tv->v_type = VAR_STRING;
1256 tv->vval.v_string = str;
1257 }
1258 return OK;
1259}
1260
1261/*
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001262 * When the value of "sv" is a null list of dict, allocate it.
1263 */
1264 static void
1265allocate_if_null(typval_T *tv)
1266{
1267 switch (tv->v_type)
1268 {
1269 case VAR_LIST:
1270 if (tv->vval.v_list == NULL)
Bram Moolenaarfef80642021-02-03 20:01:19 +01001271 (void)rettv_list_alloc(tv);
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001272 break;
1273 case VAR_DICT:
1274 if (tv->vval.v_dict == NULL)
Bram Moolenaarfef80642021-02-03 20:01:19 +01001275 (void)rettv_dict_alloc(tv);
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001276 break;
Bram Moolenaarb7c21af2021-04-18 14:12:31 +02001277 case VAR_BLOB:
1278 if (tv->vval.v_blob == NULL)
1279 (void)rettv_blob_alloc(tv);
1280 break;
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01001281 default:
1282 break;
1283 }
1284}
Bram Moolenaard3aac292020-04-19 14:32:17 +02001285
Bram Moolenaare7525c52021-01-09 13:20:37 +01001286/*
Bram Moolenaar0289a092021-03-14 18:40:19 +01001287 * Return the character "str[index]" where "index" is the character index,
1288 * including composing characters.
1289 * If "index" is out of range NULL is returned.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001290 */
1291 char_u *
1292char_from_string(char_u *str, varnumber_T index)
1293{
1294 size_t nbyte = 0;
1295 varnumber_T nchar = index;
1296 size_t slen;
1297
1298 if (str == NULL)
1299 return NULL;
1300 slen = STRLEN(str);
1301
Bram Moolenaarff871402021-03-26 13:34:05 +01001302 // Do the same as for a list: a negative index counts from the end.
1303 // Optimization to check the first byte to be below 0x80 (and no composing
1304 // character follows) makes this a lot faster.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001305 if (index < 0)
1306 {
1307 int clen = 0;
1308
1309 for (nbyte = 0; nbyte < slen; ++clen)
Bram Moolenaarff871402021-03-26 13:34:05 +01001310 {
1311 if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
1312 ++nbyte;
1313 else if (enc_utf8)
1314 nbyte += utfc_ptr2len(str + nbyte);
1315 else
1316 nbyte += mb_ptr2len(str + nbyte);
1317 }
Bram Moolenaare7525c52021-01-09 13:20:37 +01001318 nchar = clen + index;
1319 if (nchar < 0)
1320 // unlike list: index out of range results in empty string
1321 return NULL;
1322 }
1323
1324 for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar)
Bram Moolenaarff871402021-03-26 13:34:05 +01001325 {
1326 if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
1327 ++nbyte;
1328 else if (enc_utf8)
1329 nbyte += utfc_ptr2len(str + nbyte);
1330 else
1331 nbyte += mb_ptr2len(str + nbyte);
1332 }
Bram Moolenaare7525c52021-01-09 13:20:37 +01001333 if (nbyte >= slen)
1334 return NULL;
Bram Moolenaar0289a092021-03-14 18:40:19 +01001335 return vim_strnsave(str + nbyte, mb_ptr2len(str + nbyte));
Bram Moolenaare7525c52021-01-09 13:20:37 +01001336}
1337
1338/*
1339 * Get the byte index for character index "idx" in string "str" with length
Bram Moolenaar0289a092021-03-14 18:40:19 +01001340 * "str_len". Composing characters are included.
Bram Moolenaare7525c52021-01-09 13:20:37 +01001341 * If going over the end return "str_len".
1342 * If "idx" is negative count from the end, -1 is the last character.
1343 * When going over the start return -1.
1344 */
1345 static long
1346char_idx2byte(char_u *str, size_t str_len, varnumber_T idx)
1347{
1348 varnumber_T nchar = idx;
1349 size_t nbyte = 0;
1350
1351 if (nchar >= 0)
1352 {
1353 while (nchar > 0 && nbyte < str_len)
1354 {
Bram Moolenaar0289a092021-03-14 18:40:19 +01001355 nbyte += mb_ptr2len(str + nbyte);
Bram Moolenaare7525c52021-01-09 13:20:37 +01001356 --nchar;
1357 }
1358 }
1359 else
1360 {
1361 nbyte = str_len;
1362 while (nchar < 0 && nbyte > 0)
1363 {
1364 --nbyte;
1365 nbyte -= mb_head_off(str, str + nbyte);
1366 ++nchar;
1367 }
1368 if (nchar < 0)
1369 return -1;
1370 }
1371 return (long)nbyte;
1372}
1373
1374/*
Bram Moolenaar0289a092021-03-14 18:40:19 +01001375 * Return the slice "str[first : last]" using character indexes. Composing
1376 * characters are included.
Bram Moolenaar6601b622021-01-13 21:47:15 +01001377 * "exclusive" is TRUE for slice().
Bram Moolenaare7525c52021-01-09 13:20:37 +01001378 * Return NULL when the result is empty.
1379 */
1380 char_u *
Bram Moolenaar6601b622021-01-13 21:47:15 +01001381string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001382{
1383 long start_byte, end_byte;
1384 size_t slen;
1385
1386 if (str == NULL)
1387 return NULL;
1388 slen = STRLEN(str);
1389 start_byte = char_idx2byte(str, slen, first);
1390 if (start_byte < 0)
1391 start_byte = 0; // first index very negative: use zero
Bram Moolenaar6601b622021-01-13 21:47:15 +01001392 if ((last == -1 && !exclusive) || last == VARNUM_MAX)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001393 end_byte = (long)slen;
1394 else
1395 {
1396 end_byte = char_idx2byte(str, slen, last);
Bram Moolenaar6601b622021-01-13 21:47:15 +01001397 if (!exclusive && end_byte >= 0 && end_byte < (long)slen)
Bram Moolenaare7525c52021-01-09 13:20:37 +01001398 // end index is inclusive
Bram Moolenaar0289a092021-03-14 18:40:19 +01001399 end_byte += mb_ptr2len(str + end_byte);
Bram Moolenaare7525c52021-01-09 13:20:37 +01001400 }
1401
1402 if (start_byte >= (long)slen || end_byte <= start_byte)
1403 return NULL;
1404 return vim_strnsave(str + start_byte, end_byte - start_byte);
1405}
1406
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001407/*
1408 * Get a script variable for ISN_STORESCRIPT and ISN_LOADSCRIPT.
1409 * When "dfunc_idx" is negative don't give an error.
1410 * Returns NULL for an error.
1411 */
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001412 static svar_T *
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001413get_script_svar(scriptref_T *sref, int dfunc_idx)
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001414{
1415 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001416 dfunc_T *dfunc = dfunc_idx < 0 ? NULL
1417 : ((dfunc_T *)def_functions.ga_data) + dfunc_idx;
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001418 svar_T *sv;
1419
1420 if (sref->sref_seq != si->sn_script_seq)
1421 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001422 // The script was reloaded after the function was compiled, the
1423 // script_idx may not be valid.
1424 if (dfunc != NULL)
1425 semsg(_(e_script_variable_invalid_after_reload_in_function_str),
1426 printable_func_name(dfunc->df_ufunc));
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001427 return NULL;
1428 }
1429 sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx;
Bram Moolenaar60dc8272021-07-29 22:48:54 +02001430 if (!equal_type(sv->sv_type, sref->sref_type, 0))
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001431 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02001432 if (dfunc != NULL)
1433 emsg(_(e_script_variable_type_changed));
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001434 return NULL;
1435 }
1436 return sv;
1437}
1438
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001439/*
Bram Moolenaar20677332021-06-06 17:02:53 +02001440 * Function passed to do_cmdline() for splitting a script joined by NL
1441 * characters.
1442 */
1443 static char_u *
1444get_split_sourceline(
1445 int c UNUSED,
1446 void *cookie,
1447 int indent UNUSED,
1448 getline_opt_T options UNUSED)
1449{
1450 source_cookie_T *sp = (source_cookie_T *)cookie;
1451 char_u *p;
1452 char_u *line;
1453
Bram Moolenaar20677332021-06-06 17:02:53 +02001454 p = vim_strchr(sp->nextline, '\n');
1455 if (p == NULL)
1456 {
1457 line = vim_strsave(sp->nextline);
1458 sp->nextline += STRLEN(sp->nextline);
1459 }
1460 else
1461 {
1462 line = vim_strnsave(sp->nextline, p - sp->nextline);
1463 sp->nextline = p + 1;
1464 }
1465 return line;
1466}
1467
1468/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001469 * Execute a function by "name".
1470 * This can be a builtin function, user function or a funcref.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001471 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001472 */
1473 static int
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001474call_eval_func(
1475 char_u *name,
1476 int argcount,
Bram Moolenaar2fecb532021-03-24 22:00:56 +01001477 ectx_T *ectx,
1478 isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001479{
Bram Moolenaared677f52020-08-12 16:38:10 +02001480 int called_emsg_before = called_emsg;
1481 int res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001482
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02001483 res = call_by_name(name, argcount, ectx, iptr, NULL);
Bram Moolenaared677f52020-08-12 16:38:10 +02001484 if (res == FAIL && called_emsg == called_emsg_before)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001485 {
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001486 dictitem_T *v;
1487
1488 v = find_var(name, NULL, FALSE);
1489 if (v == NULL)
1490 {
Bram Moolenaare1242042021-12-16 20:56:57 +00001491 semsg(_(e_unknown_function_str), name);
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001492 return FAIL;
1493 }
1494 if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC)
1495 {
Bram Moolenaare1242042021-12-16 20:56:57 +00001496 semsg(_(e_unknown_function_str), name);
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02001497 return FAIL;
1498 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02001499 return call_partial(&v->di_tv, argcount, ectx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001500 }
Bram Moolenaared677f52020-08-12 16:38:10 +02001501 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001502}
1503
1504/*
Bram Moolenaarf112f302020-12-20 17:47:52 +01001505 * When a function reference is used, fill a partial with the information
1506 * needed, especially when it is used as a closure.
1507 */
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01001508 int
Bram Moolenaarf112f302020-12-20 17:47:52 +01001509fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
1510{
1511 pt->pt_func = ufunc;
1512 pt->pt_refcount = 1;
1513
Bram Moolenaar0d3de8c2021-01-22 20:46:27 +01001514 if (ufunc->uf_flags & FC_CLOSURE)
Bram Moolenaarf112f302020-12-20 17:47:52 +01001515 {
1516 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1517 + ectx->ec_dfunc_idx;
1518
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001519 // The closure may need to find arguments and local variables in the
1520 // current stack.
Bram Moolenaar0186e582021-01-10 18:33:11 +01001521 pt->pt_outer.out_stack = &ectx->ec_stack;
1522 pt->pt_outer.out_frame_idx = ectx->ec_frame_idx;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001523 if (ectx->ec_outer_ref != NULL)
1524 {
1525 // The current context already has a context, link to that one.
1526 pt->pt_outer.out_up = ectx->ec_outer_ref->or_outer;
1527 if (ectx->ec_outer_ref->or_partial != NULL)
1528 {
1529 pt->pt_outer.out_up_partial = ectx->ec_outer_ref->or_partial;
1530 ++pt->pt_outer.out_up_partial->pt_refcount;
1531 }
1532 }
Bram Moolenaarf112f302020-12-20 17:47:52 +01001533
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001534 // If this function returns and the closure is still being used, we
1535 // need to make a copy of the context (arguments and local variables).
1536 // Store a reference to the partial so we can handle that.
Bram Moolenaar35578162021-08-02 19:10:38 +02001537 if (GA_GROW_FAILS(&ectx->ec_funcrefs, 1))
Bram Moolenaarf112f302020-12-20 17:47:52 +01001538 {
1539 vim_free(pt);
1540 return FAIL;
1541 }
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02001542 // Extra variable keeps the count of closures created in the current
1543 // function call.
Bram Moolenaarf112f302020-12-20 17:47:52 +01001544 ++(((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx
1545 + STACK_FRAME_SIZE + dfunc->df_varcount)->vval.v_number;
1546
1547 ((partial_T **)ectx->ec_funcrefs.ga_data)
1548 [ectx->ec_funcrefs.ga_len] = pt;
1549 ++pt->pt_refcount;
1550 ++ectx->ec_funcrefs.ga_len;
1551 }
Bram Moolenaar0d3de8c2021-01-22 20:46:27 +01001552 ++ufunc->uf_refcount;
Bram Moolenaarf112f302020-12-20 17:47:52 +01001553 return OK;
1554}
1555
Bram Moolenaaraacc9662021-08-13 19:40:51 +02001556/*
1557 * Execute iptr->isn_arg.string as an Ex command.
1558 */
1559 static int
1560exec_command(isn_T *iptr)
1561{
1562 source_cookie_T cookie;
1563
1564 SOURCING_LNUM = iptr->isn_lnum;
1565 // Pass getsourceline to get an error for a missing ":end"
1566 // command.
1567 CLEAR_FIELD(cookie);
1568 cookie.sourcing_lnum = iptr->isn_lnum - 1;
1569 if (do_cmdline(iptr->isn_arg.string,
1570 getsourceline, &cookie,
1571 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED) == FAIL
1572 || did_emsg)
1573 return FAIL;
1574 return OK;
1575}
1576
Bram Moolenaarf18332f2021-05-07 17:55:55 +02001577// used for v_instr of typval of VAR_INSTR
1578struct instr_S {
1579 ectx_T *instr_ectx;
1580 isn_T *instr_instr;
1581};
1582
Bram Moolenaar4c137212021-04-19 16:48:48 +02001583// used for substitute_instr
1584typedef struct subs_expr_S {
1585 ectx_T *subs_ectx;
1586 isn_T *subs_instr;
1587 int subs_status;
1588} subs_expr_T;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001589
1590// Get pointer to item in the stack.
Bram Moolenaar4c137212021-04-19 16:48:48 +02001591#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001592
1593// Get pointer to item at the bottom of the stack, -1 is the bottom.
1594#undef STACK_TV_BOT
Bram Moolenaar4c137212021-04-19 16:48:48 +02001595#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 +01001596
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001597// Get pointer to a local variable on the stack. Negative for arguments.
Bram Moolenaar4c137212021-04-19 16:48:48 +02001598#define STACK_TV_VAR(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx + STACK_FRAME_SIZE + idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001599
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001600// Set when calling do_debug().
1601static ectx_T *debug_context = NULL;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001602static int debug_var_count;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001603
1604/*
1605 * When debugging lookup "name" and return the typeval.
1606 * When not found return NULL.
1607 */
1608 typval_T *
1609lookup_debug_var(char_u *name)
1610{
1611 int idx;
1612 dfunc_T *dfunc;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001613 ufunc_T *ufunc;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001614 ectx_T *ectx = debug_context;
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001615 int varargs_off;
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001616
1617 if (ectx == NULL)
1618 return NULL;
1619 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
1620
1621 // Go through the local variable names, from last to first.
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001622 for (idx = debug_var_count - 1; idx >= 0; --idx)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001623 {
Bram Moolenaare406ff82022-03-10 20:47:43 +00001624 char_u *varname = ((char_u **)dfunc->df_var_names.ga_data)[idx];
1625
1626 // the variable name may be NULL when not available in this block
1627 if (varname != NULL && STRCMP(varname, name) == 0)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001628 return STACK_TV_VAR(idx);
1629 }
1630
Bram Moolenaar6bc30b02021-06-16 19:19:55 +02001631 // Go through argument names.
1632 ufunc = dfunc->df_ufunc;
1633 varargs_off = ufunc->uf_va_name == NULL ? 0 : 1;
1634 for (idx = 0; idx < ufunc->uf_args.ga_len; ++idx)
1635 if (STRCMP(((char_u **)(ufunc->uf_args.ga_data))[idx], name) == 0)
1636 return STACK_TV(ectx->ec_frame_idx - ufunc->uf_args.ga_len
1637 - varargs_off + idx);
1638 if (ufunc->uf_va_name != NULL && STRCMP(ufunc->uf_va_name, name) == 0)
1639 return STACK_TV(ectx->ec_frame_idx - 1);
1640
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02001641 return NULL;
1642}
1643
Bram Moolenaar26a44842021-09-02 18:49:06 +02001644/*
1645 * Return TRUE if there might be a breakpoint in "ufunc", which is when a
1646 * breakpoint was set in that function or when there is any expression.
1647 */
1648 int
1649may_break_in_function(ufunc_T *ufunc)
1650{
1651 return ufunc->uf_has_breakpoint || debug_has_expr_breakpoint();
1652}
1653
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001654 static void
1655handle_debug(isn_T *iptr, ectx_T *ectx)
1656{
1657 char_u *line;
1658 ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
1659 + ectx->ec_dfunc_idx)->df_ufunc;
1660 isn_T *ni;
1661 int end_lnum = iptr->isn_lnum;
1662 garray_T ga;
1663 int lnum;
1664
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001665 if (ex_nesting_level > debug_break_level)
1666 {
1667 linenr_T breakpoint;
1668
Bram Moolenaar26a44842021-09-02 18:49:06 +02001669 if (!may_break_in_function(ufunc))
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001670 return;
1671
1672 // check for the next breakpoint if needed
1673 breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name,
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001674 iptr->isn_arg.debug.dbg_break_lnum);
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02001675 if (breakpoint <= 0 || breakpoint > iptr->isn_lnum)
1676 return;
1677 }
1678
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001679 SOURCING_LNUM = iptr->isn_lnum;
1680 debug_context = ectx;
Bram Moolenaar8cec9272021-06-23 20:20:53 +02001681 debug_var_count = iptr->isn_arg.debug.dbg_var_names_len;
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001682
1683 for (ni = iptr + 1; ni->isn_type != ISN_FINISH; ++ni)
1684 if (ni->isn_type == ISN_DEBUG
1685 || ni->isn_type == ISN_RETURN
1686 || ni->isn_type == ISN_RETURN_VOID)
1687 {
Bram Moolenaar112bed02021-11-23 22:16:34 +00001688 end_lnum = ni->isn_lnum + (ni->isn_type == ISN_DEBUG ? 0 : 1);
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001689 break;
1690 }
1691
1692 if (end_lnum > iptr->isn_lnum)
1693 {
1694 ga_init2(&ga, sizeof(char_u *), 10);
Bram Moolenaar310091d2021-12-23 21:14:37 +00001695 for (lnum = iptr->isn_lnum; lnum < end_lnum
1696 && lnum <= ufunc->uf_lines.ga_len; ++lnum)
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001697 {
Bram Moolenaar303215d2021-07-07 20:10:43 +02001698 char_u *p = ((char_u **)ufunc->uf_lines.ga_data)[lnum - 1];
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001699
Bram Moolenaar303215d2021-07-07 20:10:43 +02001700 if (p == NULL)
1701 continue; // left over from continuation line
1702 p = skipwhite(p);
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001703 if (*p == '#')
1704 break;
Bram Moolenaar35578162021-08-02 19:10:38 +02001705 if (GA_GROW_OK(&ga, 1))
Bram Moolenaar59b50c32021-06-17 22:27:48 +02001706 ((char_u **)(ga.ga_data))[ga.ga_len++] = p;
1707 if (STRNCMP(p, "def ", 4) == 0)
1708 break;
1709 }
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001710 line = ga_concat_strings(&ga, " ");
1711 vim_free(ga.ga_data);
1712 }
1713 else
1714 line = ((char_u **)ufunc->uf_lines.ga_data)[iptr->isn_lnum - 1];
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001715
Dominique Pelle6e969552021-06-17 13:53:41 +02001716 do_debug(line == NULL ? (char_u *)"[empty]" : line);
Bram Moolenaar4cea5362021-06-16 22:24:40 +02001717 debug_context = NULL;
1718
1719 if (end_lnum > iptr->isn_lnum)
1720 vim_free(line);
1721}
1722
Bram Moolenaar4c137212021-04-19 16:48:48 +02001723/*
Bram Moolenaarfe1bfc92022-02-06 13:55:03 +00001724 * Store a value in a list, dict or blob variable.
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001725 * Returns OK, FAIL or NOTDONE (uncatchable error).
1726 */
1727 static int
1728execute_storeindex(isn_T *iptr, ectx_T *ectx)
1729{
1730 vartype_T dest_type = iptr->isn_arg.vartype;
1731 typval_T *tv;
1732 typval_T *tv_idx = STACK_TV_BOT(-2);
1733 typval_T *tv_dest = STACK_TV_BOT(-1);
1734 int status = OK;
1735
1736 // Stack contains:
1737 // -3 value to be stored
1738 // -2 index
1739 // -1 dict or list
1740 tv = STACK_TV_BOT(-3);
1741 SOURCING_LNUM = iptr->isn_lnum;
1742 if (dest_type == VAR_ANY)
1743 {
1744 dest_type = tv_dest->v_type;
1745 if (dest_type == VAR_DICT)
1746 status = do_2string(tv_idx, TRUE, FALSE);
1747 else if (dest_type == VAR_LIST && tv_idx->v_type != VAR_NUMBER)
1748 {
1749 emsg(_(e_number_expected));
1750 status = FAIL;
1751 }
1752 }
Bram Moolenaare08be092022-02-17 13:08:26 +00001753
1754 if (status == OK)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001755 {
Bram Moolenaare08be092022-02-17 13:08:26 +00001756 if (dest_type == VAR_LIST)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001757 {
Bram Moolenaare08be092022-02-17 13:08:26 +00001758 long lidx = (long)tv_idx->vval.v_number;
1759 list_T *list = tv_dest->vval.v_list;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001760
Bram Moolenaare08be092022-02-17 13:08:26 +00001761 if (list == NULL)
1762 {
1763 emsg(_(e_list_not_set));
1764 return FAIL;
1765 }
1766 if (lidx < 0 && list->lv_len + lidx >= 0)
1767 // negative index is relative to the end
1768 lidx = list->lv_len + lidx;
1769 if (lidx < 0 || lidx > list->lv_len)
1770 {
1771 semsg(_(e_list_index_out_of_range_nr), lidx);
1772 return FAIL;
1773 }
1774 if (lidx < list->lv_len)
1775 {
1776 listitem_T *li = list_find(list, lidx);
1777
1778 if (error_if_locked(li->li_tv.v_lock,
Bram Moolenaar70c43d82022-01-26 21:01:15 +00001779 e_cannot_change_locked_list_item))
Bram Moolenaare08be092022-02-17 13:08:26 +00001780 return FAIL;
1781 // overwrite existing list item
1782 clear_tv(&li->li_tv);
1783 li->li_tv = *tv;
1784 }
1785 else
1786 {
1787 if (error_if_locked(list->lv_lock, e_cannot_change_locked_list))
1788 return FAIL;
1789 // append to list, only fails when out of memory
1790 if (list_append_tv(list, tv) == FAIL)
1791 return NOTDONE;
1792 clear_tv(tv);
1793 }
1794 }
1795 else if (dest_type == VAR_DICT)
1796 {
1797 char_u *key = tv_idx->vval.v_string;
1798 dict_T *dict = tv_dest->vval.v_dict;
1799 dictitem_T *di;
1800
1801 SOURCING_LNUM = iptr->isn_lnum;
1802 if (dict == NULL)
1803 {
1804 emsg(_(e_dictionary_not_set));
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001805 return FAIL;
Bram Moolenaare08be092022-02-17 13:08:26 +00001806 }
1807 if (key == NULL)
1808 key = (char_u *)"";
1809 di = dict_find(dict, key, -1);
1810 if (di != NULL)
1811 {
1812 if (error_if_locked(di->di_tv.v_lock,
1813 e_cannot_change_dict_item))
1814 return FAIL;
1815 // overwrite existing value
1816 clear_tv(&di->di_tv);
1817 di->di_tv = *tv;
1818 }
1819 else
1820 {
1821 if (error_if_locked(dict->dv_lock, e_cannot_change_dict))
1822 return FAIL;
1823 // add to dict, only fails when out of memory
1824 if (dict_add_tv(dict, (char *)key, tv) == FAIL)
1825 return NOTDONE;
1826 clear_tv(tv);
1827 }
1828 }
1829 else if (dest_type == VAR_BLOB)
1830 {
1831 long lidx = (long)tv_idx->vval.v_number;
1832 blob_T *blob = tv_dest->vval.v_blob;
1833 varnumber_T nr;
1834 int error = FALSE;
1835 int len;
1836
1837 if (blob == NULL)
1838 {
1839 emsg(_(e_blob_not_set));
1840 return FAIL;
1841 }
1842 len = blob_len(blob);
1843 if (lidx < 0 && len + lidx >= 0)
1844 // negative index is relative to the end
1845 lidx = len + lidx;
1846
1847 // Can add one byte at the end.
1848 if (lidx < 0 || lidx > len)
1849 {
1850 semsg(_(e_blob_index_out_of_range_nr), lidx);
1851 return FAIL;
1852 }
1853 if (value_check_lock(blob->bv_lock, (char_u *)"blob", FALSE))
1854 return FAIL;
1855 nr = tv_get_number_chk(tv, &error);
1856 if (error)
1857 return FAIL;
1858 blob_set_append(blob, lidx, nr);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001859 }
1860 else
1861 {
Bram Moolenaare08be092022-02-17 13:08:26 +00001862 status = FAIL;
1863 semsg(_(e_cannot_index_str), vartype_name(dest_type));
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001864 }
1865 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001866
1867 clear_tv(tv_idx);
1868 clear_tv(tv_dest);
1869 ectx->ec_stack.ga_len -= 3;
1870 if (status == FAIL)
1871 {
1872 clear_tv(tv);
1873 return FAIL;
1874 }
1875 return OK;
1876}
1877
1878/*
Bram Moolenaarea5c8982022-02-17 14:42:02 +00001879 * Store a value in a list or blob range.
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001880 */
1881 static int
1882execute_storerange(isn_T *iptr, ectx_T *ectx)
1883{
1884 typval_T *tv;
1885 typval_T *tv_idx1 = STACK_TV_BOT(-3);
1886 typval_T *tv_idx2 = STACK_TV_BOT(-2);
1887 typval_T *tv_dest = STACK_TV_BOT(-1);
1888 int status = OK;
1889
1890 // Stack contains:
1891 // -4 value to be stored
1892 // -3 first index or "none"
1893 // -2 second index or "none"
1894 // -1 destination list or blob
1895 tv = STACK_TV_BOT(-4);
Bram Moolenaarea5c8982022-02-17 14:42:02 +00001896 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001897 if (tv_dest->v_type == VAR_LIST)
1898 {
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00001899 long n1;
1900 long n2;
1901 listitem_T *li1;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001902
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00001903 n1 = (long)tv_get_number_chk(tv_idx1, NULL);
1904 if (tv_idx2->v_type == VAR_SPECIAL
1905 && tv_idx2->vval.v_number == VVAL_NONE)
1906 n2 = list_len(tv_dest->vval.v_list) - 1;
1907 else
1908 n2 = (long)tv_get_number_chk(tv_idx2, NULL);
1909
1910 li1 = check_range_index_one(tv_dest->vval.v_list, &n1, FALSE);
1911 if (li1 == NULL)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001912 status = FAIL;
1913 else
1914 {
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00001915 status = check_range_index_two(tv_dest->vval.v_list,
1916 &n1, li1, &n2, FALSE);
1917 if (status != FAIL)
1918 status = list_assign_range(
1919 tv_dest->vval.v_list,
1920 tv->vval.v_list,
1921 n1,
1922 n2,
1923 tv_idx2->v_type == VAR_SPECIAL,
1924 (char_u *)"=",
1925 (char_u *)"[unknown]");
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001926 }
1927 }
1928 else if (tv_dest->v_type == VAR_BLOB)
1929 {
1930 varnumber_T n1;
1931 varnumber_T n2;
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00001932 long bloblen;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001933
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00001934 n1 = tv_get_number_chk(tv_idx1, NULL);
1935 if (tv_idx2->v_type == VAR_SPECIAL
1936 && tv_idx2->vval.v_number == VVAL_NONE)
1937 n2 = blob_len(tv_dest->vval.v_blob) - 1;
1938 else
1939 n2 = tv_get_number_chk(tv_idx2, NULL);
1940 bloblen = blob_len(tv_dest->vval.v_blob);
1941
1942 if (check_blob_index(bloblen, n1, FALSE) == FAIL
1943 || check_blob_range(bloblen, n1, n2, FALSE) == FAIL)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001944 status = FAIL;
1945 else
Bram Moolenaar2995e5c2022-03-18 21:41:47 +00001946 status = blob_set_range(tv_dest->vval.v_blob, n1, n2, tv);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001947 }
1948 else
1949 {
1950 status = FAIL;
Bram Moolenaarea5c8982022-02-17 14:42:02 +00001951 emsg(_(e_list_or_blob_required));
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001952 }
1953
1954 clear_tv(tv_idx1);
1955 clear_tv(tv_idx2);
1956 clear_tv(tv_dest);
1957 ectx->ec_stack.ga_len -= 4;
1958 clear_tv(tv);
1959
1960 return status;
1961}
1962
1963/*
1964 * Unlet item in list or dict variable.
1965 */
1966 static int
1967execute_unletindex(isn_T *iptr, ectx_T *ectx)
1968{
1969 typval_T *tv_idx = STACK_TV_BOT(-2);
1970 typval_T *tv_dest = STACK_TV_BOT(-1);
1971 int status = OK;
1972
1973 // Stack contains:
1974 // -2 index
1975 // -1 dict or list
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00001976 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001977 if (tv_dest->v_type == VAR_DICT)
1978 {
1979 // unlet a dict item, index must be a string
Bram Moolenaarea5c8982022-02-17 14:42:02 +00001980 if (tv_idx->v_type != VAR_STRING && tv_idx->v_type != VAR_NUMBER)
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001981 {
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001982 semsg(_(e_expected_str_but_got_str),
1983 vartype_name(VAR_STRING),
1984 vartype_name(tv_idx->v_type));
1985 status = FAIL;
1986 }
1987 else
1988 {
1989 dict_T *d = tv_dest->vval.v_dict;
Bram Moolenaarea5c8982022-02-17 14:42:02 +00001990 char_u *key;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00001991 dictitem_T *di = NULL;
1992
1993 if (d != NULL && value_check_lock(
1994 d->dv_lock, NULL, FALSE))
1995 status = FAIL;
1996 else
1997 {
Bram Moolenaarea5c8982022-02-17 14:42:02 +00001998 if (tv_idx->v_type == VAR_STRING)
1999 {
2000 key = tv_idx->vval.v_string;
2001 if (key == NULL)
2002 key = (char_u *)"";
2003 }
2004 else
2005 {
2006 key = tv_get_string(tv_idx);
2007 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002008 if (d != NULL)
2009 di = dict_find(d, key, (int)STRLEN(key));
2010 if (di == NULL)
2011 {
2012 // NULL dict is equivalent to empty dict
2013 semsg(_(e_key_not_present_in_dictionary),
2014 key);
2015 status = FAIL;
2016 }
2017 else if (var_check_fixed(di->di_flags,
2018 NULL, FALSE)
2019 || var_check_ro(di->di_flags,
2020 NULL, FALSE))
2021 status = FAIL;
2022 else
2023 dictitem_remove(d, di);
2024 }
2025 }
2026 }
2027 else if (tv_dest->v_type == VAR_LIST)
2028 {
2029 // unlet a List item, index must be a number
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002030 if (check_for_number(tv_idx) == FAIL)
2031 {
2032 status = FAIL;
2033 }
2034 else
2035 {
2036 list_T *l = tv_dest->vval.v_list;
2037 long n = (long)tv_idx->vval.v_number;
2038
2039 if (l != NULL && value_check_lock(
2040 l->lv_lock, NULL, FALSE))
2041 status = FAIL;
2042 else
2043 {
2044 listitem_T *li = list_find(l, n);
2045
2046 if (li == NULL)
2047 {
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002048 semsg(_(e_list_index_out_of_range_nr), n);
2049 status = FAIL;
2050 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002051 else
2052 listitem_remove(l, li);
2053 }
2054 }
2055 }
2056 else
2057 {
2058 status = FAIL;
2059 semsg(_(e_cannot_index_str),
2060 vartype_name(tv_dest->v_type));
2061 }
2062
2063 clear_tv(tv_idx);
2064 clear_tv(tv_dest);
2065 ectx->ec_stack.ga_len -= 2;
2066
2067 return status;
2068}
2069
2070/*
2071 * Unlet a range of items in a list variable.
2072 */
2073 static int
2074execute_unletrange(isn_T *iptr, ectx_T *ectx)
2075{
2076 // Stack contains:
2077 // -3 index1
2078 // -2 index2
2079 // -1 dict or list
2080 typval_T *tv_idx1 = STACK_TV_BOT(-3);
2081 typval_T *tv_idx2 = STACK_TV_BOT(-2);
2082 typval_T *tv_dest = STACK_TV_BOT(-1);
2083 int status = OK;
2084
2085 if (tv_dest->v_type == VAR_LIST)
2086 {
2087 // indexes must be a number
2088 SOURCING_LNUM = iptr->isn_lnum;
2089 if (check_for_number(tv_idx1) == FAIL
2090 || (tv_idx2->v_type != VAR_SPECIAL
2091 && check_for_number(tv_idx2) == FAIL))
2092 {
2093 status = FAIL;
2094 }
2095 else
2096 {
2097 list_T *l = tv_dest->vval.v_list;
2098 long n1 = (long)tv_idx1->vval.v_number;
2099 long n2 = tv_idx2->v_type == VAR_SPECIAL
2100 ? 0 : (long)tv_idx2->vval.v_number;
2101 listitem_T *li;
2102
2103 li = list_find_index(l, &n1);
2104 if (li == NULL)
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002105 {
2106 semsg(_(e_list_index_out_of_range_nr),
2107 (long)tv_idx1->vval.v_number);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002108 status = FAIL;
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002109 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002110 else
2111 {
2112 if (n1 < 0)
2113 n1 = list_idx_of_item(l, li);
2114 if (n2 < 0)
2115 {
2116 listitem_T *li2 = list_find(l, n2);
2117
2118 if (li2 == NULL)
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002119 {
2120 semsg(_(e_list_index_out_of_range_nr), n2);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002121 status = FAIL;
Bram Moolenaar6296d1e2022-02-17 16:30:11 +00002122 }
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002123 else
2124 n2 = list_idx_of_item(l, li2);
2125 }
2126 if (status != FAIL
2127 && tv_idx2->v_type != VAR_SPECIAL
2128 && n2 < n1)
2129 {
2130 semsg(_(e_list_index_out_of_range_nr), n2);
2131 status = FAIL;
2132 }
Bram Moolenaar6b8c7ba2022-03-20 17:46:06 +00002133 if (status != FAIL)
2134 list_unlet_range(l, li, n1,
2135 tv_idx2->v_type != VAR_SPECIAL, n2);
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002136 }
2137 }
2138 }
2139 else
2140 {
2141 status = FAIL;
2142 SOURCING_LNUM = iptr->isn_lnum;
2143 semsg(_(e_cannot_index_str),
2144 vartype_name(tv_dest->v_type));
2145 }
2146
2147 clear_tv(tv_idx1);
2148 clear_tv(tv_idx2);
2149 clear_tv(tv_dest);
2150 ectx->ec_stack.ga_len -= 3;
2151
2152 return status;
2153}
2154
2155/*
2156 * Top of a for loop.
2157 */
2158 static int
2159execute_for(isn_T *iptr, ectx_T *ectx)
2160{
2161 typval_T *tv;
2162 typval_T *ltv = STACK_TV_BOT(-1);
2163 typval_T *idxtv =
2164 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);
2165
2166 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2167 return FAIL;
2168 if (ltv->v_type == VAR_LIST)
2169 {
2170 list_T *list = ltv->vval.v_list;
2171
2172 // push the next item from the list
2173 ++idxtv->vval.v_number;
2174 if (list == NULL
2175 || idxtv->vval.v_number >= list->lv_len)
2176 {
2177 // past the end of the list, jump to "endfor"
2178 ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
2179 may_restore_cmdmod(&ectx->ec_funclocal);
2180 }
2181 else if (list->lv_first == &range_list_item)
2182 {
2183 // non-materialized range() list
2184 tv = STACK_TV_BOT(0);
2185 tv->v_type = VAR_NUMBER;
2186 tv->v_lock = 0;
2187 tv->vval.v_number = list_find_nr(
2188 list, idxtv->vval.v_number, NULL);
2189 ++ectx->ec_stack.ga_len;
2190 }
2191 else
2192 {
2193 listitem_T *li = list_find(list,
2194 idxtv->vval.v_number);
2195
2196 copy_tv(&li->li_tv, STACK_TV_BOT(0));
2197 ++ectx->ec_stack.ga_len;
2198 }
2199 }
2200 else if (ltv->v_type == VAR_STRING)
2201 {
2202 char_u *str = ltv->vval.v_string;
2203
2204 // The index is for the last byte of the previous
2205 // character.
2206 ++idxtv->vval.v_number;
2207 if (str == NULL || str[idxtv->vval.v_number] == NUL)
2208 {
2209 // past the end of the string, jump to "endfor"
2210 ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
2211 may_restore_cmdmod(&ectx->ec_funclocal);
2212 }
2213 else
2214 {
2215 int clen = mb_ptr2len(str + idxtv->vval.v_number);
2216
2217 // Push the next character from the string.
2218 tv = STACK_TV_BOT(0);
2219 tv->v_type = VAR_STRING;
2220 tv->vval.v_string = vim_strnsave(
2221 str + idxtv->vval.v_number, clen);
2222 ++ectx->ec_stack.ga_len;
2223 idxtv->vval.v_number += clen - 1;
2224 }
2225 }
2226 else if (ltv->v_type == VAR_BLOB)
2227 {
2228 blob_T *blob = ltv->vval.v_blob;
2229
2230 // When we get here the first time make a copy of the
2231 // blob, so that the iteration still works when it is
2232 // changed.
2233 if (idxtv->vval.v_number == -1 && blob != NULL)
2234 {
2235 blob_copy(blob, ltv);
2236 blob_unref(blob);
2237 blob = ltv->vval.v_blob;
2238 }
2239
2240 // The index is for the previous byte.
2241 ++idxtv->vval.v_number;
2242 if (blob == NULL
2243 || idxtv->vval.v_number >= blob_len(blob))
2244 {
2245 // past the end of the blob, jump to "endfor"
2246 ectx->ec_iidx = iptr->isn_arg.forloop.for_end;
2247 may_restore_cmdmod(&ectx->ec_funclocal);
2248 }
2249 else
2250 {
2251 // Push the next byte from the blob.
2252 tv = STACK_TV_BOT(0);
2253 tv->v_type = VAR_NUMBER;
2254 tv->vval.v_number = blob_get(blob,
2255 idxtv->vval.v_number);
2256 ++ectx->ec_stack.ga_len;
2257 }
2258 }
2259 else
2260 {
2261 semsg(_(e_for_loop_on_str_not_supported),
2262 vartype_name(ltv->v_type));
2263 return FAIL;
2264 }
2265 return OK;
2266}
2267
2268/*
Bram Moolenaar06b77222022-01-25 15:51:56 +00002269 * Load instruction for w:/b:/g:/t: variable.
2270 * "isn_type" is used instead of "iptr->isn_type".
2271 */
2272 static int
2273load_namespace_var(ectx_T *ectx, isntype_T isn_type, isn_T *iptr)
2274{
2275 dictitem_T *di = NULL;
2276 hashtab_T *ht = NULL;
2277 char namespace;
2278
2279 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
2280 return NOTDONE;
2281 switch (isn_type)
2282 {
2283 case ISN_LOADG:
2284 ht = get_globvar_ht();
2285 namespace = 'g';
2286 break;
2287 case ISN_LOADB:
2288 ht = &curbuf->b_vars->dv_hashtab;
2289 namespace = 'b';
2290 break;
2291 case ISN_LOADW:
2292 ht = &curwin->w_vars->dv_hashtab;
2293 namespace = 'w';
2294 break;
2295 case ISN_LOADT:
2296 ht = &curtab->tp_vars->dv_hashtab;
2297 namespace = 't';
2298 break;
2299 default: // Cannot reach here
2300 return NOTDONE;
2301 }
2302 di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
2303
Bram Moolenaar06b77222022-01-25 15:51:56 +00002304 if (di == NULL)
2305 {
Bram Moolenaarfe732552022-02-22 19:39:13 +00002306 if (isn_type == ISN_LOADG)
2307 {
2308 ufunc_T *ufunc = find_func(iptr->isn_arg.string, TRUE);
2309
2310 // g:Something could be a function
2311 if (ufunc != NULL)
2312 {
2313 typval_T *tv = STACK_TV_BOT(0);
2314
2315 ++ectx->ec_stack.ga_len;
2316 tv->v_type = VAR_FUNC;
2317 tv->vval.v_string = alloc(STRLEN(iptr->isn_arg.string) + 3);
2318 if (tv->vval.v_string == NULL)
2319 return FAIL;
2320 STRCPY(tv->vval.v_string, "g:");
2321 STRCPY(tv->vval.v_string + 2, iptr->isn_arg.string);
2322 return OK;
2323 }
2324 }
Bram Moolenaar06b77222022-01-25 15:51:56 +00002325 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarfe732552022-02-22 19:39:13 +00002326 if (vim_strchr(iptr->isn_arg.string, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar06b77222022-01-25 15:51:56 +00002327 // no check if the item exists in the script but
2328 // isn't exported, it is too complicated
Bram Moolenaarfe732552022-02-22 19:39:13 +00002329 semsg(_(e_item_not_found_in_script_str), iptr->isn_arg.string);
Bram Moolenaar06b77222022-01-25 15:51:56 +00002330 else
2331 semsg(_(e_undefined_variable_char_str),
Bram Moolenaarfe732552022-02-22 19:39:13 +00002332 namespace, iptr->isn_arg.string);
Bram Moolenaar06b77222022-01-25 15:51:56 +00002333 return FAIL;
2334 }
2335 else
2336 {
2337 copy_tv(&di->di_tv, STACK_TV_BOT(0));
2338 ++ectx->ec_stack.ga_len;
2339 }
2340 return OK;
2341}
2342
2343/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02002344 * Execute instructions in execution context "ectx".
2345 * Return OK or FAIL;
2346 */
2347 static int
2348exec_instructions(ectx_T *ectx)
2349{
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002350 int ret = FAIL;
2351 int save_trylevel_at_start = ectx->ec_trylevel_at_start;
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02002352 int dict_stack_len_at_start = dict_stack.ga_len;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01002353
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02002354 // Start execution at the first instruction.
Bram Moolenaar4c137212021-04-19 16:48:48 +02002355 ectx->ec_iidx = 0;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01002356
Bram Moolenaarff652882021-05-16 15:24:49 +02002357 // Only catch exceptions in this instruction list.
2358 ectx->ec_trylevel_at_start = trylevel;
2359
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002360 for (;;)
2361 {
Bram Moolenaara7490192021-07-22 12:26:14 +02002362 static int breakcheck_count = 0; // using "static" makes it faster
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002363 isn_T *iptr;
Bram Moolenaara7490192021-07-22 12:26:14 +02002364 typval_T *tv;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002365
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002366 if (unlikely(++breakcheck_count >= 100))
Bram Moolenaar270d0382020-05-15 21:42:53 +02002367 {
2368 line_breakcheck();
2369 breakcheck_count = 0;
2370 }
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002371 if (unlikely(got_int))
Bram Moolenaar20431c92020-03-20 18:39:46 +01002372 {
2373 // Turn CTRL-C into an exception.
2374 got_int = FALSE;
Bram Moolenaar97acfc72020-03-22 13:44:28 +01002375 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002376 goto theend;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002377 did_throw = TRUE;
2378 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002379
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002380 if (unlikely(did_emsg && msg_list != NULL && *msg_list != NULL))
Bram Moolenaara26b9702020-04-18 19:53:28 +02002381 {
2382 // Turn an error message into an exception.
2383 did_emsg = FALSE;
2384 if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002385 goto theend;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002386 did_throw = TRUE;
2387 *msg_list = NULL;
2388 }
2389
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002390 if (unlikely(did_throw))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002391 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02002392 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002393 trycmd_T *trycmd = NULL;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002394 int index = trystack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395
2396 // An exception jumps to the first catch, finally, or returns from
2397 // the current function.
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002398 while (index > 0)
2399 {
2400 trycmd = ((trycmd_T *)trystack->ga_data) + index - 1;
Bram Moolenaar834193a2021-06-30 20:39:15 +02002401 if (!trycmd->tcd_in_catch || trycmd->tcd_finally_idx != 0)
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002402 break;
2403 // In the catch and finally block of this try we have to go up
2404 // one level.
2405 --index;
2406 trycmd = NULL;
2407 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02002408 if (trycmd != NULL && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002409 {
Bram Moolenaar834193a2021-06-30 20:39:15 +02002410 if (trycmd->tcd_in_catch)
2411 {
2412 // exception inside ":catch", jump to ":finally" once
2413 ectx->ec_iidx = trycmd->tcd_finally_idx;
2414 trycmd->tcd_finally_idx = 0;
2415 }
2416 else
2417 // jump to first ":catch"
2418 ectx->ec_iidx = trycmd->tcd_catch_idx;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002419 trycmd->tcd_in_catch = TRUE;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02002420 did_throw = FALSE; // don't come back here until :endtry
2421 trycmd->tcd_did_throw = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002422 }
2423 else
2424 {
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02002425 // Not inside try or need to return from current functions.
2426 // Push a dummy return value.
Bram Moolenaar35578162021-08-02 19:10:38 +02002427 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002428 goto theend;
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02002429 tv = STACK_TV_BOT(0);
2430 tv->v_type = VAR_NUMBER;
2431 tv->vval.v_number = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002432 ++ectx->ec_stack.ga_len;
2433 if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002434 {
Bram Moolenaarcdd70f02020-08-13 21:40:18 +02002435 // At the toplevel we are done.
Bram Moolenaar257cc5e2020-02-19 17:06:11 +01002436 need_rethrow = TRUE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002437 if (handle_closure_in_use(ectx, FALSE) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002438 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002439 goto done;
2440 }
2441
Bram Moolenaar4c137212021-04-19 16:48:48 +02002442 if (func_return(ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002443 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002444 }
2445 continue;
2446 }
2447
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00002448 /*
2449 * Big switch on the instruction. Most compilers will be turning this
2450 * into an efficient lookup table, since the "case" values are an enum
2451 * with sequential numbers. It may look ugly, but it should be the
2452 * most efficient way.
2453 */
Bram Moolenaar4c137212021-04-19 16:48:48 +02002454 iptr = &ectx->ec_instr[ectx->ec_iidx++];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002455 switch (iptr->isn_type)
2456 {
2457 // execute Ex command line
2458 case ISN_EXEC:
Bram Moolenaaraacc9662021-08-13 19:40:51 +02002459 if (exec_command(iptr) == FAIL)
2460 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002461 break;
2462
Bram Moolenaar20677332021-06-06 17:02:53 +02002463 // execute Ex command line split at NL characters.
2464 case ISN_EXEC_SPLIT:
2465 {
2466 source_cookie_T cookie;
Bram Moolenaar518df272021-06-06 17:34:13 +02002467 char_u *line;
Bram Moolenaar20677332021-06-06 17:02:53 +02002468
2469 SOURCING_LNUM = iptr->isn_lnum;
2470 CLEAR_FIELD(cookie);
2471 cookie.sourcing_lnum = iptr->isn_lnum - 1;
2472 cookie.nextline = iptr->isn_arg.string;
Bram Moolenaar518df272021-06-06 17:34:13 +02002473 line = get_split_sourceline(0, &cookie, 0, 0);
2474 if (do_cmdline(line,
Bram Moolenaar20677332021-06-06 17:02:53 +02002475 get_split_sourceline, &cookie,
2476 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED)
2477 == FAIL
2478 || did_emsg)
Bram Moolenaar518df272021-06-06 17:34:13 +02002479 {
2480 vim_free(line);
Bram Moolenaar20677332021-06-06 17:02:53 +02002481 goto on_error;
Bram Moolenaar518df272021-06-06 17:34:13 +02002482 }
2483 vim_free(line);
Bram Moolenaar20677332021-06-06 17:02:53 +02002484 }
2485 break;
2486
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00002487 // execute Ex command line that is only a range
2488 case ISN_EXECRANGE:
2489 {
2490 exarg_T ea;
2491 char *error = NULL;
2492
2493 CLEAR_FIELD(ea);
2494 ea.cmdidx = CMD_SIZE;
2495 ea.addr_type = ADDR_LINES;
2496 ea.cmd = iptr->isn_arg.string;
Bram Moolenaar0c7f2612022-02-17 19:44:07 +00002497 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00002498 parse_cmd_address(&ea, &error, FALSE);
Bram Moolenaar01a4dcb2021-12-04 13:15:10 +00002499 if (ea.cmd == NULL)
2500 goto on_error;
Bram Moolenaar0c7f2612022-02-17 19:44:07 +00002501 // error is always NULL when using ADDR_LINES
2502 error = ex_range_without_command(&ea);
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00002503 if (error != NULL)
2504 {
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00002505 emsg(error);
2506 goto on_error;
2507 }
2508 }
2509 break;
2510
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02002511 // Evaluate an expression with legacy syntax, push it onto the
2512 // stack.
2513 case ISN_LEGACY_EVAL:
2514 {
2515 char_u *arg = iptr->isn_arg.string;
2516 int res;
2517 int save_flags = cmdmod.cmod_flags;
2518
Bram Moolenaar35578162021-08-02 19:10:38 +02002519 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002520 goto theend;
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02002521 tv = STACK_TV_BOT(0);
2522 init_tv(tv);
2523 cmdmod.cmod_flags |= CMOD_LEGACY;
2524 res = eval0(arg, tv, NULL, &EVALARG_EVALUATE);
2525 cmdmod.cmod_flags = save_flags;
2526 if (res == FAIL)
2527 goto on_error;
2528 ++ectx->ec_stack.ga_len;
2529 }
2530 break;
2531
Bram Moolenaarf18332f2021-05-07 17:55:55 +02002532 // push typeval VAR_INSTR with instructions to be executed
2533 case ISN_INSTR:
2534 {
Bram Moolenaar35578162021-08-02 19:10:38 +02002535 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002536 goto theend;
Bram Moolenaarf18332f2021-05-07 17:55:55 +02002537 tv = STACK_TV_BOT(0);
2538 tv->vval.v_instr = ALLOC_ONE(instr_T);
2539 if (tv->vval.v_instr == NULL)
2540 goto on_error;
2541 ++ectx->ec_stack.ga_len;
2542
2543 tv->v_type = VAR_INSTR;
2544 tv->vval.v_instr->instr_ectx = ectx;
2545 tv->vval.v_instr->instr_instr = iptr->isn_arg.instr;
2546 }
2547 break;
2548
Bram Moolenaar4c137212021-04-19 16:48:48 +02002549 // execute :substitute with an expression
2550 case ISN_SUBSTITUTE:
2551 {
2552 subs_T *subs = &iptr->isn_arg.subs;
2553 source_cookie_T cookie;
2554 struct subs_expr_S *save_instr = substitute_instr;
2555 struct subs_expr_S subs_instr;
2556 int res;
2557
2558 subs_instr.subs_ectx = ectx;
2559 subs_instr.subs_instr = subs->subs_instr;
2560 subs_instr.subs_status = OK;
2561 substitute_instr = &subs_instr;
2562
2563 SOURCING_LNUM = iptr->isn_lnum;
2564 // This is very much like ISN_EXEC
2565 CLEAR_FIELD(cookie);
2566 cookie.sourcing_lnum = iptr->isn_lnum - 1;
2567 res = do_cmdline(subs->subs_cmd,
2568 getsourceline, &cookie,
2569 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
2570 substitute_instr = save_instr;
2571
2572 if (res == FAIL || did_emsg
2573 || subs_instr.subs_status == FAIL)
2574 goto on_error;
2575 }
2576 break;
2577
2578 case ISN_FINISH:
2579 goto done;
2580
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02002581 case ISN_REDIRSTART:
2582 // create a dummy entry for var_redir_str()
2583 if (alloc_redir_lval() == FAIL)
2584 goto on_error;
2585
2586 // The output is stored in growarray "redir_ga" until
2587 // redirection ends.
2588 init_redir_ga();
2589 redir_vname = 1;
2590 break;
2591
2592 case ISN_REDIREND:
2593 {
2594 char_u *res = get_clear_redir_ga();
2595
2596 // End redirection, put redirected text on the stack.
2597 clear_redir_lval();
2598 redir_vname = 0;
2599
Bram Moolenaar35578162021-08-02 19:10:38 +02002600 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02002601 {
2602 vim_free(res);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002603 goto theend;
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02002604 }
2605 tv = STACK_TV_BOT(0);
2606 tv->v_type = VAR_STRING;
2607 tv->vval.v_string = res;
2608 ++ectx->ec_stack.ga_len;
2609 }
2610 break;
2611
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02002612 case ISN_CEXPR_AUCMD:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02002613#ifdef FEAT_QUICKFIX
Bram Moolenaar397a87a2022-03-20 21:14:15 +00002614 force_abort = TRUE;
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02002615 if (trigger_cexpr_autocmd(iptr->isn_arg.number) == FAIL)
2616 goto on_error;
Bram Moolenaar397a87a2022-03-20 21:14:15 +00002617 force_abort = FALSE;
Bram Moolenaarb7c97812021-05-05 22:51:39 +02002618#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02002619 break;
2620
2621 case ISN_CEXPR_CORE:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02002622#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02002623 {
2624 exarg_T ea;
2625 int res;
2626
2627 CLEAR_FIELD(ea);
2628 ea.cmdidx = iptr->isn_arg.cexpr.cexpr_ref->cer_cmdidx;
2629 ea.forceit = iptr->isn_arg.cexpr.cexpr_ref->cer_forceit;
2630 ea.cmdlinep = &iptr->isn_arg.cexpr.cexpr_ref->cer_cmdline;
2631 --ectx->ec_stack.ga_len;
2632 tv = STACK_TV_BOT(0);
2633 res = cexpr_core(&ea, tv);
2634 clear_tv(tv);
2635 if (res == FAIL)
2636 goto on_error;
2637 }
Bram Moolenaarb7c97812021-05-05 22:51:39 +02002638#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02002639 break;
2640
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02002641 // execute Ex command from pieces on the stack
2642 case ISN_EXECCONCAT:
2643 {
2644 int count = iptr->isn_arg.number;
Bram Moolenaar7f6f56f2020-04-30 20:21:43 +02002645 size_t len = 0;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02002646 int pass;
2647 int i;
2648 char_u *cmd = NULL;
2649 char_u *str;
2650
2651 for (pass = 1; pass <= 2; ++pass)
2652 {
2653 for (i = 0; i < count; ++i)
2654 {
2655 tv = STACK_TV_BOT(i - count);
2656 str = tv->vval.v_string;
2657 if (str != NULL && *str != NUL)
2658 {
2659 if (pass == 2)
2660 STRCPY(cmd + len, str);
2661 len += STRLEN(str);
2662 }
2663 if (pass == 2)
2664 clear_tv(tv);
2665 }
2666 if (pass == 1)
2667 {
2668 cmd = alloc(len + 1);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02002669 if (unlikely(cmd == NULL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002670 goto theend;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02002671 len = 0;
2672 }
2673 }
2674
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02002675 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02002676 do_cmdline_cmd(cmd);
2677 vim_free(cmd);
2678 }
2679 break;
2680
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002681 // execute :echo {string} ...
2682 case ISN_ECHO:
2683 {
2684 int count = iptr->isn_arg.echo.echo_count;
2685 int atstart = TRUE;
2686 int needclr = TRUE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002687 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002688
2689 for (idx = 0; idx < count; ++idx)
2690 {
2691 tv = STACK_TV_BOT(idx - count);
2692 echo_one(tv, iptr->isn_arg.echo.echo_with_white,
2693 &atstart, &needclr);
2694 clear_tv(tv);
2695 }
Bram Moolenaare0807ea2020-02-20 22:18:06 +01002696 if (needclr)
2697 msg_clr_eos();
Bram Moolenaar4c137212021-04-19 16:48:48 +02002698 ectx->ec_stack.ga_len -= count;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002699 }
2700 break;
2701
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002702 // :execute {string} ...
2703 // :echomsg {string} ...
Bram Moolenaar7de62622021-08-07 15:05:47 +02002704 // :echoconsole {string} ...
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002705 // :echoerr {string} ...
Bram Moolenaarad39c092020-02-26 18:23:43 +01002706 case ISN_EXECUTE:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002707 case ISN_ECHOMSG:
Bram Moolenaar7de62622021-08-07 15:05:47 +02002708 case ISN_ECHOCONSOLE:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002709 case ISN_ECHOERR:
Bram Moolenaarad39c092020-02-26 18:23:43 +01002710 {
2711 int count = iptr->isn_arg.number;
2712 garray_T ga;
2713 char_u buf[NUMBUFLEN];
2714 char_u *p;
2715 int len;
2716 int failed = FALSE;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002717 int idx;
Bram Moolenaarad39c092020-02-26 18:23:43 +01002718
2719 ga_init2(&ga, 1, 80);
2720 for (idx = 0; idx < count; ++idx)
2721 {
2722 tv = STACK_TV_BOT(idx - count);
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02002723 if (iptr->isn_type == ISN_EXECUTE)
Bram Moolenaarad39c092020-02-26 18:23:43 +01002724 {
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02002725 if (tv->v_type == VAR_CHANNEL
2726 || tv->v_type == VAR_JOB)
2727 {
2728 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar68db9962021-05-09 23:19:22 +02002729 semsg(_(e_using_invalid_value_as_string_str),
2730 vartype_name(tv->v_type));
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02002731 break;
2732 }
2733 else
2734 p = tv_get_string_buf(tv, buf);
Bram Moolenaarad39c092020-02-26 18:23:43 +01002735 }
2736 else
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02002737 p = tv_stringify(tv, buf);
Bram Moolenaarad39c092020-02-26 18:23:43 +01002738
2739 len = (int)STRLEN(p);
Bram Moolenaar35578162021-08-02 19:10:38 +02002740 if (GA_GROW_FAILS(&ga, len + 2))
Bram Moolenaarad39c092020-02-26 18:23:43 +01002741 failed = TRUE;
2742 else
2743 {
2744 if (ga.ga_len > 0)
2745 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
2746 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
2747 ga.ga_len += len;
2748 }
2749 clear_tv(tv);
2750 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02002751 ectx->ec_stack.ga_len -= count;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02002752 if (failed)
Bram Moolenaarc71ee822020-11-21 11:45:50 +01002753 {
2754 ga_clear(&ga);
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02002755 goto on_error;
Bram Moolenaarc71ee822020-11-21 11:45:50 +01002756 }
Bram Moolenaarad39c092020-02-26 18:23:43 +01002757
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02002758 if (ga.ga_data != NULL)
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002759 {
2760 if (iptr->isn_type == ISN_EXECUTE)
Bram Moolenaar430deb12020-08-23 16:29:11 +02002761 {
2762 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002763 do_cmdline_cmd((char_u *)ga.ga_data);
Bram Moolenaareeece9e2020-11-20 19:26:48 +01002764 if (did_emsg)
Bram Moolenaarc71ee822020-11-21 11:45:50 +01002765 {
2766 ga_clear(&ga);
Bram Moolenaareeece9e2020-11-20 19:26:48 +01002767 goto on_error;
Bram Moolenaarc71ee822020-11-21 11:45:50 +01002768 }
Bram Moolenaar430deb12020-08-23 16:29:11 +02002769 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002770 else
2771 {
2772 msg_sb_eol();
2773 if (iptr->isn_type == ISN_ECHOMSG)
2774 {
2775 msg_attr(ga.ga_data, echo_attr);
2776 out_flush();
2777 }
Bram Moolenaar7de62622021-08-07 15:05:47 +02002778 else if (iptr->isn_type == ISN_ECHOCONSOLE)
2779 {
2780 ui_write(ga.ga_data, (int)STRLEN(ga.ga_data),
2781 TRUE);
2782 ui_write((char_u *)"\r\n", 2, TRUE);
2783 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002784 else
2785 {
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002786 SOURCING_LNUM = iptr->isn_lnum;
2787 emsg(ga.ga_data);
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002788 }
2789 }
2790 }
Bram Moolenaarad39c092020-02-26 18:23:43 +01002791 ga_clear(&ga);
2792 }
2793 break;
2794
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002795 // load local variable or argument
2796 case ISN_LOAD:
Bram Moolenaar35578162021-08-02 19:10:38 +02002797 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002798 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002799 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02002800 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002801 break;
2802
2803 // load v: variable
2804 case ISN_LOADV:
Bram Moolenaar35578162021-08-02 19:10:38 +02002805 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002806 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002807 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02002808 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002809 break;
2810
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002811 // load s: variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002812 case ISN_LOADSCRIPT:
2813 {
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01002814 scriptref_T *sref = iptr->isn_arg.script.scriptref;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002815 svar_T *sv;
2816
Bram Moolenaar6db660b2021-08-01 14:08:54 +02002817 sv = get_script_svar(sref, ectx->ec_dfunc_idx);
Bram Moolenaar07a65d22020-12-26 20:09:15 +01002818 if (sv == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002819 goto theend;
Bram Moolenaar3beaf9c2020-12-18 17:23:14 +01002820 allocate_if_null(sv->sv_tv);
Bram Moolenaar35578162021-08-02 19:10:38 +02002821 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002822 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002823 copy_tv(sv->sv_tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02002824 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002825 }
2826 break;
2827
2828 // load s: variable in old script
2829 case ISN_LOADS:
2830 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002831 hashtab_T *ht = &SCRIPT_VARS(
2832 iptr->isn_arg.loadstore.ls_sid);
2833 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002834 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002835
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002836 if (di == NULL)
2837 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002838 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002839 semsg(_(e_undefined_variable_str), name);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002840 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002841 }
2842 else
2843 {
Bram Moolenaar35578162021-08-02 19:10:38 +02002844 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002845 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002846 copy_tv(&di->di_tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02002847 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002848 }
2849 }
2850 break;
2851
Bram Moolenaard3aac292020-04-19 14:32:17 +02002852 // load g:/b:/w:/t: variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002853 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02002854 case ISN_LOADB:
2855 case ISN_LOADW:
2856 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002857 {
Bram Moolenaar06b77222022-01-25 15:51:56 +00002858 int res = load_namespace_var(ectx, iptr->isn_type, iptr);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002859
Bram Moolenaar06b77222022-01-25 15:51:56 +00002860 if (res == NOTDONE)
Bram Moolenaarcbbc48f2022-01-18 12:58:28 +00002861 goto theend;
Bram Moolenaar06b77222022-01-25 15:51:56 +00002862 if (res == FAIL)
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002863 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002864 }
Bram Moolenaar06b77222022-01-25 15:51:56 +00002865
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002866 break;
2867
Bram Moolenaar03290b82020-12-19 16:30:44 +01002868 // load autoload variable
2869 case ISN_LOADAUTO:
2870 {
2871 char_u *name = iptr->isn_arg.string;
2872
Bram Moolenaar35578162021-08-02 19:10:38 +02002873 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002874 goto theend;
Bram Moolenaar03290b82020-12-19 16:30:44 +01002875 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaard5f400c2022-01-06 21:10:28 +00002876 if (eval_variable(name, (int)STRLEN(name), 0,
Bram Moolenaarcb4e80f2021-03-13 20:57:19 +01002877 STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL)
Bram Moolenaar03290b82020-12-19 16:30:44 +01002878 goto on_error;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002879 ++ectx->ec_stack.ga_len;
Bram Moolenaar03290b82020-12-19 16:30:44 +01002880 }
2881 break;
2882
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002883 // load g:/b:/w:/t: namespace
2884 case ISN_LOADGDICT:
2885 case ISN_LOADBDICT:
2886 case ISN_LOADWDICT:
2887 case ISN_LOADTDICT:
2888 {
2889 dict_T *d = NULL;
2890
2891 switch (iptr->isn_type)
2892 {
Bram Moolenaar682d0a12020-07-19 20:48:59 +02002893 case ISN_LOADGDICT: d = get_globvar_dict(); break;
2894 case ISN_LOADBDICT: d = curbuf->b_vars; break;
2895 case ISN_LOADWDICT: d = curwin->w_vars; break;
2896 case ISN_LOADTDICT: d = curtab->tp_vars; break;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002897 default: // Cannot reach here
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002898 goto theend;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002899 }
Bram Moolenaar35578162021-08-02 19:10:38 +02002900 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002901 goto theend;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002902 tv = STACK_TV_BOT(0);
2903 tv->v_type = VAR_DICT;
2904 tv->v_lock = 0;
2905 tv->vval.v_dict = d;
Bram Moolenaar1bd3cb22021-02-24 12:27:31 +01002906 ++d->dv_refcount;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002907 ++ectx->ec_stack.ga_len;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002908 }
2909 break;
2910
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002911 // load &option
2912 case ISN_LOADOPT:
2913 {
2914 typval_T optval;
2915 char_u *name = iptr->isn_arg.string;
2916
Bram Moolenaara8c17702020-04-01 21:17:24 +02002917 // This is not expected to fail, name is checked during
2918 // compilation: don't set SOURCING_LNUM.
Bram Moolenaar35578162021-08-02 19:10:38 +02002919 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002920 goto theend;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002921 if (eval_option(&name, &optval, TRUE) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002922 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002923 *STACK_TV_BOT(0) = optval;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002924 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002925 }
2926 break;
2927
2928 // load $ENV
2929 case ISN_LOADENV:
2930 {
2931 typval_T optval;
2932 char_u *name = iptr->isn_arg.string;
2933
Bram Moolenaar35578162021-08-02 19:10:38 +02002934 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002935 goto theend;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002936 // name is always valid, checked when compiling
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02002937 (void)eval_env_var(&name, &optval, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002938 *STACK_TV_BOT(0) = optval;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002939 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002940 }
2941 break;
2942
2943 // load @register
2944 case ISN_LOADREG:
Bram Moolenaar35578162021-08-02 19:10:38 +02002945 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002946 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002947 tv = STACK_TV_BOT(0);
2948 tv->v_type = VAR_STRING;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002949 tv->v_lock = 0;
Bram Moolenaar1e021e62020-10-16 20:25:23 +02002950 // This may result in NULL, which should be equivalent to an
2951 // empty string.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002952 tv->vval.v_string = get_reg_contents(
2953 iptr->isn_arg.number, GREG_EXPR_SRC);
Bram Moolenaar4c137212021-04-19 16:48:48 +02002954 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002955 break;
2956
2957 // store local variable
2958 case ISN_STORE:
Bram Moolenaar4c137212021-04-19 16:48:48 +02002959 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002960 tv = STACK_TV_VAR(iptr->isn_arg.number);
2961 clear_tv(tv);
2962 *tv = *STACK_TV_BOT(0);
2963 break;
2964
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002965 // store s: variable in old script
2966 case ISN_STORES:
2967 {
2968 hashtab_T *ht = &SCRIPT_VARS(
2969 iptr->isn_arg.loadstore.ls_sid);
2970 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002971 dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002972
Bram Moolenaar4c137212021-04-19 16:48:48 +02002973 --ectx->ec_stack.ga_len;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002974 if (di == NULL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002975 store_var(name, STACK_TV_BOT(0));
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002976 else
2977 {
Bram Moolenaardcf29ac2021-04-02 14:44:02 +02002978 SOURCING_LNUM = iptr->isn_lnum;
2979 if (var_check_permission(di, name) == FAIL)
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02002980 {
2981 clear_tv(STACK_TV_BOT(0));
Bram Moolenaardcf29ac2021-04-02 14:44:02 +02002982 goto on_error;
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02002983 }
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002984 clear_tv(&di->di_tv);
2985 di->di_tv = *STACK_TV_BOT(0);
2986 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002987 }
2988 break;
2989
2990 // store script-local variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002991 case ISN_STORESCRIPT:
2992 {
Bram Moolenaar07a65d22020-12-26 20:09:15 +01002993 scriptref_T *sref = iptr->isn_arg.script.scriptref;
2994 svar_T *sv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002995
Bram Moolenaar6db660b2021-08-01 14:08:54 +02002996 sv = get_script_svar(sref, ectx->ec_dfunc_idx);
Bram Moolenaar07a65d22020-12-26 20:09:15 +01002997 if (sv == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02002998 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02002999 --ectx->ec_stack.ga_len;
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02003000
3001 // "const" and "final" are checked at compile time, locking
3002 // the value needs to be checked here.
3003 SOURCING_LNUM = iptr->isn_lnum;
3004 if (value_check_lock(sv->sv_tv->v_lock, sv->sv_name, FALSE))
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02003005 {
3006 clear_tv(STACK_TV_BOT(0));
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02003007 goto on_error;
Bram Moolenaar6e50ec22021-04-03 19:32:44 +02003008 }
Bram Moolenaarf5906aa2021-04-02 14:35:15 +02003009
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003010 clear_tv(sv->sv_tv);
3011 *sv->sv_tv = *STACK_TV_BOT(0);
3012 }
3013 break;
3014
3015 // store option
3016 case ISN_STOREOPT:
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003017 case ISN_STOREFUNCOPT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003018 {
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003019 char_u *opt_name = iptr->isn_arg.storeopt.so_name;
3020 int opt_flags = iptr->isn_arg.storeopt.so_flags;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003021 long n = 0;
3022 char_u *s = NULL;
3023 char *msg;
Bram Moolenaar2ef91562021-12-11 16:14:07 +00003024 char_u numbuf[NUMBUFLEN];
3025 char_u *tofree = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003026
Bram Moolenaar4c137212021-04-19 16:48:48 +02003027 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003028 tv = STACK_TV_BOT(0);
3029 if (tv->v_type == VAR_STRING)
Bram Moolenaar97a2af32020-01-28 22:52:48 +01003030 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003031 s = tv->vval.v_string;
Bram Moolenaar97a2af32020-01-28 22:52:48 +01003032 if (s == NULL)
3033 s = (char_u *)"";
3034 }
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003035 else if (iptr->isn_type == ISN_STOREFUNCOPT)
3036 {
3037 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar2ef91562021-12-11 16:14:07 +00003038 // If the option can be set to a function reference or
3039 // a lambda and the passed value is a function
3040 // reference, then convert it to the name (string) of
3041 // the function reference.
3042 s = tv2string(tv, &tofree, numbuf, 0);
3043 if (s == NULL || *s == NUL)
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003044 {
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003045 // cannot happen?
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003046 clear_tv(tv);
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003047 vim_free(tofree);
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003048 goto on_error;
3049 }
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003050 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003051 else
Bram Moolenaara6e67e42020-05-15 23:36:40 +02003052 // must be VAR_NUMBER, CHECKTYPE makes sure
3053 n = tv->vval.v_number;
Bram Moolenaardcb53be2021-12-09 14:23:43 +00003054 msg = set_option_value(opt_name, n, s, opt_flags);
Bram Moolenaare75ba262020-05-16 15:43:31 +02003055 clear_tv(tv);
Bram Moolenaar2ef91562021-12-11 16:14:07 +00003056 vim_free(tofree);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003057 if (msg != NULL)
3058 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003059 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003060 emsg(_(msg));
Bram Moolenaare8593122020-07-18 15:17:02 +02003061 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003062 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003063 }
3064 break;
3065
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003066 // store $ENV
3067 case ISN_STOREENV:
Bram Moolenaar4c137212021-04-19 16:48:48 +02003068 --ectx->ec_stack.ga_len;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003069 tv = STACK_TV_BOT(0);
3070 vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
3071 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003072 break;
3073
3074 // store @r
3075 case ISN_STOREREG:
3076 {
3077 int reg = iptr->isn_arg.number;
3078
Bram Moolenaar4c137212021-04-19 16:48:48 +02003079 --ectx->ec_stack.ga_len;
Bram Moolenaar401d9ff2020-02-19 18:14:44 +01003080 tv = STACK_TV_BOT(0);
Bram Moolenaar74f4a962021-06-17 21:03:07 +02003081 write_reg_contents(reg, tv_get_string(tv), -1, FALSE);
Bram Moolenaar401d9ff2020-02-19 18:14:44 +01003082 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003083 }
3084 break;
3085
3086 // store v: variable
3087 case ISN_STOREV:
Bram Moolenaar4c137212021-04-19 16:48:48 +02003088 --ectx->ec_stack.ga_len;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003089 if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
3090 == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02003091 // should not happen, type is checked when compiling
3092 goto on_error;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003093 break;
3094
Bram Moolenaard3aac292020-04-19 14:32:17 +02003095 // store g:/b:/w:/t: variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003096 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02003097 case ISN_STOREB:
3098 case ISN_STOREW:
3099 case ISN_STORET:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003100 {
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01003101 dictitem_T *di;
3102 hashtab_T *ht;
3103 char_u *name = iptr->isn_arg.string + 2;
3104
Bram Moolenaard3aac292020-04-19 14:32:17 +02003105 switch (iptr->isn_type)
3106 {
3107 case ISN_STOREG:
3108 ht = get_globvar_ht();
3109 break;
3110 case ISN_STOREB:
3111 ht = &curbuf->b_vars->dv_hashtab;
3112 break;
3113 case ISN_STOREW:
3114 ht = &curwin->w_vars->dv_hashtab;
3115 break;
3116 case ISN_STORET:
3117 ht = &curtab->tp_vars->dv_hashtab;
3118 break;
3119 default: // Cannot reach here
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003120 goto theend;
Bram Moolenaard3aac292020-04-19 14:32:17 +02003121 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003122
Bram Moolenaar4c137212021-04-19 16:48:48 +02003123 --ectx->ec_stack.ga_len;
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01003124 di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003125 if (di == NULL)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003126 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003127 else
3128 {
Bram Moolenaar3bdc90b2020-12-22 20:35:40 +01003129 SOURCING_LNUM = iptr->isn_lnum;
3130 if (var_check_permission(di, name) == FAIL)
3131 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003132 clear_tv(&di->di_tv);
3133 di->di_tv = *STACK_TV_BOT(0);
3134 }
3135 }
3136 break;
3137
Bram Moolenaar03290b82020-12-19 16:30:44 +01003138 // store an autoload variable
3139 case ISN_STOREAUTO:
3140 SOURCING_LNUM = iptr->isn_lnum;
3141 set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE);
3142 clear_tv(STACK_TV_BOT(-1));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003143 --ectx->ec_stack.ga_len;
Bram Moolenaar03290b82020-12-19 16:30:44 +01003144 break;
3145
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003146 // store number in local variable
3147 case ISN_STORENR:
Bram Moolenaara471eea2020-03-04 22:20:26 +01003148 tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003149 clear_tv(tv);
3150 tv->v_type = VAR_NUMBER;
Bram Moolenaara471eea2020-03-04 22:20:26 +01003151 tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003152 break;
3153
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01003154 // store value in list or dict variable
3155 case ISN_STOREINDEX:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003156 {
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003157 int res = execute_storeindex(iptr, ectx);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003158
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003159 if (res == FAIL)
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02003160 goto on_error;
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003161 if (res == NOTDONE)
3162 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003163 }
3164 break;
3165
Bram Moolenaarea5c8982022-02-17 14:42:02 +00003166 // store value in list or blob range
Bram Moolenaar68452172021-04-12 21:21:02 +02003167 case ISN_STORERANGE:
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003168 if (execute_storerange(iptr, ectx) == FAIL)
3169 goto on_error;
Bram Moolenaar68452172021-04-12 21:21:02 +02003170 break;
3171
Bram Moolenaar0186e582021-01-10 18:33:11 +01003172 // load or store variable or argument from outer scope
3173 case ISN_LOADOUTER:
3174 case ISN_STOREOUTER:
3175 {
3176 int depth = iptr->isn_arg.outer.outer_depth;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02003177 outer_T *outer = ectx->ec_outer_ref == NULL ? NULL
3178 : ectx->ec_outer_ref->or_outer;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003179
3180 while (depth > 1 && outer != NULL)
3181 {
3182 outer = outer->out_up;
3183 --depth;
3184 }
3185 if (outer == NULL)
3186 {
3187 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar69c76172021-12-02 16:38:52 +00003188 if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx
3189 || ectx->ec_outer_ref == NULL)
3190 // Possibly :def function called from legacy
3191 // context.
3192 emsg(_(e_closure_called_from_invalid_context));
3193 else
3194 iemsg("LOADOUTER depth more than scope levels");
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003195 goto theend;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003196 }
3197 tv = ((typval_T *)outer->out_stack->ga_data)
3198 + outer->out_frame_idx + STACK_FRAME_SIZE
3199 + iptr->isn_arg.outer.outer_idx;
3200 if (iptr->isn_type == ISN_LOADOUTER)
3201 {
Bram Moolenaar35578162021-08-02 19:10:38 +02003202 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003203 goto theend;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003204 copy_tv(tv, STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02003205 ++ectx->ec_stack.ga_len;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003206 }
3207 else
3208 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003209 --ectx->ec_stack.ga_len;
Bram Moolenaar0186e582021-01-10 18:33:11 +01003210 clear_tv(tv);
3211 *tv = *STACK_TV_BOT(0);
3212 }
3213 }
3214 break;
3215
Bram Moolenaar752fc692021-01-04 21:57:11 +01003216 // unlet item in list or dict variable
3217 case ISN_UNLETINDEX:
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003218 if (execute_unletindex(iptr, ectx) == FAIL)
3219 goto on_error;
Bram Moolenaar752fc692021-01-04 21:57:11 +01003220 break;
3221
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01003222 // unlet range of items in list variable
3223 case ISN_UNLETRANGE:
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003224 if (execute_unletrange(iptr, ectx) == FAIL)
3225 goto on_error;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01003226 break;
3227
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003228 // push constant
3229 case ISN_PUSHNR:
3230 case ISN_PUSHBOOL:
3231 case ISN_PUSHSPEC:
3232 case ISN_PUSHF:
3233 case ISN_PUSHS:
3234 case ISN_PUSHBLOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003235 case ISN_PUSHFUNC:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003236 case ISN_PUSHCHANNEL:
3237 case ISN_PUSHJOB:
Bram Moolenaar35578162021-08-02 19:10:38 +02003238 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003239 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003240 tv = STACK_TV_BOT(0);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003241 tv->v_lock = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003242 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003243 switch (iptr->isn_type)
3244 {
3245 case ISN_PUSHNR:
3246 tv->v_type = VAR_NUMBER;
3247 tv->vval.v_number = iptr->isn_arg.number;
3248 break;
3249 case ISN_PUSHBOOL:
3250 tv->v_type = VAR_BOOL;
3251 tv->vval.v_number = iptr->isn_arg.number;
3252 break;
3253 case ISN_PUSHSPEC:
3254 tv->v_type = VAR_SPECIAL;
3255 tv->vval.v_number = iptr->isn_arg.number;
3256 break;
3257#ifdef FEAT_FLOAT
3258 case ISN_PUSHF:
3259 tv->v_type = VAR_FLOAT;
3260 tv->vval.v_float = iptr->isn_arg.fnumber;
3261 break;
3262#endif
3263 case ISN_PUSHBLOB:
3264 blob_copy(iptr->isn_arg.blob, tv);
3265 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003266 case ISN_PUSHFUNC:
3267 tv->v_type = VAR_FUNC;
Bram Moolenaar087d2e12020-03-01 15:36:42 +01003268 if (iptr->isn_arg.string == NULL)
3269 tv->vval.v_string = NULL;
3270 else
3271 tv->vval.v_string =
3272 vim_strsave(iptr->isn_arg.string);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003273 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003274 case ISN_PUSHCHANNEL:
3275#ifdef FEAT_JOB_CHANNEL
3276 tv->v_type = VAR_CHANNEL;
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003277 tv->vval.v_channel = NULL;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003278#endif
3279 break;
3280 case ISN_PUSHJOB:
3281#ifdef FEAT_JOB_CHANNEL
3282 tv->v_type = VAR_JOB;
Bram Moolenaar397a87a2022-03-20 21:14:15 +00003283 tv->vval.v_job = NULL;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003284#endif
3285 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003286 default:
3287 tv->v_type = VAR_STRING;
Bram Moolenaarf8691002022-03-10 12:20:53 +00003288 tv->vval.v_string = iptr->isn_arg.string == NULL
3289 ? NULL : vim_strsave(iptr->isn_arg.string);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003290 }
3291 break;
3292
Bram Moolenaar06b77222022-01-25 15:51:56 +00003293 case ISN_AUTOLOAD:
3294 {
3295 char_u *name = iptr->isn_arg.string;
3296
3297 (void)script_autoload(name, FALSE);
3298 if (find_func(name, TRUE))
3299 {
3300 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3301 goto theend;
3302 tv = STACK_TV_BOT(0);
3303 tv->v_lock = 0;
3304 ++ectx->ec_stack.ga_len;
3305 tv->v_type = VAR_FUNC;
3306 tv->vval.v_string = vim_strsave(name);
3307 }
3308 else
3309 {
3310 int res = load_namespace_var(ectx, ISN_LOADG, iptr);
3311
3312 if (res == NOTDONE)
3313 goto theend;
3314 if (res == FAIL)
3315 goto on_error;
3316 }
3317 }
3318 break;
3319
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02003320 case ISN_UNLET:
3321 if (do_unlet(iptr->isn_arg.unlet.ul_name,
3322 iptr->isn_arg.unlet.ul_forceit) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02003323 goto on_error;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02003324 break;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02003325 case ISN_UNLETENV:
3326 vim_unsetenv(iptr->isn_arg.unlet.ul_name);
3327 break;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02003328
Bram Moolenaaraacc9662021-08-13 19:40:51 +02003329 case ISN_LOCKUNLOCK:
3330 {
3331 typval_T *lval_root_save = lval_root;
3332 int res;
3333
3334 // Stack has the local variable, argument the whole :lock
3335 // or :unlock command, like ISN_EXEC.
3336 --ectx->ec_stack.ga_len;
3337 lval_root = STACK_TV_BOT(0);
3338 res = exec_command(iptr);
3339 clear_tv(lval_root);
3340 lval_root = lval_root_save;
3341 if (res == FAIL)
3342 goto on_error;
3343 }
3344 break;
3345
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02003346 case ISN_LOCKCONST:
3347 item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE);
3348 break;
3349
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003350 // create a list from items on the stack; uses a single allocation
3351 // for the list header and the items
3352 case ISN_NEWLIST:
Bram Moolenaar4c137212021-04-19 16:48:48 +02003353 if (exe_newlist(iptr->isn_arg.number, ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003354 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003355 break;
3356
3357 // create a dict from items on the stack
3358 case ISN_NEWDICT:
3359 {
Bram Moolenaare8593122020-07-18 15:17:02 +02003360 int count = iptr->isn_arg.number;
3361 dict_T *dict = dict_alloc();
3362 dictitem_T *item;
Bram Moolenaarc7f7f6d2020-11-04 13:38:28 +01003363 char_u *key;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003364 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003365
Dominique Pelle5a9e5842021-07-24 19:32:12 +02003366 if (unlikely(dict == NULL))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003367 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003368 for (idx = 0; idx < count; ++idx)
3369 {
Bram Moolenaare8593122020-07-18 15:17:02 +02003370 // have already checked key type is VAR_STRING
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003371 tv = STACK_TV_BOT(2 * (idx - count));
Bram Moolenaare8593122020-07-18 15:17:02 +02003372 // check key is unique
Bram Moolenaarc7f7f6d2020-11-04 13:38:28 +01003373 key = tv->vval.v_string == NULL
3374 ? (char_u *)"" : tv->vval.v_string;
3375 item = dict_find(dict, key, -1);
Bram Moolenaare8593122020-07-18 15:17:02 +02003376 if (item != NULL)
3377 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003378 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar74409f62022-01-01 15:58:22 +00003379 semsg(_(e_duplicate_key_in_dicitonary), key);
Bram Moolenaare8593122020-07-18 15:17:02 +02003380 dict_unref(dict);
3381 goto on_error;
3382 }
Bram Moolenaarc7f7f6d2020-11-04 13:38:28 +01003383 item = dictitem_alloc(key);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003384 clear_tv(tv);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02003385 if (unlikely(item == NULL))
Bram Moolenaare8593122020-07-18 15:17:02 +02003386 {
3387 dict_unref(dict);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003388 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02003389 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003390 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
3391 item->di_tv.v_lock = 0;
3392 if (dict_add(dict, item) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02003393 {
Bram Moolenaard032f342020-07-18 18:13:02 +02003394 // can this ever happen?
Bram Moolenaare8593122020-07-18 15:17:02 +02003395 dict_unref(dict);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003396 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02003397 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003398 }
3399
3400 if (count > 0)
Bram Moolenaar4c137212021-04-19 16:48:48 +02003401 ectx->ec_stack.ga_len -= 2 * count - 1;
Bram Moolenaar35578162021-08-02 19:10:38 +02003402 else if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003403 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003404 else
Bram Moolenaar4c137212021-04-19 16:48:48 +02003405 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003406 tv = STACK_TV_BOT(-1);
3407 tv->v_type = VAR_DICT;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003408 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003409 tv->vval.v_dict = dict;
3410 ++dict->dv_refcount;
3411 }
3412 break;
3413
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00003414 // create a partial with NULL value
3415 case ISN_NEWPARTIAL:
3416 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3417 goto theend;
3418 ++ectx->ec_stack.ga_len;
3419 tv = STACK_TV_BOT(-1);
3420 tv->v_type = VAR_PARTIAL;
3421 tv->v_lock = 0;
3422 tv->vval.v_partial = NULL;
3423 break;
3424
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003425 // call a :def function
3426 case ISN_DCALL:
Bram Moolenaardfa3d552020-09-10 22:05:08 +02003427 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01003428 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
3429 NULL,
3430 iptr->isn_arg.dfunc.cdf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02003431 ectx) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02003432 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003433 break;
3434
3435 // call a builtin function
3436 case ISN_BCALL:
3437 SOURCING_LNUM = iptr->isn_lnum;
3438 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
3439 iptr->isn_arg.bfunc.cbf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02003440 ectx) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02003441 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003442 break;
3443
3444 // call a funcref or partial
3445 case ISN_PCALL:
3446 {
3447 cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
3448 int r;
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02003449 typval_T partial_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003450
3451 SOURCING_LNUM = iptr->isn_lnum;
3452 if (pfunc->cpf_top)
3453 {
3454 // funcref is above the arguments
3455 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
3456 }
3457 else
3458 {
3459 // Get the funcref from the stack.
Bram Moolenaar4c137212021-04-19 16:48:48 +02003460 --ectx->ec_stack.ga_len;
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02003461 partial_tv = *STACK_TV_BOT(0);
3462 tv = &partial_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003463 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02003464 r = call_partial(tv, pfunc->cpf_argcount, ectx);
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02003465 if (tv == &partial_tv)
3466 clear_tv(&partial_tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003467 if (r == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02003468 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003469 }
3470 break;
3471
Bram Moolenaarbd5da372020-03-31 23:13:10 +02003472 case ISN_PCALL_END:
3473 // PCALL finished, arguments have been consumed and replaced by
3474 // the return value. Now clear the funcref from the stack,
3475 // and move the return value in its place.
Bram Moolenaar4c137212021-04-19 16:48:48 +02003476 --ectx->ec_stack.ga_len;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02003477 clear_tv(STACK_TV_BOT(-1));
3478 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
3479 break;
3480
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003481 // call a user defined function or funcref/partial
3482 case ISN_UCALL:
3483 {
3484 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
3485
3486 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar2fecb532021-03-24 22:00:56 +01003487 if (call_eval_func(cufunc->cuf_name, cufunc->cuf_argcount,
Bram Moolenaar4c137212021-04-19 16:48:48 +02003488 ectx, iptr) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02003489 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003490 }
3491 break;
3492
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02003493 // return from a :def function call without a value
3494 case ISN_RETURN_VOID:
Bram Moolenaar35578162021-08-02 19:10:38 +02003495 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003496 goto theend;
Bram Moolenaar299f3032021-01-08 20:53:09 +01003497 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003498 ++ectx->ec_stack.ga_len;
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02003499 tv->v_type = VAR_VOID;
Bram Moolenaar299f3032021-01-08 20:53:09 +01003500 tv->vval.v_number = 0;
3501 tv->v_lock = 0;
3502 // FALLTHROUGH
3503
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02003504 // return from a :def function call with what is on the stack
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003505 case ISN_RETURN:
3506 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003507 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003508 trycmd_T *trycmd = NULL;
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01003509
3510 if (trystack->ga_len > 0)
3511 trycmd = ((trycmd_T *)trystack->ga_data)
3512 + trystack->ga_len - 1;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02003513 if (trycmd != NULL
Bram Moolenaar4c137212021-04-19 16:48:48 +02003514 && trycmd->tcd_frame_idx == ectx->ec_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003515 {
Bram Moolenaar9cb577a2021-02-22 22:45:10 +01003516 // jump to ":finally" or ":endtry"
3517 if (trycmd->tcd_finally_idx != 0)
Bram Moolenaar4c137212021-04-19 16:48:48 +02003518 ectx->ec_iidx = trycmd->tcd_finally_idx;
Bram Moolenaar9cb577a2021-02-22 22:45:10 +01003519 else
Bram Moolenaar4c137212021-04-19 16:48:48 +02003520 ectx->ec_iidx = trycmd->tcd_endtry_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003521 trycmd->tcd_return = TRUE;
3522 }
3523 else
Bram Moolenaard032f342020-07-18 18:13:02 +02003524 goto func_return;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003525 }
3526 break;
3527
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02003528 // push a partial, a reference to a compiled function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003529 case ISN_FUNCREF:
3530 {
Bram Moolenaarf112f302020-12-20 17:47:52 +01003531 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
Bram Moolenaar38453522021-11-28 22:00:12 +00003532 ufunc_T *ufunc;
3533 funcref_T *funcref = &iptr->isn_arg.funcref;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003534
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003535 if (pt == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003536 goto theend;
Bram Moolenaar35578162021-08-02 19:10:38 +02003537 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003538 {
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02003539 vim_free(pt);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003540 goto theend;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02003541 }
Bram Moolenaar38453522021-11-28 22:00:12 +00003542 if (funcref->fr_func_name == NULL)
3543 {
3544 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data)
3545 + funcref->fr_dfunc_idx;
3546
3547 ufunc = pt_dfunc->df_ufunc;
3548 }
3549 else
3550 {
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00003551 ufunc = find_func(funcref->fr_func_name, FALSE);
Bram Moolenaar38453522021-11-28 22:00:12 +00003552 }
Bram Moolenaar56acd1f2022-02-18 13:24:52 +00003553 if (ufunc == NULL)
3554 {
3555 SOURCING_LNUM = iptr->isn_lnum;
3556 iemsg("ufunc unexpectedly NULL for FUNCREF");
3557 goto theend;
3558 }
Bram Moolenaar38453522021-11-28 22:00:12 +00003559 if (fill_partial_and_closure(pt, ufunc, ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003560 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003561 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003562 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003563 tv->vval.v_partial = pt;
3564 tv->v_type = VAR_PARTIAL;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003565 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003566 }
3567 break;
3568
Bram Moolenaar38ddf332020-07-31 22:05:04 +02003569 // Create a global function from a lambda.
3570 case ISN_NEWFUNC:
3571 {
3572 newfunc_T *newfunc = &iptr->isn_arg.newfunc;
3573
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01003574 if (copy_func(newfunc->nf_lambda, newfunc->nf_global,
Bram Moolenaar4c137212021-04-19 16:48:48 +02003575 ectx) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003576 goto theend;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02003577 }
3578 break;
3579
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01003580 // List functions
3581 case ISN_DEF:
3582 if (iptr->isn_arg.string == NULL)
3583 list_functions(NULL);
3584 else
3585 {
Bram Moolenaar14336722022-01-08 16:02:59 +00003586 exarg_T ea;
3587 garray_T lines_to_free;
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01003588
3589 CLEAR_FIELD(ea);
3590 ea.cmd = ea.arg = iptr->isn_arg.string;
Bram Moolenaar14336722022-01-08 16:02:59 +00003591 ga_init2(&lines_to_free, sizeof(char_u *), 50);
3592 define_function(&ea, NULL, &lines_to_free);
3593 ga_clear_strings(&lines_to_free);
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01003594 }
3595 break;
3596
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003597 // jump if a condition is met
3598 case ISN_JUMP:
3599 {
3600 jumpwhen_T when = iptr->isn_arg.jump.jump_when;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003601 int error = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003602 int jump = TRUE;
3603
3604 if (when != JUMP_ALWAYS)
3605 {
3606 tv = STACK_TV_BOT(-1);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003607 if (when == JUMP_IF_COND_FALSE
Bram Moolenaar13106602020-10-04 16:06:05 +02003608 || when == JUMP_IF_FALSE
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003609 || when == JUMP_IF_COND_TRUE)
3610 {
3611 SOURCING_LNUM = iptr->isn_lnum;
3612 jump = tv_get_bool_chk(tv, &error);
3613 if (error)
3614 goto on_error;
3615 }
3616 else
3617 jump = tv2bool(tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003618 if (when == JUMP_IF_FALSE
Bram Moolenaar2bb26582020-10-03 22:52:39 +02003619 || when == JUMP_AND_KEEP_IF_FALSE
3620 || when == JUMP_IF_COND_FALSE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003621 jump = !jump;
Bram Moolenaar777770f2020-02-06 21:27:08 +01003622 if (when == JUMP_IF_FALSE || !jump)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003623 {
3624 // drop the value from the stack
3625 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003626 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003627 }
3628 }
3629 if (jump)
Bram Moolenaar4c137212021-04-19 16:48:48 +02003630 ectx->ec_iidx = iptr->isn_arg.jump.jump_where;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003631 }
3632 break;
3633
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02003634 // Jump if an argument with a default value was already set and not
3635 // v:none.
3636 case ISN_JUMP_IF_ARG_SET:
3637 tv = STACK_TV_VAR(iptr->isn_arg.jumparg.jump_arg_off);
3638 if (tv->v_type != VAR_UNKNOWN
3639 && !(tv->v_type == VAR_SPECIAL
3640 && tv->vval.v_number == VVAL_NONE))
Bram Moolenaar4c137212021-04-19 16:48:48 +02003641 ectx->ec_iidx = iptr->isn_arg.jumparg.jump_where;
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02003642 break;
3643
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003644 // top of a for loop
3645 case ISN_FOR:
Bram Moolenaar058ee7c2022-01-23 20:00:42 +00003646 if (execute_for(iptr, ectx) == FAIL)
3647 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003648 break;
3649
3650 // start of ":try" block
3651 case ISN_TRY:
3652 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01003653 trycmd_T *trycmd = NULL;
3654
Bram Moolenaar35578162021-08-02 19:10:38 +02003655 if (GA_GROW_FAILS(&ectx->ec_trystack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003656 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02003657 trycmd = ((trycmd_T *)ectx->ec_trystack.ga_data)
3658 + ectx->ec_trystack.ga_len;
3659 ++ectx->ec_trystack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003660 ++trylevel;
Bram Moolenaar8d4be892021-02-13 18:33:02 +01003661 CLEAR_POINTER(trycmd);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003662 trycmd->tcd_frame_idx = ectx->ec_frame_idx;
3663 trycmd->tcd_stack_len = ectx->ec_stack.ga_len;
Bram Moolenaara91a7132021-03-25 21:12:15 +01003664 trycmd->tcd_catch_idx =
Bram Moolenaar0d807102021-12-21 09:42:09 +00003665 iptr->isn_arg.tryref.try_ref->try_catch;
Bram Moolenaara91a7132021-03-25 21:12:15 +01003666 trycmd->tcd_finally_idx =
Bram Moolenaar0d807102021-12-21 09:42:09 +00003667 iptr->isn_arg.tryref.try_ref->try_finally;
Bram Moolenaara91a7132021-03-25 21:12:15 +01003668 trycmd->tcd_endtry_idx =
Bram Moolenaar0d807102021-12-21 09:42:09 +00003669 iptr->isn_arg.tryref.try_ref->try_endtry;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003670 }
3671 break;
3672
3673 case ISN_PUSHEXC:
3674 if (current_exception == NULL)
3675 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02003676 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003677 iemsg("Evaluating catch while current_exception is NULL");
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003678 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003679 }
Bram Moolenaar35578162021-08-02 19:10:38 +02003680 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003681 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003682 tv = STACK_TV_BOT(0);
Bram Moolenaar4c137212021-04-19 16:48:48 +02003683 ++ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003684 tv->v_type = VAR_STRING;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003685 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003686 tv->vval.v_string = vim_strsave(
3687 (char_u *)current_exception->value);
3688 break;
3689
3690 case ISN_CATCH:
3691 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003692 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003693
Bram Moolenaar4c137212021-04-19 16:48:48 +02003694 may_restore_cmdmod(&ectx->ec_funclocal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003695 if (trystack->ga_len > 0)
3696 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01003697 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003698 + trystack->ga_len - 1;
3699 trycmd->tcd_caught = TRUE;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02003700 trycmd->tcd_did_throw = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003701 }
3702 did_emsg = got_int = did_throw = FALSE;
Bram Moolenaar1430cee2021-01-17 19:20:32 +01003703 force_abort = need_rethrow = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003704 catch_exception(current_exception);
3705 }
3706 break;
3707
Bram Moolenaarc150c092021-02-13 15:02:46 +01003708 case ISN_TRYCONT:
3709 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003710 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaarc150c092021-02-13 15:02:46 +01003711 trycont_T *trycont = &iptr->isn_arg.trycont;
3712 int i;
3713 trycmd_T *trycmd;
3714 int iidx = trycont->tct_where;
3715
3716 if (trystack->ga_len < trycont->tct_levels)
3717 {
3718 siemsg("TRYCONT: expected %d levels, found %d",
3719 trycont->tct_levels, trystack->ga_len);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003720 goto theend;
Bram Moolenaarc150c092021-02-13 15:02:46 +01003721 }
3722 // Make :endtry jump to any outer try block and the last
3723 // :endtry inside the loop to the loop start.
3724 for (i = trycont->tct_levels; i > 0; --i)
3725 {
3726 trycmd = ((trycmd_T *)trystack->ga_data)
3727 + trystack->ga_len - i;
Bram Moolenaar2e34c342021-03-14 12:13:33 +01003728 // Add one to tcd_cont to be able to jump to
3729 // instruction with index zero.
3730 trycmd->tcd_cont = iidx + 1;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01003731 iidx = trycmd->tcd_finally_idx == 0
3732 ? trycmd->tcd_endtry_idx : trycmd->tcd_finally_idx;
Bram Moolenaarc150c092021-02-13 15:02:46 +01003733 }
3734 // jump to :finally or :endtry of current try statement
Bram Moolenaar4c137212021-04-19 16:48:48 +02003735 ectx->ec_iidx = iidx;
Bram Moolenaarc150c092021-02-13 15:02:46 +01003736 }
3737 break;
3738
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01003739 case ISN_FINALLY:
3740 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003741 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01003742 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
3743 + trystack->ga_len - 1;
3744
3745 // Reset the index to avoid a return statement jumps here
3746 // again.
3747 trycmd->tcd_finally_idx = 0;
3748 break;
3749 }
3750
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003751 // end of ":try" block
3752 case ISN_ENDTRY:
3753 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003754 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003755
3756 if (trystack->ga_len > 0)
3757 {
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003758 trycmd_T *trycmd;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003759
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003760 --trystack->ga_len;
3761 --trylevel;
3762 trycmd = ((trycmd_T *)trystack->ga_data)
3763 + trystack->ga_len;
Bram Moolenaard3d8fee2021-06-30 19:54:43 +02003764 if (trycmd->tcd_did_throw)
3765 did_throw = TRUE;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01003766 if (trycmd->tcd_caught && current_exception != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003767 {
3768 // discard the exception
3769 if (caught_stack == current_exception)
3770 caught_stack = caught_stack->caught;
3771 discard_current_exception();
3772 }
3773
3774 if (trycmd->tcd_return)
Bram Moolenaard032f342020-07-18 18:13:02 +02003775 goto func_return;
Bram Moolenaard9d77892021-02-12 21:32:47 +01003776
Bram Moolenaar4c137212021-04-19 16:48:48 +02003777 while (ectx->ec_stack.ga_len > trycmd->tcd_stack_len)
Bram Moolenaard9d77892021-02-12 21:32:47 +01003778 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003779 --ectx->ec_stack.ga_len;
Bram Moolenaard9d77892021-02-12 21:32:47 +01003780 clear_tv(STACK_TV_BOT(0));
3781 }
Bram Moolenaar8d4be892021-02-13 18:33:02 +01003782 if (trycmd->tcd_cont != 0)
Bram Moolenaarc150c092021-02-13 15:02:46 +01003783 // handling :continue: jump to outer try block or
3784 // start of the loop
Bram Moolenaar4c137212021-04-19 16:48:48 +02003785 ectx->ec_iidx = trycmd->tcd_cont - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003786 }
3787 }
3788 break;
3789
3790 case ISN_THROW:
Bram Moolenaar8f81b222021-01-14 21:47:06 +01003791 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02003792 garray_T *trystack = &ectx->ec_trystack;
Bram Moolenaar1e021e62020-10-16 20:25:23 +02003793
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003794 if (trystack->ga_len == 0 && trylevel == 0 && emsg_silent)
3795 {
3796 // throwing an exception while using "silent!" causes
3797 // the function to abort but not display an error.
3798 tv = STACK_TV_BOT(-1);
3799 clear_tv(tv);
3800 tv->v_type = VAR_NUMBER;
3801 tv->vval.v_number = 0;
3802 goto done;
3803 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02003804 --ectx->ec_stack.ga_len;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003805 tv = STACK_TV_BOT(0);
3806 if (tv->vval.v_string == NULL
3807 || *skipwhite(tv->vval.v_string) == NUL)
3808 {
3809 vim_free(tv->vval.v_string);
3810 SOURCING_LNUM = iptr->isn_lnum;
3811 emsg(_(e_throw_with_empty_string));
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003812 goto theend;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003813 }
3814
3815 // Inside a "catch" we need to first discard the caught
3816 // exception.
3817 if (trystack->ga_len > 0)
3818 {
3819 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
3820 + trystack->ga_len - 1;
3821 if (trycmd->tcd_caught && current_exception != NULL)
3822 {
3823 // discard the exception
3824 if (caught_stack == current_exception)
3825 caught_stack = caught_stack->caught;
3826 discard_current_exception();
3827 trycmd->tcd_caught = FALSE;
3828 }
3829 }
3830
Bram Moolenaar90a57162022-02-12 14:23:17 +00003831 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003832 if (throw_exception(tv->vval.v_string, ET_USER, NULL)
3833 == FAIL)
3834 {
3835 vim_free(tv->vval.v_string);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02003836 goto theend;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01003837 }
3838 did_throw = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003839 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003840 break;
3841
3842 // compare with special values
3843 case ISN_COMPAREBOOL:
3844 case ISN_COMPARESPECIAL:
3845 {
3846 typval_T *tv1 = STACK_TV_BOT(-2);
3847 typval_T *tv2 = STACK_TV_BOT(-1);
3848 varnumber_T arg1 = tv1->vval.v_number;
3849 varnumber_T arg2 = tv2->vval.v_number;
3850 int res;
3851
3852 switch (iptr->isn_arg.op.op_type)
3853 {
3854 case EXPR_EQUAL: res = arg1 == arg2; break;
3855 case EXPR_NEQUAL: res = arg1 != arg2; break;
3856 default: res = 0; break;
3857 }
3858
Bram Moolenaar4c137212021-04-19 16:48:48 +02003859 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003860 tv1->v_type = VAR_BOOL;
3861 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
3862 }
3863 break;
3864
Bram Moolenaar7a222242022-03-01 19:23:24 +00003865 case ISN_COMPARENULL:
3866 {
3867 typval_T *tv1 = STACK_TV_BOT(-2);
3868 typval_T *tv2 = STACK_TV_BOT(-1);
3869 int res;
3870
3871 res = typval_compare_null(tv1, tv2);
3872 if (res == MAYBE)
3873 goto on_error;
3874 if (iptr->isn_arg.op.op_type == EXPR_NEQUAL)
3875 res = !res;
3876 clear_tv(tv1);
3877 clear_tv(tv2);
3878 --ectx->ec_stack.ga_len;
3879 tv1->v_type = VAR_BOOL;
3880 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
3881 }
3882 break;
3883
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003884 // Operation with two number arguments
3885 case ISN_OPNR:
3886 case ISN_COMPARENR:
3887 {
3888 typval_T *tv1 = STACK_TV_BOT(-2);
3889 typval_T *tv2 = STACK_TV_BOT(-1);
3890 varnumber_T arg1 = tv1->vval.v_number;
3891 varnumber_T arg2 = tv2->vval.v_number;
Bram Moolenaarfbeefb12021-08-07 15:50:23 +02003892 varnumber_T res = 0;
3893 int div_zero = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003894
3895 switch (iptr->isn_arg.op.op_type)
3896 {
3897 case EXPR_MULT: res = arg1 * arg2; break;
Bram Moolenaarfbeefb12021-08-07 15:50:23 +02003898 case EXPR_DIV: if (arg2 == 0)
3899 div_zero = TRUE;
3900 else
3901 res = arg1 / arg2;
3902 break;
3903 case EXPR_REM: if (arg2 == 0)
3904 div_zero = TRUE;
3905 else
3906 res = arg1 % arg2;
3907 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003908 case EXPR_SUB: res = arg1 - arg2; break;
3909 case EXPR_ADD: res = arg1 + arg2; break;
3910
3911 case EXPR_EQUAL: res = arg1 == arg2; break;
3912 case EXPR_NEQUAL: res = arg1 != arg2; break;
3913 case EXPR_GREATER: res = arg1 > arg2; break;
3914 case EXPR_GEQUAL: res = arg1 >= arg2; break;
3915 case EXPR_SMALLER: res = arg1 < arg2; break;
3916 case EXPR_SEQUAL: res = arg1 <= arg2; break;
Bram Moolenaarfbeefb12021-08-07 15:50:23 +02003917 default: break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003918 }
3919
Bram Moolenaar4c137212021-04-19 16:48:48 +02003920 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003921 if (iptr->isn_type == ISN_COMPARENR)
3922 {
3923 tv1->v_type = VAR_BOOL;
3924 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
3925 }
3926 else
3927 tv1->vval.v_number = res;
Bram Moolenaarfbeefb12021-08-07 15:50:23 +02003928 if (div_zero)
3929 {
3930 SOURCING_LNUM = iptr->isn_lnum;
3931 emsg(_(e_divide_by_zero));
3932 goto on_error;
3933 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003934 }
3935 break;
3936
3937 // Computation with two float arguments
3938 case ISN_OPFLOAT:
3939 case ISN_COMPAREFLOAT:
Bram Moolenaara5d59532020-01-26 21:42:03 +01003940#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003941 {
3942 typval_T *tv1 = STACK_TV_BOT(-2);
3943 typval_T *tv2 = STACK_TV_BOT(-1);
3944 float_T arg1 = tv1->vval.v_float;
3945 float_T arg2 = tv2->vval.v_float;
3946 float_T res = 0;
3947 int cmp = FALSE;
3948
3949 switch (iptr->isn_arg.op.op_type)
3950 {
3951 case EXPR_MULT: res = arg1 * arg2; break;
3952 case EXPR_DIV: res = arg1 / arg2; break;
3953 case EXPR_SUB: res = arg1 - arg2; break;
3954 case EXPR_ADD: res = arg1 + arg2; break;
3955
3956 case EXPR_EQUAL: cmp = arg1 == arg2; break;
3957 case EXPR_NEQUAL: cmp = arg1 != arg2; break;
3958 case EXPR_GREATER: cmp = arg1 > arg2; break;
3959 case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
3960 case EXPR_SMALLER: cmp = arg1 < arg2; break;
3961 case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
3962 default: cmp = 0; break;
3963 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02003964 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003965 if (iptr->isn_type == ISN_COMPAREFLOAT)
3966 {
3967 tv1->v_type = VAR_BOOL;
3968 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
3969 }
3970 else
3971 tv1->vval.v_float = res;
3972 }
Bram Moolenaara5d59532020-01-26 21:42:03 +01003973#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003974 break;
3975
3976 case ISN_COMPARELIST:
Bram Moolenaar265f8112021-12-19 12:33:05 +00003977 case ISN_COMPAREDICT:
3978 case ISN_COMPAREFUNC:
3979 case ISN_COMPARESTRING:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003980 case ISN_COMPAREBLOB:
3981 {
3982 typval_T *tv1 = STACK_TV_BOT(-2);
3983 typval_T *tv2 = STACK_TV_BOT(-1);
Bram Moolenaar265f8112021-12-19 12:33:05 +00003984 exprtype_T exprtype = iptr->isn_arg.op.op_type;
3985 int ic = iptr->isn_arg.op.op_ic;
3986 int res = FALSE;
3987 int status = OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003988
Bram Moolenaar265f8112021-12-19 12:33:05 +00003989 SOURCING_LNUM = iptr->isn_lnum;
3990 if (iptr->isn_type == ISN_COMPARELIST)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003991 {
Bram Moolenaar265f8112021-12-19 12:33:05 +00003992 status = typval_compare_list(tv1, tv2,
3993 exprtype, ic, &res);
3994 }
3995 else if (iptr->isn_type == ISN_COMPAREDICT)
3996 {
3997 status = typval_compare_dict(tv1, tv2,
3998 exprtype, ic, &res);
3999 }
4000 else if (iptr->isn_type == ISN_COMPAREFUNC)
4001 {
4002 status = typval_compare_func(tv1, tv2,
4003 exprtype, ic, &res);
4004 }
4005 else if (iptr->isn_type == ISN_COMPARESTRING)
4006 {
4007 status = typval_compare_string(tv1, tv2,
4008 exprtype, ic, &res);
4009 }
4010 else
4011 {
4012 status = typval_compare_blob(tv1, tv2, exprtype, &res);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004013 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004014 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004015 clear_tv(tv1);
4016 clear_tv(tv2);
4017 tv1->v_type = VAR_BOOL;
Bram Moolenaar265f8112021-12-19 12:33:05 +00004018 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
4019 if (status == FAIL)
4020 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004021 }
4022 break;
4023
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004024 case ISN_COMPAREANY:
4025 {
4026 typval_T *tv1 = STACK_TV_BOT(-2);
4027 typval_T *tv2 = STACK_TV_BOT(-1);
Bram Moolenaar657137c2021-01-09 15:45:23 +01004028 exprtype_T exprtype = iptr->isn_arg.op.op_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004029 int ic = iptr->isn_arg.op.op_ic;
Bram Moolenaar265f8112021-12-19 12:33:05 +00004030 int status;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004031
Bram Moolenaareb26f432020-09-14 16:50:05 +02004032 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar265f8112021-12-19 12:33:05 +00004033 status = typval_compare(tv1, tv2, exprtype, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004034 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004035 --ectx->ec_stack.ga_len;
Bram Moolenaar265f8112021-12-19 12:33:05 +00004036 if (status == FAIL)
4037 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004038 }
4039 break;
4040
4041 case ISN_ADDLIST:
4042 case ISN_ADDBLOB:
4043 {
4044 typval_T *tv1 = STACK_TV_BOT(-2);
4045 typval_T *tv2 = STACK_TV_BOT(-1);
4046
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004047 // add two lists or blobs
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004048 if (iptr->isn_type == ISN_ADDLIST)
Bram Moolenaar07802042021-09-09 23:01:14 +02004049 {
4050 if (iptr->isn_arg.op.op_type == EXPR_APPEND
4051 && tv1->vval.v_list != NULL)
4052 list_extend(tv1->vval.v_list, tv2->vval.v_list,
4053 NULL);
4054 else
4055 eval_addlist(tv1, tv2);
4056 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004057 else
4058 eval_addblob(tv1, tv2);
4059 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004060 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004061 }
4062 break;
4063
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004064 case ISN_LISTAPPEND:
4065 {
4066 typval_T *tv1 = STACK_TV_BOT(-2);
4067 typval_T *tv2 = STACK_TV_BOT(-1);
4068 list_T *l = tv1->vval.v_list;
4069
4070 // add an item to a list
Bram Moolenaar1f4a3452022-01-01 18:29:21 +00004071 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004072 if (l == NULL)
4073 {
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004074 emsg(_(e_cannot_add_to_null_list));
4075 goto on_error;
4076 }
Bram Moolenaar1f4a3452022-01-01 18:29:21 +00004077 if (value_check_lock(l->lv_lock, NULL, FALSE))
4078 goto on_error;
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004079 if (list_append_tv(l, tv2) == FAIL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004080 goto theend;
Bram Moolenaar955347c2020-10-19 23:01:46 +02004081 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004082 --ectx->ec_stack.ga_len;
Bram Moolenaar1dcae592020-10-19 19:02:42 +02004083 }
4084 break;
4085
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02004086 case ISN_BLOBAPPEND:
4087 {
4088 typval_T *tv1 = STACK_TV_BOT(-2);
4089 typval_T *tv2 = STACK_TV_BOT(-1);
4090 blob_T *b = tv1->vval.v_blob;
4091 int error = FALSE;
4092 varnumber_T n;
4093
4094 // add a number to a blob
4095 if (b == NULL)
4096 {
4097 SOURCING_LNUM = iptr->isn_lnum;
4098 emsg(_(e_cannot_add_to_null_blob));
4099 goto on_error;
4100 }
4101 n = tv_get_number_chk(tv2, &error);
4102 if (error)
4103 goto on_error;
4104 ga_append(&b->bv_ga, (int)n);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004105 --ectx->ec_stack.ga_len;
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02004106 }
4107 break;
4108
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004109 // Computation with two arguments of unknown type
4110 case ISN_OPANY:
4111 {
4112 typval_T *tv1 = STACK_TV_BOT(-2);
4113 typval_T *tv2 = STACK_TV_BOT(-1);
4114 varnumber_T n1, n2;
4115#ifdef FEAT_FLOAT
4116 float_T f1 = 0, f2 = 0;
4117#endif
4118 int error = FALSE;
4119
4120 if (iptr->isn_arg.op.op_type == EXPR_ADD)
4121 {
4122 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
4123 {
4124 eval_addlist(tv1, tv2);
4125 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004126 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004127 break;
4128 }
4129 else if (tv1->v_type == VAR_BLOB
4130 && tv2->v_type == VAR_BLOB)
4131 {
4132 eval_addblob(tv1, tv2);
4133 clear_tv(tv2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004134 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004135 break;
4136 }
4137 }
4138#ifdef FEAT_FLOAT
4139 if (tv1->v_type == VAR_FLOAT)
4140 {
4141 f1 = tv1->vval.v_float;
4142 n1 = 0;
4143 }
4144 else
4145#endif
4146 {
Bram Moolenaarf665e972020-12-05 19:17:16 +01004147 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004148 n1 = tv_get_number_chk(tv1, &error);
4149 if (error)
Bram Moolenaard032f342020-07-18 18:13:02 +02004150 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004151#ifdef FEAT_FLOAT
4152 if (tv2->v_type == VAR_FLOAT)
4153 f1 = n1;
4154#endif
4155 }
4156#ifdef FEAT_FLOAT
4157 if (tv2->v_type == VAR_FLOAT)
4158 {
4159 f2 = tv2->vval.v_float;
4160 n2 = 0;
4161 }
4162 else
4163#endif
4164 {
4165 n2 = tv_get_number_chk(tv2, &error);
4166 if (error)
Bram Moolenaard032f342020-07-18 18:13:02 +02004167 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004168#ifdef FEAT_FLOAT
4169 if (tv1->v_type == VAR_FLOAT)
4170 f2 = n2;
4171#endif
4172 }
4173#ifdef FEAT_FLOAT
4174 // if there is a float on either side the result is a float
4175 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
4176 {
4177 switch (iptr->isn_arg.op.op_type)
4178 {
4179 case EXPR_MULT: f1 = f1 * f2; break;
4180 case EXPR_DIV: f1 = f1 / f2; break;
4181 case EXPR_SUB: f1 = f1 - f2; break;
4182 case EXPR_ADD: f1 = f1 + f2; break;
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004183 default: SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00004184 emsg(_(e_cannot_use_percent_with_float));
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004185 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004186 }
4187 clear_tv(tv1);
4188 clear_tv(tv2);
4189 tv1->v_type = VAR_FLOAT;
4190 tv1->vval.v_float = f1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004191 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004192 }
4193 else
4194#endif
4195 {
Bram Moolenaarb1f28572021-01-21 13:03:20 +01004196 int failed = FALSE;
4197
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004198 switch (iptr->isn_arg.op.op_type)
4199 {
4200 case EXPR_MULT: n1 = n1 * n2; break;
Bram Moolenaarb1f28572021-01-21 13:03:20 +01004201 case EXPR_DIV: n1 = num_divide(n1, n2, &failed);
4202 if (failed)
Bram Moolenaar99880f92021-01-20 21:23:14 +01004203 goto on_error;
4204 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004205 case EXPR_SUB: n1 = n1 - n2; break;
4206 case EXPR_ADD: n1 = n1 + n2; break;
Bram Moolenaarb1f28572021-01-21 13:03:20 +01004207 default: n1 = num_modulus(n1, n2, &failed);
4208 if (failed)
Bram Moolenaar99880f92021-01-20 21:23:14 +01004209 goto on_error;
4210 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004211 }
4212 clear_tv(tv1);
4213 clear_tv(tv2);
4214 tv1->v_type = VAR_NUMBER;
4215 tv1->vval.v_number = n1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004216 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004217 }
4218 }
4219 break;
4220
4221 case ISN_CONCAT:
4222 {
4223 char_u *str1 = STACK_TV_BOT(-2)->vval.v_string;
4224 char_u *str2 = STACK_TV_BOT(-1)->vval.v_string;
4225 char_u *res;
4226
4227 res = concat_str(str1, str2);
4228 clear_tv(STACK_TV_BOT(-2));
4229 clear_tv(STACK_TV_BOT(-1));
Bram Moolenaar4c137212021-04-19 16:48:48 +02004230 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004231 STACK_TV_BOT(-1)->vval.v_string = res;
4232 }
4233 break;
4234
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004235 case ISN_STRINDEX:
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004236 case ISN_STRSLICE:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004237 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004238 int is_slice = iptr->isn_type == ISN_STRSLICE;
4239 varnumber_T n1 = 0, n2;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004240 char_u *res;
4241
4242 // string index: string is at stack-2, index at stack-1
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004243 // string slice: string is at stack-3, first index at
4244 // stack-2, second index at stack-1
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004245 if (is_slice)
4246 {
4247 tv = STACK_TV_BOT(-2);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004248 n1 = tv->vval.v_number;
4249 }
4250
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004251 tv = STACK_TV_BOT(-1);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004252 n2 = tv->vval.v_number;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004253
Bram Moolenaar4c137212021-04-19 16:48:48 +02004254 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004255 tv = STACK_TV_BOT(-1);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004256 if (is_slice)
4257 // Slice: Select the characters from the string
Bram Moolenaar6601b622021-01-13 21:47:15 +01004258 res = string_slice(tv->vval.v_string, n1, n2, FALSE);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004259 else
4260 // Index: The resulting variable is a string of a
Bram Moolenaar0289a092021-03-14 18:40:19 +01004261 // single character (including composing characters).
4262 // If the index is too big or negative the result is
4263 // empty.
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004264 res = char_from_string(tv->vval.v_string, n2);
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004265 vim_free(tv->vval.v_string);
4266 tv->vval.v_string = res;
4267 }
4268 break;
4269
4270 case ISN_LISTINDEX:
Bram Moolenaared591872020-08-15 22:14:53 +02004271 case ISN_LISTSLICE:
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004272 case ISN_BLOBINDEX:
4273 case ISN_BLOBSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004274 {
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004275 int is_slice = iptr->isn_type == ISN_LISTSLICE
4276 || iptr->isn_type == ISN_BLOBSLICE;
4277 int is_blob = iptr->isn_type == ISN_BLOBINDEX
4278 || iptr->isn_type == ISN_BLOBSLICE;
Bram Moolenaared591872020-08-15 22:14:53 +02004279 varnumber_T n1, n2;
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004280 typval_T *val_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004281
4282 // list index: list is at stack-2, index at stack-1
Bram Moolenaared591872020-08-15 22:14:53 +02004283 // list slice: list is at stack-3, indexes at stack-2 and
4284 // stack-1
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004285 // Same for blob.
4286 val_tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004287
4288 tv = STACK_TV_BOT(-1);
Bram Moolenaared591872020-08-15 22:14:53 +02004289 n1 = n2 = tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004290 clear_tv(tv);
Bram Moolenaared591872020-08-15 22:14:53 +02004291
4292 if (is_slice)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004293 {
Bram Moolenaared591872020-08-15 22:14:53 +02004294 tv = STACK_TV_BOT(-2);
Bram Moolenaared591872020-08-15 22:14:53 +02004295 n1 = tv->vval.v_number;
4296 clear_tv(tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004297 }
Bram Moolenaared591872020-08-15 22:14:53 +02004298
Bram Moolenaar4c137212021-04-19 16:48:48 +02004299 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaar435d8972020-07-05 16:42:13 +02004300 tv = STACK_TV_BOT(-1);
Bram Moolenaar1d634542020-08-18 13:41:50 +02004301 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004302 if (is_blob)
4303 {
4304 if (blob_slice_or_index(val_tv->vval.v_blob, is_slice,
4305 n1, n2, FALSE, tv) == FAIL)
4306 goto on_error;
4307 }
4308 else
4309 {
4310 if (list_slice_or_index(val_tv->vval.v_list, is_slice,
4311 n1, n2, FALSE, tv, TRUE) == FAIL)
4312 goto on_error;
4313 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004314 }
4315 break;
4316
Bram Moolenaarcc673e72020-08-16 17:33:35 +02004317 case ISN_ANYINDEX:
4318 case ISN_ANYSLICE:
4319 {
4320 int is_slice = iptr->isn_type == ISN_ANYSLICE;
4321 typval_T *var1, *var2;
4322 int res;
4323
4324 // index: composite is at stack-2, index at stack-1
4325 // slice: composite is at stack-3, indexes at stack-2 and
4326 // stack-1
4327 tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
Bram Moolenaar3affe7a2020-08-18 20:34:13 +02004328 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02004329 if (check_can_index(tv, TRUE, TRUE) == FAIL)
4330 goto on_error;
4331 var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1);
4332 var2 = is_slice ? STACK_TV_BOT(-1) : NULL;
Bram Moolenaar6601b622021-01-13 21:47:15 +01004333 res = eval_index_inner(tv, is_slice, var1, var2,
4334 FALSE, NULL, -1, TRUE);
Bram Moolenaarcc673e72020-08-16 17:33:35 +02004335 clear_tv(var1);
4336 if (is_slice)
4337 clear_tv(var2);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004338 ectx->ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02004339 if (res == FAIL)
4340 goto on_error;
4341 }
4342 break;
4343
Bram Moolenaar9af78762020-06-16 11:34:42 +02004344 case ISN_SLICE:
4345 {
4346 list_T *list;
4347 int count = iptr->isn_arg.number;
4348
Bram Moolenaarc5b1c202020-06-18 22:43:27 +02004349 // type will have been checked to be a list
Bram Moolenaar9af78762020-06-16 11:34:42 +02004350 tv = STACK_TV_BOT(-1);
Bram Moolenaar9af78762020-06-16 11:34:42 +02004351 list = tv->vval.v_list;
4352
4353 // no error for short list, expect it to be checked earlier
4354 if (list != NULL && list->lv_len >= count)
4355 {
4356 list_T *newlist = list_slice(list,
4357 count, list->lv_len - 1);
4358
4359 if (newlist != NULL)
4360 {
4361 list_unref(list);
4362 tv->vval.v_list = newlist;
4363 ++newlist->lv_refcount;
4364 }
4365 }
4366 }
4367 break;
4368
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004369 case ISN_GETITEM:
4370 {
4371 listitem_T *li;
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02004372 getitem_T *gi = &iptr->isn_arg.getitem;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004373
Bram Moolenaarc785b9a2020-06-19 18:34:15 +02004374 // Get list item: list is at stack-1, push item.
4375 // List type and length is checked for when compiling.
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02004376 tv = STACK_TV_BOT(-1 - gi->gi_with_op);
4377 li = list_find(tv->vval.v_list, gi->gi_index);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004378
Bram Moolenaar35578162021-08-02 19:10:38 +02004379 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004380 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004381 ++ectx->ec_stack.ga_len;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004382 copy_tv(&li->li_tv, STACK_TV_BOT(-1));
Bram Moolenaarf785aa12021-02-11 21:19:34 +01004383
4384 // Useful when used in unpack assignment. Reset at
4385 // ISN_DROP.
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02004386 ectx->ec_where.wt_index = gi->gi_index + 1;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004387 ectx->ec_where.wt_variable = TRUE;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02004388 }
4389 break;
4390
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004391 case ISN_MEMBER:
4392 {
4393 dict_T *dict;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004394 char_u *key;
4395 dictitem_T *di;
4396
4397 // dict member: dict is at stack-2, key at stack-1
4398 tv = STACK_TV_BOT(-2);
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02004399 // no need to check for VAR_DICT, CHECKTYPE will check.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004400 dict = tv->vval.v_dict;
4401
4402 tv = STACK_TV_BOT(-1);
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02004403 // no need to check for VAR_STRING, 2STRING will check.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004404 key = tv->vval.v_string;
Bram Moolenaar086fc9a2020-10-30 18:33:02 +01004405 if (key == NULL)
4406 key = (char_u *)"";
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02004407
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004408 if ((di = dict_find(dict, key, -1)) == NULL)
4409 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004410 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00004411 semsg(_(e_key_not_present_in_dictionary), key);
Bram Moolenaar4029cab2020-12-05 18:13:27 +01004412
4413 // If :silent! is used we will continue, make sure the
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02004414 // stack contents makes sense and the dict stack is
4415 // updated.
Bram Moolenaar4029cab2020-12-05 18:13:27 +01004416 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004417 --ectx->ec_stack.ga_len;
Bram Moolenaar4029cab2020-12-05 18:13:27 +01004418 tv = STACK_TV_BOT(-1);
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02004419 (void) dict_stack_save(tv);
Bram Moolenaar4029cab2020-12-05 18:13:27 +01004420 tv->v_type = VAR_NUMBER;
4421 tv->vval.v_number = 0;
Bram Moolenaaraf0df472020-12-02 20:51:22 +01004422 goto on_fatal_error;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004423 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004424 clear_tv(tv);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004425 --ectx->ec_stack.ga_len;
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02004426 // Put the dict used on the dict stack, it might be used by
4427 // a dict function later.
Bram Moolenaar50788ef2020-07-05 16:51:26 +02004428 tv = STACK_TV_BOT(-1);
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02004429 if (dict_stack_save(tv) == FAIL)
4430 goto on_fatal_error;
Bram Moolenaar50788ef2020-07-05 16:51:26 +02004431 copy_tv(&di->di_tv, tv);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004432 }
4433 break;
4434
4435 // dict member with string key
4436 case ISN_STRINGMEMBER:
4437 {
4438 dict_T *dict;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004439 dictitem_T *di;
4440
4441 tv = STACK_TV_BOT(-1);
4442 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
4443 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004444 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00004445 emsg(_(e_dictionary_required));
Bram Moolenaard032f342020-07-18 18:13:02 +02004446 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004447 }
4448 dict = tv->vval.v_dict;
4449
4450 if ((di = dict_find(dict, iptr->isn_arg.string, -1))
4451 == NULL)
4452 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004453 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar381692b2022-02-02 20:01:27 +00004454 semsg(_(e_key_not_present_in_dictionary),
4455 iptr->isn_arg.string);
Bram Moolenaard032f342020-07-18 18:13:02 +02004456 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004457 }
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02004458 // Put the dict used on the dict stack, it might be used by
4459 // a dict function later.
4460 if (dict_stack_save(tv) == FAIL)
4461 goto on_fatal_error;
4462
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004463 copy_tv(&di->di_tv, tv);
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02004464 }
4465 break;
4466
4467 case ISN_CLEARDICT:
4468 dict_stack_drop();
4469 break;
4470
4471 case ISN_USEDICT:
4472 {
4473 typval_T *dict_tv = dict_stack_get_tv();
4474
4475 // Turn "dict.Func" into a partial for "Func" bound to
4476 // "dict". Don't do this when "Func" is already a partial
4477 // that was bound explicitly (pt_auto is FALSE).
4478 tv = STACK_TV_BOT(-1);
4479 if (dict_tv != NULL
4480 && dict_tv->v_type == VAR_DICT
4481 && dict_tv->vval.v_dict != NULL
4482 && (tv->v_type == VAR_FUNC
4483 || (tv->v_type == VAR_PARTIAL
4484 && (tv->vval.v_partial->pt_auto
4485 || tv->vval.v_partial->pt_dict == NULL))))
4486 dict_tv->vval.v_dict =
4487 make_partial(dict_tv->vval.v_dict, tv);
4488 dict_stack_drop();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004489 }
4490 break;
4491
4492 case ISN_NEGATENR:
4493 tv = STACK_TV_BOT(-1);
Bram Moolenaar0c7f2612022-02-17 19:44:07 +00004494 // CHECKTYPE should have checked the variable type
Bram Moolenaarc58164c2020-03-29 18:40:30 +02004495#ifdef FEAT_FLOAT
4496 if (tv->v_type == VAR_FLOAT)
4497 tv->vval.v_float = -tv->vval.v_float;
4498 else
4499#endif
4500 tv->vval.v_number = -tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004501 break;
4502
4503 case ISN_CHECKNR:
4504 {
4505 int error = FALSE;
4506
4507 tv = STACK_TV_BOT(-1);
Bram Moolenaar3affe7a2020-08-18 20:34:13 +02004508 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004509 if (check_not_string(tv) == FAIL)
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004510 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004511 (void)tv_get_number_chk(tv, &error);
4512 if (error)
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004513 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004514 }
4515 break;
4516
4517 case ISN_CHECKTYPE:
4518 {
4519 checktype_T *ct = &iptr->isn_arg.type;
4520
Bram Moolenaarb3005ce2021-01-22 17:51:06 +01004521 tv = STACK_TV_BOT((int)ct->ct_off);
Bram Moolenaar5e654232020-09-16 15:22:00 +02004522 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004523 if (!ectx->ec_where.wt_variable)
4524 ectx->ec_where.wt_index = ct->ct_arg_idx;
4525 if (check_typval_type(ct->ct_type, tv, ectx->ec_where)
4526 == FAIL)
Bram Moolenaar5e654232020-09-16 15:22:00 +02004527 goto on_error;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004528 if (!ectx->ec_where.wt_variable)
4529 ectx->ec_where.wt_index = 0;
Bram Moolenaar5e654232020-09-16 15:22:00 +02004530
4531 // number 0 is FALSE, number 1 is TRUE
4532 if (tv->v_type == VAR_NUMBER
4533 && ct->ct_type->tt_type == VAR_BOOL
4534 && (tv->vval.v_number == 0
4535 || tv->vval.v_number == 1))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004536 {
Bram Moolenaar5e654232020-09-16 15:22:00 +02004537 tv->v_type = VAR_BOOL;
4538 tv->vval.v_number = tv->vval.v_number
Bram Moolenaardadaddd2020-09-12 19:11:23 +02004539 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004540 }
4541 }
4542 break;
4543
Bram Moolenaar9af78762020-06-16 11:34:42 +02004544 case ISN_CHECKLEN:
4545 {
4546 int min_len = iptr->isn_arg.checklen.cl_min_len;
4547 list_T *list = NULL;
4548
4549 tv = STACK_TV_BOT(-1);
4550 if (tv->v_type == VAR_LIST)
4551 list = tv->vval.v_list;
4552 if (list == NULL || list->lv_len < min_len
4553 || (list->lv_len > min_len
4554 && !iptr->isn_arg.checklen.cl_more_OK))
4555 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02004556 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004557 semsg(_(e_expected_nr_items_but_got_nr),
Bram Moolenaar9af78762020-06-16 11:34:42 +02004558 min_len, list == NULL ? 0 : list->lv_len);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004559 goto on_error;
Bram Moolenaar9af78762020-06-16 11:34:42 +02004560 }
4561 }
4562 break;
4563
Bram Moolenaaraa210a32021-01-02 15:41:03 +01004564 case ISN_SETTYPE:
Bram Moolenaar381692b2022-02-02 20:01:27 +00004565 set_tv_type(STACK_TV_BOT(-1), iptr->isn_arg.type.ct_type);
Bram Moolenaaraa210a32021-01-02 15:41:03 +01004566 break;
4567
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004568 case ISN_2BOOL:
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004569 case ISN_COND2BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004570 {
4571 int n;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004572 int error = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004573
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004574 if (iptr->isn_type == ISN_2BOOL)
4575 {
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02004576 tv = STACK_TV_BOT(iptr->isn_arg.tobool.offset);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004577 n = tv2bool(tv);
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02004578 if (iptr->isn_arg.tobool.invert)
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004579 n = !n;
4580 }
4581 else
4582 {
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02004583 tv = STACK_TV_BOT(-1);
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004584 SOURCING_LNUM = iptr->isn_lnum;
4585 n = tv_get_bool_chk(tv, &error);
4586 if (error)
4587 goto on_error;
4588 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004589 clear_tv(tv);
4590 tv->v_type = VAR_BOOL;
4591 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
4592 }
4593 break;
4594
4595 case ISN_2STRING:
Bram Moolenaar418f1df2020-08-12 21:34:49 +02004596 case ISN_2STRING_ANY:
Bram Moolenaar0acbf5a2021-01-05 20:58:25 +01004597 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02004598 if (do_2string(STACK_TV_BOT(iptr->isn_arg.tostring.offset),
4599 iptr->isn_type == ISN_2STRING_ANY,
4600 iptr->isn_arg.tostring.tolerant) == FAIL)
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01004601 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004602 break;
4603
Bram Moolenaar08597872020-12-10 19:43:40 +01004604 case ISN_RANGE:
4605 {
4606 exarg_T ea;
4607 char *errormsg;
4608
Bram Moolenaarece0b872021-01-08 20:40:45 +01004609 ea.line2 = 0;
Bram Moolenaard1510ee2021-01-04 16:15:58 +01004610 ea.addr_count = 0;
Bram Moolenaar08597872020-12-10 19:43:40 +01004611 ea.addr_type = ADDR_LINES;
4612 ea.cmd = iptr->isn_arg.string;
Bram Moolenaarece0b872021-01-08 20:40:45 +01004613 ea.skip = FALSE;
Bram Moolenaar08597872020-12-10 19:43:40 +01004614 if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
Bram Moolenaarece0b872021-01-08 20:40:45 +01004615 goto on_error;
Bram Moolenaara28639e2021-01-19 22:48:09 +01004616
Bram Moolenaar35578162021-08-02 19:10:38 +02004617 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004618 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004619 ++ectx->ec_stack.ga_len;
Bram Moolenaara28639e2021-01-19 22:48:09 +01004620 tv = STACK_TV_BOT(-1);
4621 tv->v_type = VAR_NUMBER;
4622 tv->v_lock = 0;
Bram Moolenaar08597872020-12-10 19:43:40 +01004623 if (ea.addr_count == 0)
4624 tv->vval.v_number = curwin->w_cursor.lnum;
4625 else
4626 tv->vval.v_number = ea.line2;
4627 }
4628 break;
4629
Bram Moolenaarc3516f72020-09-08 22:45:35 +02004630 case ISN_PUT:
4631 {
4632 int regname = iptr->isn_arg.put.put_regname;
4633 linenr_T lnum = iptr->isn_arg.put.put_lnum;
4634 char_u *expr = NULL;
4635 int dir = FORWARD;
4636
Bram Moolenaar08597872020-12-10 19:43:40 +01004637 if (lnum < -2)
4638 {
4639 // line number was put on the stack by ISN_RANGE
4640 tv = STACK_TV_BOT(-1);
4641 curwin->w_cursor.lnum = tv->vval.v_number;
4642 if (lnum == LNUM_VARIABLE_RANGE_ABOVE)
4643 dir = BACKWARD;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004644 --ectx->ec_stack.ga_len;
Bram Moolenaar08597872020-12-10 19:43:40 +01004645 }
4646 else if (lnum == -2)
Bram Moolenaarc3516f72020-09-08 22:45:35 +02004647 // :put! above cursor
4648 dir = BACKWARD;
4649 else if (lnum >= 0)
Bram Moolenaar4e713ba2022-02-07 15:31:37 +00004650 {
4651 curwin->w_cursor.lnum = lnum;
4652 if (lnum == 0)
4653 // check_cursor() below will move to line 1
4654 dir = BACKWARD;
4655 }
Bram Moolenaara28639e2021-01-19 22:48:09 +01004656
4657 if (regname == '=')
4658 {
4659 tv = STACK_TV_BOT(-1);
4660 if (tv->v_type == VAR_STRING)
4661 expr = tv->vval.v_string;
4662 else
4663 {
4664 expr = typval2string(tv, TRUE); // allocates value
4665 clear_tv(tv);
4666 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004667 --ectx->ec_stack.ga_len;
Bram Moolenaara28639e2021-01-19 22:48:09 +01004668 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02004669 check_cursor();
4670 do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
4671 vim_free(expr);
4672 }
4673 break;
4674
Bram Moolenaar02194d22020-10-24 23:08:38 +02004675 case ISN_CMDMOD:
Bram Moolenaar4c137212021-04-19 16:48:48 +02004676 ectx->ec_funclocal.floc_save_cmdmod = cmdmod;
4677 ectx->ec_funclocal.floc_restore_cmdmod = TRUE;
4678 ectx->ec_funclocal.floc_restore_cmdmod_stacklen =
4679 ectx->ec_stack.ga_len;
Bram Moolenaar02194d22020-10-24 23:08:38 +02004680 cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod;
4681 apply_cmdmod(&cmdmod);
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02004682 break;
4683
Bram Moolenaar02194d22020-10-24 23:08:38 +02004684 case ISN_CMDMOD_REV:
4685 // filter regprog is owned by the instruction, don't free it
4686 cmdmod.cmod_filter_regmatch.regprog = NULL;
4687 undo_cmdmod(&cmdmod);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004688 cmdmod = ectx->ec_funclocal.floc_save_cmdmod;
4689 ectx->ec_funclocal.floc_restore_cmdmod = FALSE;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02004690 break;
4691
Bram Moolenaar792f7862020-11-23 08:31:18 +01004692 case ISN_UNPACK:
4693 {
4694 int count = iptr->isn_arg.unpack.unp_count;
4695 int semicolon = iptr->isn_arg.unpack.unp_semicolon;
4696 list_T *l;
4697 listitem_T *li;
4698 int i;
4699
4700 // Check there is a valid list to unpack.
4701 tv = STACK_TV_BOT(-1);
4702 if (tv->v_type != VAR_LIST)
4703 {
4704 SOURCING_LNUM = iptr->isn_lnum;
4705 emsg(_(e_for_argument_must_be_sequence_of_lists));
4706 goto on_error;
4707 }
4708 l = tv->vval.v_list;
4709 if (l == NULL
4710 || l->lv_len < (semicolon ? count - 1 : count))
4711 {
4712 SOURCING_LNUM = iptr->isn_lnum;
4713 emsg(_(e_list_value_does_not_have_enough_items));
4714 goto on_error;
4715 }
4716 else if (!semicolon && l->lv_len > count)
4717 {
4718 SOURCING_LNUM = iptr->isn_lnum;
4719 emsg(_(e_list_value_has_more_items_than_targets));
4720 goto on_error;
4721 }
4722
4723 CHECK_LIST_MATERIALIZE(l);
Bram Moolenaar35578162021-08-02 19:10:38 +02004724 if (GA_GROW_FAILS(&ectx->ec_stack, count - 1))
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004725 goto theend;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004726 ectx->ec_stack.ga_len += count - 1;
Bram Moolenaar792f7862020-11-23 08:31:18 +01004727
4728 // Variable after semicolon gets a list with the remaining
4729 // items.
4730 if (semicolon)
4731 {
4732 list_T *rem_list =
4733 list_alloc_with_items(l->lv_len - count + 1);
4734
4735 if (rem_list == NULL)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004736 goto theend;
Bram Moolenaar792f7862020-11-23 08:31:18 +01004737 tv = STACK_TV_BOT(-count);
4738 tv->vval.v_list = rem_list;
4739 ++rem_list->lv_refcount;
4740 tv->v_lock = 0;
4741 li = l->lv_first;
4742 for (i = 0; i < count - 1; ++i)
4743 li = li->li_next;
4744 for (i = 0; li != NULL; ++i)
4745 {
Bram Moolenaar61efa162022-03-18 13:10:48 +00004746 typval_T tvcopy;
4747
4748 copy_tv(&li->li_tv, &tvcopy);
4749 list_set_item(rem_list, i, &tvcopy);
Bram Moolenaar792f7862020-11-23 08:31:18 +01004750 li = li->li_next;
4751 }
4752 --count;
4753 }
4754
4755 // Produce the values in reverse order, first item last.
4756 li = l->lv_first;
4757 for (i = 0; i < count; ++i)
4758 {
4759 tv = STACK_TV_BOT(-i - 1);
4760 copy_tv(&li->li_tv, tv);
4761 li = li->li_next;
4762 }
4763
4764 list_unref(l);
4765 }
4766 break;
4767
Bram Moolenaarb2049902021-01-24 12:53:53 +01004768 case ISN_PROF_START:
4769 case ISN_PROF_END:
4770 {
Bram Moolenaarf002a412021-01-24 13:34:18 +01004771#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01004772 funccall_T cookie;
4773 ufunc_T *cur_ufunc =
4774 (((dfunc_T *)def_functions.ga_data)
Bram Moolenaarb69c6fb2021-06-14 20:40:37 +02004775 + ectx->ec_dfunc_idx)->df_ufunc;
Bram Moolenaarb2049902021-01-24 12:53:53 +01004776
4777 cookie.func = cur_ufunc;
4778 if (iptr->isn_type == ISN_PROF_START)
4779 {
4780 func_line_start(&cookie, iptr->isn_lnum);
4781 // if we get here the instruction is executed
4782 func_line_exec(&cookie);
4783 }
4784 else
4785 func_line_end(&cookie);
Bram Moolenaarf002a412021-01-24 13:34:18 +01004786#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01004787 }
4788 break;
4789
Bram Moolenaare99d4222021-06-13 14:01:26 +02004790 case ISN_DEBUG:
Bram Moolenaar4f8f5422021-06-20 19:28:14 +02004791 handle_debug(iptr, ectx);
Bram Moolenaare99d4222021-06-13 14:01:26 +02004792 break;
4793
Bram Moolenaar389df252020-07-09 21:20:47 +02004794 case ISN_SHUFFLE:
4795 {
Bram Moolenaar792f7862020-11-23 08:31:18 +01004796 typval_T tmp_tv;
4797 int item = iptr->isn_arg.shuffle.shfl_item;
4798 int up = iptr->isn_arg.shuffle.shfl_up;
Bram Moolenaar389df252020-07-09 21:20:47 +02004799
4800 tmp_tv = *STACK_TV_BOT(-item);
4801 for ( ; up > 0 && item > 1; --up)
4802 {
4803 *STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1);
4804 --item;
4805 }
4806 *STACK_TV_BOT(-item) = tmp_tv;
4807 }
4808 break;
4809
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004810 case ISN_DROP:
Bram Moolenaar4c137212021-04-19 16:48:48 +02004811 --ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004812 clear_tv(STACK_TV_BOT(0));
Bram Moolenaar4c137212021-04-19 16:48:48 +02004813 ectx->ec_where.wt_index = 0;
4814 ectx->ec_where.wt_variable = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004815 break;
4816 }
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004817 continue;
4818
Bram Moolenaard032f342020-07-18 18:13:02 +02004819func_return:
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02004820 // Restore previous function. If the frame pointer is where we started
4821 // then there is none and we are done.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004822 if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx)
Bram Moolenaard032f342020-07-18 18:13:02 +02004823 goto done;
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02004824
Bram Moolenaar4c137212021-04-19 16:48:48 +02004825 if (func_return(ectx) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02004826 // only fails when out of memory
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004827 goto theend;
Bram Moolenaarc7db5772020-07-21 20:55:50 +02004828 continue;
Bram Moolenaard032f342020-07-18 18:13:02 +02004829
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02004830on_error:
Bram Moolenaaraf0df472020-12-02 20:51:22 +01004831 // Jump here for an error that does not require aborting execution.
Bram Moolenaar56602ba2020-12-05 21:22:08 +01004832 // If "emsg_silent" is set then ignore the error, unless it was set
4833 // when calling the function.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004834 if (did_emsg_cumul + did_emsg == ectx->ec_did_emsg_before
Bram Moolenaar56602ba2020-12-05 21:22:08 +01004835 && emsg_silent && did_emsg_def == 0)
Bram Moolenaarf9041332021-01-21 19:41:16 +01004836 {
4837 // If a sequence of instructions causes an error while ":silent!"
4838 // was used, restore the stack length and jump ahead to restoring
4839 // the cmdmod.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004840 if (ectx->ec_funclocal.floc_restore_cmdmod)
Bram Moolenaarf9041332021-01-21 19:41:16 +01004841 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004842 while (ectx->ec_stack.ga_len
4843 > ectx->ec_funclocal.floc_restore_cmdmod_stacklen)
Bram Moolenaarf9041332021-01-21 19:41:16 +01004844 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004845 --ectx->ec_stack.ga_len;
Bram Moolenaarf9041332021-01-21 19:41:16 +01004846 clear_tv(STACK_TV_BOT(0));
4847 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02004848 while (ectx->ec_instr[ectx->ec_iidx].isn_type != ISN_CMDMOD_REV)
4849 ++ectx->ec_iidx;
Bram Moolenaarf9041332021-01-21 19:41:16 +01004850 }
Bram Moolenaarcd030c42020-10-30 21:49:40 +01004851 continue;
Bram Moolenaarf9041332021-01-21 19:41:16 +01004852 }
Bram Moolenaaraf0df472020-12-02 20:51:22 +01004853on_fatal_error:
4854 // Jump here for an error that messes up the stack.
Bram Moolenaar171fb922020-10-28 16:54:47 +01004855 // If we are not inside a try-catch started here, abort execution.
Bram Moolenaar4c137212021-04-19 16:48:48 +02004856 if (trylevel <= ectx->ec_trylevel_at_start)
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004857 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004858 }
4859
4860done:
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004861 ret = OK;
4862theend:
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02004863 dict_stack_clear(dict_stack_len_at_start);
Bram Moolenaarcbe178e2021-05-18 17:49:59 +02004864 ectx->ec_trylevel_at_start = save_trylevel_at_start;
4865 return ret;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004866}
4867
4868/*
Bram Moolenaarf18332f2021-05-07 17:55:55 +02004869 * Execute the instructions from a VAR_INSTR typeval and put the result in
4870 * "rettv".
4871 * Return OK or FAIL.
4872 */
4873 int
4874exe_typval_instr(typval_T *tv, typval_T *rettv)
4875{
4876 ectx_T *ectx = tv->vval.v_instr->instr_ectx;
4877 isn_T *save_instr = ectx->ec_instr;
4878 int save_iidx = ectx->ec_iidx;
4879 int res;
4880
4881 ectx->ec_instr = tv->vval.v_instr->instr_instr;
4882 res = exec_instructions(ectx);
4883 if (res == OK)
4884 {
4885 *rettv = *STACK_TV_BOT(-1);
4886 --ectx->ec_stack.ga_len;
4887 }
4888
4889 ectx->ec_instr = save_instr;
4890 ectx->ec_iidx = save_iidx;
4891
4892 return res;
4893}
4894
4895/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02004896 * Execute the instructions from an ISN_SUBSTITUTE command, which are in
4897 * "substitute_instr".
4898 */
4899 char_u *
4900exe_substitute_instr(void)
4901{
4902 ectx_T *ectx = substitute_instr->subs_ectx;
4903 isn_T *save_instr = ectx->ec_instr;
4904 int save_iidx = ectx->ec_iidx;
4905 char_u *res;
4906
4907 ectx->ec_instr = substitute_instr->subs_instr;
4908 if (exec_instructions(ectx) == OK)
Bram Moolenaar90193e62021-04-04 20:49:50 +02004909 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004910 typval_T *tv = STACK_TV_BOT(-1);
4911
Bram Moolenaar27523602021-06-05 21:36:19 +02004912 res = typval2string(tv, TRUE);
Bram Moolenaar4c137212021-04-19 16:48:48 +02004913 --ectx->ec_stack.ga_len;
4914 clear_tv(tv);
Bram Moolenaar90193e62021-04-04 20:49:50 +02004915 }
4916 else
4917 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02004918 substitute_instr->subs_status = FAIL;
4919 res = vim_strsave((char_u *)"");
Bram Moolenaar90193e62021-04-04 20:49:50 +02004920 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004921
Bram Moolenaar4c137212021-04-19 16:48:48 +02004922 ectx->ec_instr = save_instr;
4923 ectx->ec_iidx = save_iidx;
4924
4925 return res;
4926}
4927
4928/*
4929 * Call a "def" function from old Vim script.
4930 * Return OK or FAIL.
4931 */
4932 int
4933call_def_function(
4934 ufunc_T *ufunc,
4935 int argc_arg, // nr of arguments
4936 typval_T *argv, // arguments
4937 partial_T *partial, // optional partial for context
4938 typval_T *rettv) // return value
4939{
4940 ectx_T ectx; // execution context
4941 int argc = argc_arg;
4942 typval_T *tv;
4943 int idx;
4944 int ret = FAIL;
4945 int defcount = ufunc->uf_args.ga_len - argc;
4946 sctx_T save_current_sctx = current_sctx;
4947 int did_emsg_before = did_emsg_cumul + did_emsg;
4948 int save_suppress_errthrow = suppress_errthrow;
4949 msglist_T **saved_msg_list = NULL;
4950 msglist_T *private_msg_list = NULL;
4951 int save_emsg_silent_def = emsg_silent_def;
4952 int save_did_emsg_def = did_emsg_def;
4953 int orig_funcdepth;
Bram Moolenaare99d4222021-06-13 14:01:26 +02004954 int orig_nesting_level = ex_nesting_level;
Bram Moolenaar4c137212021-04-19 16:48:48 +02004955
4956// Get pointer to item in the stack.
4957#undef STACK_TV
4958#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
4959
4960// Get pointer to item at the bottom of the stack, -1 is the bottom.
4961#undef STACK_TV_BOT
4962#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
4963
4964// Get pointer to a local variable on the stack. Negative for arguments.
4965#undef STACK_TV_VAR
4966#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
4967
4968 if (ufunc->uf_def_status == UF_NOT_COMPILED
4969 || ufunc->uf_def_status == UF_COMPILE_ERROR
Bram Moolenaar139575d2022-03-15 19:29:30 +00004970 || (func_needs_compiling(ufunc, get_compile_type(ufunc))
4971 && compile_def_function(ufunc, FALSE,
4972 get_compile_type(ufunc), NULL) == FAIL))
Bram Moolenaar4c137212021-04-19 16:48:48 +02004973 {
4974 if (did_emsg_cumul + did_emsg == did_emsg_before)
4975 semsg(_(e_function_is_not_compiled_str),
4976 printable_func_name(ufunc));
4977 return FAIL;
4978 }
4979
4980 {
4981 // Check the function was really compiled.
4982 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
4983 + ufunc->uf_dfunc_idx;
4984 if (INSTRUCTIONS(dfunc) == NULL)
4985 {
4986 iemsg("using call_def_function() on not compiled function");
4987 return FAIL;
4988 }
4989 }
4990
4991 // If depth of calling is getting too high, don't execute the function.
4992 orig_funcdepth = funcdepth_get();
4993 if (funcdepth_increment() == FAIL)
4994 return FAIL;
4995
4996 CLEAR_FIELD(ectx);
4997 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
4998 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
Bram Moolenaar35578162021-08-02 19:10:38 +02004999 if (GA_GROW_FAILS(&ectx.ec_stack, 20))
Bram Moolenaar4c137212021-04-19 16:48:48 +02005000 {
5001 funcdepth_decrement();
5002 return FAIL;
5003 }
5004 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
5005 ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
5006 ectx.ec_did_emsg_before = did_emsg_before;
Bram Moolenaare99d4222021-06-13 14:01:26 +02005007 ++ex_nesting_level;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005008
5009 idx = argc - ufunc->uf_args.ga_len;
5010 if (idx > 0 && ufunc->uf_va_name == NULL)
5011 {
5012 if (idx == 1)
5013 emsg(_(e_one_argument_too_many));
5014 else
5015 semsg(_(e_nr_arguments_too_many), idx);
5016 goto failed_early;
5017 }
Bram Moolenaarc6d71532021-06-05 18:49:38 +02005018 idx = argc - ufunc->uf_args.ga_len + ufunc->uf_def_args.ga_len;
5019 if (idx < 0)
Bram Moolenaar8da6d6d2021-06-05 18:15:09 +02005020 {
5021 if (idx == -1)
5022 emsg(_(e_one_argument_too_few));
5023 else
5024 semsg(_(e_nr_arguments_too_few), -idx);
5025 goto failed_early;
5026 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005027
5028 // Put arguments on the stack, but no more than what the function expects.
5029 // A lambda can be called with more arguments than it uses.
5030 for (idx = 0; idx < argc
5031 && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len);
5032 ++idx)
5033 {
5034 if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len
5035 && argv[idx].v_type == VAR_SPECIAL
5036 && argv[idx].vval.v_number == VVAL_NONE)
5037 {
5038 // Use the default value.
5039 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
5040 }
5041 else
5042 {
5043 if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
5044 && check_typval_arg_type(
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02005045 ufunc->uf_arg_types[idx], &argv[idx],
5046 NULL, idx + 1) == FAIL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005047 goto failed_early;
5048 copy_tv(&argv[idx], STACK_TV_BOT(0));
5049 }
5050 ++ectx.ec_stack.ga_len;
5051 }
5052
5053 // Turn varargs into a list. Empty list if no args.
5054 if (ufunc->uf_va_name != NULL)
5055 {
5056 int vararg_count = argc - ufunc->uf_args.ga_len;
5057
5058 if (vararg_count < 0)
5059 vararg_count = 0;
5060 else
5061 argc -= vararg_count;
5062 if (exe_newlist(vararg_count, &ectx) == FAIL)
5063 goto failed_early;
5064
5065 // Check the type of the list items.
5066 tv = STACK_TV_BOT(-1);
5067 if (ufunc->uf_va_type != NULL
5068 && ufunc->uf_va_type != &t_list_any
5069 && ufunc->uf_va_type->tt_member != &t_any
5070 && tv->vval.v_list != NULL)
5071 {
5072 type_T *expected = ufunc->uf_va_type->tt_member;
5073 listitem_T *li = tv->vval.v_list->lv_first;
5074
5075 for (idx = 0; idx < vararg_count; ++idx)
5076 {
5077 if (check_typval_arg_type(expected, &li->li_tv,
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02005078 NULL, argc + idx + 1) == FAIL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005079 goto failed_early;
5080 li = li->li_next;
5081 }
5082 }
5083
5084 if (defcount > 0)
5085 // Move varargs list to below missing default arguments.
5086 *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1);
5087 --ectx.ec_stack.ga_len;
5088 }
5089
5090 // Make space for omitted arguments, will store default value below.
5091 // Any varargs list goes after them.
5092 if (defcount > 0)
5093 for (idx = 0; idx < defcount; ++idx)
5094 {
5095 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
5096 ++ectx.ec_stack.ga_len;
5097 }
5098 if (ufunc->uf_va_name != NULL)
5099 ++ectx.ec_stack.ga_len;
5100
5101 // Frame pointer points to just after arguments.
5102 ectx.ec_frame_idx = ectx.ec_stack.ga_len;
5103 ectx.ec_initial_frame_idx = ectx.ec_frame_idx;
5104
5105 {
5106 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5107 + ufunc->uf_dfunc_idx;
5108 ufunc_T *base_ufunc = dfunc->df_ufunc;
5109
5110 // "uf_partial" is on the ufunc that "df_ufunc" points to, as is done
5111 // by copy_func().
5112 if (partial != NULL || base_ufunc->uf_partial != NULL)
5113 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005114 ectx.ec_outer_ref = ALLOC_CLEAR_ONE(outer_ref_T);
5115 if (ectx.ec_outer_ref == NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005116 goto failed_early;
5117 if (partial != NULL)
5118 {
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +00005119 outer_T *outer = get_pt_outer(partial);
5120
5121 if (outer->out_stack == NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02005122 {
Bram Moolenaarfe1bfc92022-02-06 13:55:03 +00005123 if (current_ectx != NULL)
5124 {
5125 if (current_ectx->ec_outer_ref != NULL
5126 && current_ectx->ec_outer_ref->or_outer != NULL)
5127 ectx.ec_outer_ref->or_outer =
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005128 current_ectx->ec_outer_ref->or_outer;
Bram Moolenaarfe1bfc92022-02-06 13:55:03 +00005129 }
5130 // Should there be an error here?
Bram Moolenaar4c137212021-04-19 16:48:48 +02005131 }
5132 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005133 {
Bram Moolenaar7aca5ca2022-02-07 19:56:43 +00005134 ectx.ec_outer_ref->or_outer = outer;
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005135 ++partial->pt_refcount;
5136 ectx.ec_outer_ref->or_partial = partial;
5137 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005138 }
5139 else
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005140 {
5141 ectx.ec_outer_ref->or_outer = &base_ufunc->uf_partial->pt_outer;
5142 ++base_ufunc->uf_partial->pt_refcount;
5143 ectx.ec_outer_ref->or_partial = base_ufunc->uf_partial;
5144 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005145 }
5146 }
5147
5148 // dummy frame entries
5149 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
5150 {
5151 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
5152 ++ectx.ec_stack.ga_len;
5153 }
5154
5155 {
5156 // Reserve space for local variables and any closure reference count.
5157 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5158 + ufunc->uf_dfunc_idx;
5159
Bram Moolenaar5cd64792021-12-25 18:23:24 +00005160 // Initialize variables to zero. That avoids having to generate
5161 // initializing instructions for "var nr: number", "var x: any", etc.
Bram Moolenaar4c137212021-04-19 16:48:48 +02005162 for (idx = 0; idx < dfunc->df_varcount; ++idx)
Bram Moolenaar5cd64792021-12-25 18:23:24 +00005163 {
5164 STACK_TV_VAR(idx)->v_type = VAR_NUMBER;
5165 STACK_TV_VAR(idx)->vval.v_number = 0;
5166 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005167 ectx.ec_stack.ga_len += dfunc->df_varcount;
5168 if (dfunc->df_has_closure)
5169 {
5170 STACK_TV_VAR(idx)->v_type = VAR_NUMBER;
5171 STACK_TV_VAR(idx)->vval.v_number = 0;
5172 ++ectx.ec_stack.ga_len;
5173 }
5174
5175 ectx.ec_instr = INSTRUCTIONS(dfunc);
5176 }
5177
5178 // Following errors are in the function, not the caller.
5179 // Commands behave like vim9script.
5180 estack_push_ufunc(ufunc, 1);
5181 current_sctx = ufunc->uf_script_ctx;
5182 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5183
5184 // Use a specific location for storing error messages to be converted to an
5185 // exception.
5186 saved_msg_list = msg_list;
5187 msg_list = &private_msg_list;
5188
5189 // Do turn errors into exceptions.
5190 suppress_errthrow = FALSE;
5191
5192 // Do not delete the function while executing it.
5193 ++ufunc->uf_calls;
5194
5195 // When ":silent!" was used before calling then we still abort the
5196 // function. If ":silent!" is used in the function then we don't.
5197 emsg_silent_def = emsg_silent;
5198 did_emsg_def = 0;
5199
5200 ectx.ec_where.wt_index = 0;
5201 ectx.ec_where.wt_variable = FALSE;
5202
5203 // Execute the instructions until done.
5204 ret = exec_instructions(&ectx);
5205 if (ret == OK)
5206 {
5207 // function finished, get result from the stack.
5208 if (ufunc->uf_ret_type == &t_void)
5209 {
5210 rettv->v_type = VAR_VOID;
5211 }
5212 else
5213 {
5214 tv = STACK_TV_BOT(-1);
5215 *rettv = *tv;
5216 tv->v_type = VAR_UNKNOWN;
5217 }
5218 }
5219
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01005220 // When failed need to unwind the call stack.
Bram Moolenaar4c137212021-04-19 16:48:48 +02005221 while (ectx.ec_frame_idx != ectx.ec_initial_frame_idx)
5222 func_return(&ectx);
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02005223
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02005224 // Deal with any remaining closures, they may be in use somewhere.
5225 if (ectx.ec_funcrefs.ga_len > 0)
Bram Moolenaarf112f302020-12-20 17:47:52 +01005226 {
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02005227 handle_closure_in_use(&ectx, FALSE);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00005228 ga_clear(&ectx.ec_funcrefs);
Bram Moolenaarf112f302020-12-20 17:47:52 +01005229 }
Bram Moolenaarc70bdab2020-09-26 19:59:38 +02005230
Bram Moolenaaree8580e2020-08-28 17:19:07 +02005231 estack_pop();
5232 current_sctx = save_current_sctx;
5233
Bram Moolenaar2336c372021-12-06 15:06:54 +00005234 if (--ufunc->uf_calls <= 0 && ufunc->uf_refcount <= 0)
5235 // Function was unreferenced while being used, free it now.
5236 func_clear_free(ufunc, FALSE);
Bram Moolenaarc970e422021-03-17 15:03:04 +01005237
Bram Moolenaar352134b2020-10-17 22:04:08 +02005238 if (*msg_list != NULL && saved_msg_list != NULL)
5239 {
5240 msglist_T **plist = saved_msg_list;
5241
5242 // Append entries from the current msg_list (uncaught exceptions) to
5243 // the saved msg_list.
5244 while (*plist != NULL)
5245 plist = &(*plist)->next;
5246
5247 *plist = *msg_list;
5248 }
5249 msg_list = saved_msg_list;
5250
Bram Moolenaar4c137212021-04-19 16:48:48 +02005251 if (ectx.ec_funclocal.floc_restore_cmdmod)
Bram Moolenaar02194d22020-10-24 23:08:38 +02005252 {
5253 cmdmod.cmod_filter_regmatch.regprog = NULL;
5254 undo_cmdmod(&cmdmod);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005255 cmdmod = ectx.ec_funclocal.floc_save_cmdmod;
Bram Moolenaar02194d22020-10-24 23:08:38 +02005256 }
Bram Moolenaar56602ba2020-12-05 21:22:08 +01005257 emsg_silent_def = save_emsg_silent_def;
5258 did_emsg_def += save_did_emsg_def;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02005259
Bram Moolenaaree8580e2020-08-28 17:19:07 +02005260failed_early:
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02005261 // Free all local variables, but not arguments.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005262 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
5263 clear_tv(STACK_TV(idx));
Bram Moolenaare99d4222021-06-13 14:01:26 +02005264 ex_nesting_level = orig_nesting_level;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02005265
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005266 vim_free(ectx.ec_stack.ga_data);
Bram Moolenaar20431c92020-03-20 18:39:46 +01005267 vim_free(ectx.ec_trystack.ga_data);
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005268 if (ectx.ec_outer_ref != NULL)
Bram Moolenaar0186e582021-01-10 18:33:11 +01005269 {
Bram Moolenaarc04f2a42021-06-09 19:30:03 +02005270 if (ectx.ec_outer_ref->or_outer_allocated)
5271 vim_free(ectx.ec_outer_ref->or_outer);
5272 partial_unref(ectx.ec_outer_ref->or_partial);
5273 vim_free(ectx.ec_outer_ref);
Bram Moolenaar0186e582021-01-10 18:33:11 +01005274 }
5275
Bram Moolenaar77e5dcc2020-09-17 21:29:03 +02005276 // Not sure if this is necessary.
5277 suppress_errthrow = save_suppress_errthrow;
5278
Bram Moolenaarb5841b92021-07-15 18:09:53 +02005279 if (ret != OK && did_emsg_cumul + did_emsg == did_emsg_before
5280 && !need_rethrow)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005281 semsg(_(e_unknown_error_while_executing_str),
Bram Moolenaar682d0a12020-07-19 20:48:59 +02005282 printable_func_name(ufunc));
Bram Moolenaar0ba48e82020-11-17 18:23:19 +01005283 funcdepth_restore(orig_funcdepth);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005284 return ret;
5285}
5286
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005287/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02005288 * List instructions "instr" up to "instr_count" or until ISN_FINISH.
5289 * "ufunc" has the source lines, NULL for the instructions of ISN_SUBSTITUTE.
5290 * "pfx" is prefixed to every line.
5291 */
5292 static void
5293list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
5294{
5295 int line_idx = 0;
5296 int prev_current = 0;
5297 int current;
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02005298 int def_arg_idx = 0;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005299
5300 for (current = 0; current < instr_count; ++current)
5301 {
5302 isn_T *iptr = &instr[current];
5303 char *line;
5304
5305 if (ufunc != NULL)
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02005306 {
Bram Moolenaar4c137212021-04-19 16:48:48 +02005307 while (line_idx < iptr->isn_lnum
5308 && line_idx < ufunc->uf_lines.ga_len)
5309 {
5310 if (current > prev_current)
5311 {
5312 msg_puts("\n\n");
5313 prev_current = current;
5314 }
5315 line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
5316 if (line != NULL)
5317 msg(line);
5318 }
Bram Moolenaar9ce47ec2021-04-20 22:16:39 +02005319 if (iptr->isn_type == ISN_JUMP_IF_ARG_SET)
5320 {
5321 int first_def_arg = ufunc->uf_args.ga_len
5322 - ufunc->uf_def_args.ga_len;
5323
5324 if (def_arg_idx > 0)
5325 msg_puts("\n\n");
5326 msg_start();
5327 msg_puts(" ");
5328 msg_puts(((char **)(ufunc->uf_args.ga_data))[
5329 first_def_arg + def_arg_idx]);
5330 msg_puts(" = ");
5331 msg_puts(((char **)(ufunc->uf_def_args.ga_data))[def_arg_idx++]);
5332 msg_clr_eos();
5333 msg_end();
5334 }
5335 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02005336
5337 switch (iptr->isn_type)
5338 {
5339 case ISN_EXEC:
5340 smsg("%s%4d EXEC %s", pfx, current, iptr->isn_arg.string);
5341 break;
Bram Moolenaar20677332021-06-06 17:02:53 +02005342 case ISN_EXEC_SPLIT:
5343 smsg("%s%4d EXEC_SPLIT %s", pfx, current, iptr->isn_arg.string);
5344 break;
Bram Moolenaare4eed8c2021-12-01 15:22:56 +00005345 case ISN_EXECRANGE:
5346 smsg("%s%4d EXECRANGE %s", pfx, current, iptr->isn_arg.string);
5347 break;
Bram Moolenaar3b1373b2021-05-17 00:01:42 +02005348 case ISN_LEGACY_EVAL:
5349 smsg("%s%4d EVAL legacy %s", pfx, current,
5350 iptr->isn_arg.string);
5351 break;
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02005352 case ISN_REDIRSTART:
5353 smsg("%s%4d REDIR", pfx, current);
5354 break;
5355 case ISN_REDIREND:
5356 smsg("%s%4d REDIR END%s", pfx, current,
5357 iptr->isn_arg.number ? " append" : "");
5358 break;
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02005359 case ISN_CEXPR_AUCMD:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02005360#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02005361 smsg("%s%4d CEXPR pre %s", pfx, current,
5362 cexpr_get_auname(iptr->isn_arg.number));
Bram Moolenaarb7c97812021-05-05 22:51:39 +02005363#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02005364 break;
5365 case ISN_CEXPR_CORE:
Bram Moolenaarb7c97812021-05-05 22:51:39 +02005366#ifdef FEAT_QUICKFIX
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02005367 {
5368 cexprref_T *cer = iptr->isn_arg.cexpr.cexpr_ref;
5369
5370 smsg("%s%4d CEXPR core %s%s \"%s\"", pfx, current,
5371 cexpr_get_auname(cer->cer_cmdidx),
5372 cer->cer_forceit ? "!" : "",
5373 cer->cer_cmdline);
5374 }
Bram Moolenaarb7c97812021-05-05 22:51:39 +02005375#endif
Bram Moolenaar5f7d4c02021-05-05 21:31:39 +02005376 break;
Bram Moolenaarf18332f2021-05-07 17:55:55 +02005377 case ISN_INSTR:
5378 {
5379 smsg("%s%4d INSTR", pfx, current);
5380 list_instructions(" ", iptr->isn_arg.instr,
5381 INT_MAX, NULL);
5382 msg(" -------------");
5383 }
5384 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005385 case ISN_SUBSTITUTE:
5386 {
5387 subs_T *subs = &iptr->isn_arg.subs;
5388
5389 smsg("%s%4d SUBSTITUTE %s", pfx, current, subs->subs_cmd);
5390 list_instructions(" ", subs->subs_instr, INT_MAX, NULL);
5391 msg(" -------------");
5392 }
5393 break;
5394 case ISN_EXECCONCAT:
5395 smsg("%s%4d EXECCONCAT %lld", pfx, current,
5396 (varnumber_T)iptr->isn_arg.number);
5397 break;
5398 case ISN_ECHO:
5399 {
5400 echo_T *echo = &iptr->isn_arg.echo;
5401
5402 smsg("%s%4d %s %d", pfx, current,
5403 echo->echo_with_white ? "ECHO" : "ECHON",
5404 echo->echo_count);
5405 }
5406 break;
5407 case ISN_EXECUTE:
5408 smsg("%s%4d EXECUTE %lld", pfx, current,
Bram Moolenaar7de62622021-08-07 15:05:47 +02005409 (varnumber_T)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005410 break;
5411 case ISN_ECHOMSG:
5412 smsg("%s%4d ECHOMSG %lld", pfx, current,
Bram Moolenaar7de62622021-08-07 15:05:47 +02005413 (varnumber_T)(iptr->isn_arg.number));
5414 break;
5415 case ISN_ECHOCONSOLE:
5416 smsg("%s%4d ECHOCONSOLE %lld", pfx, current,
5417 (varnumber_T)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005418 break;
5419 case ISN_ECHOERR:
5420 smsg("%s%4d ECHOERR %lld", pfx, current,
Bram Moolenaar7de62622021-08-07 15:05:47 +02005421 (varnumber_T)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005422 break;
5423 case ISN_LOAD:
5424 {
5425 if (iptr->isn_arg.number < 0)
5426 smsg("%s%4d LOAD arg[%lld]", pfx, current,
5427 (varnumber_T)(iptr->isn_arg.number
5428 + STACK_FRAME_SIZE));
5429 else
5430 smsg("%s%4d LOAD $%lld", pfx, current,
5431 (varnumber_T)(iptr->isn_arg.number));
5432 }
5433 break;
5434 case ISN_LOADOUTER:
5435 {
5436 if (iptr->isn_arg.number < 0)
5437 smsg("%s%4d LOADOUTER level %d arg[%d]", pfx, current,
5438 iptr->isn_arg.outer.outer_depth,
5439 iptr->isn_arg.outer.outer_idx
5440 + STACK_FRAME_SIZE);
5441 else
5442 smsg("%s%4d LOADOUTER level %d $%d", pfx, current,
5443 iptr->isn_arg.outer.outer_depth,
5444 iptr->isn_arg.outer.outer_idx);
5445 }
5446 break;
5447 case ISN_LOADV:
5448 smsg("%s%4d LOADV v:%s", pfx, current,
5449 get_vim_var_name(iptr->isn_arg.number));
5450 break;
5451 case ISN_LOADSCRIPT:
5452 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005453 scriptref_T *sref = iptr->isn_arg.script.scriptref;
5454 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
5455 svar_T *sv;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005456
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005457 sv = get_script_svar(sref, -1);
5458 if (sv == NULL)
5459 smsg("%s%4d LOADSCRIPT [deleted] from %s",
5460 pfx, current, si->sn_name);
5461 else
5462 smsg("%s%4d LOADSCRIPT %s-%d from %s", pfx, current,
Bram Moolenaar4c137212021-04-19 16:48:48 +02005463 sv->sv_name,
5464 sref->sref_idx,
5465 si->sn_name);
5466 }
5467 break;
5468 case ISN_LOADS:
5469 {
5470 scriptitem_T *si = SCRIPT_ITEM(
5471 iptr->isn_arg.loadstore.ls_sid);
5472
5473 smsg("%s%4d LOADS s:%s from %s", pfx, current,
5474 iptr->isn_arg.loadstore.ls_name, si->sn_name);
5475 }
5476 break;
5477 case ISN_LOADAUTO:
5478 smsg("%s%4d LOADAUTO %s", pfx, current, iptr->isn_arg.string);
5479 break;
5480 case ISN_LOADG:
5481 smsg("%s%4d LOADG g:%s", pfx, current, iptr->isn_arg.string);
5482 break;
5483 case ISN_LOADB:
5484 smsg("%s%4d LOADB b:%s", pfx, current, iptr->isn_arg.string);
5485 break;
5486 case ISN_LOADW:
5487 smsg("%s%4d LOADW w:%s", pfx, current, iptr->isn_arg.string);
5488 break;
5489 case ISN_LOADT:
5490 smsg("%s%4d LOADT t:%s", pfx, current, iptr->isn_arg.string);
5491 break;
5492 case ISN_LOADGDICT:
5493 smsg("%s%4d LOAD g:", pfx, current);
5494 break;
5495 case ISN_LOADBDICT:
5496 smsg("%s%4d LOAD b:", pfx, current);
5497 break;
5498 case ISN_LOADWDICT:
5499 smsg("%s%4d LOAD w:", pfx, current);
5500 break;
5501 case ISN_LOADTDICT:
5502 smsg("%s%4d LOAD t:", pfx, current);
5503 break;
5504 case ISN_LOADOPT:
5505 smsg("%s%4d LOADOPT %s", pfx, current, iptr->isn_arg.string);
5506 break;
5507 case ISN_LOADENV:
5508 smsg("%s%4d LOADENV %s", pfx, current, iptr->isn_arg.string);
5509 break;
5510 case ISN_LOADREG:
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005511 smsg("%s%4d LOADREG @%c", pfx, current,
5512 (int)(iptr->isn_arg.number));
Bram Moolenaar4c137212021-04-19 16:48:48 +02005513 break;
5514
5515 case ISN_STORE:
5516 if (iptr->isn_arg.number < 0)
5517 smsg("%s%4d STORE arg[%lld]", pfx, current,
5518 iptr->isn_arg.number + STACK_FRAME_SIZE);
5519 else
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005520 smsg("%s%4d STORE $%lld", pfx, current,
5521 iptr->isn_arg.number);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005522 break;
5523 case ISN_STOREOUTER:
5524 {
5525 if (iptr->isn_arg.number < 0)
5526 smsg("%s%4d STOREOUTEr level %d arg[%d]", pfx, current,
5527 iptr->isn_arg.outer.outer_depth,
5528 iptr->isn_arg.outer.outer_idx + STACK_FRAME_SIZE);
5529 else
5530 smsg("%s%4d STOREOUTER level %d $%d", pfx, current,
5531 iptr->isn_arg.outer.outer_depth,
5532 iptr->isn_arg.outer.outer_idx);
5533 }
5534 break;
5535 case ISN_STOREV:
5536 smsg("%s%4d STOREV v:%s", pfx, current,
5537 get_vim_var_name(iptr->isn_arg.number));
5538 break;
5539 case ISN_STOREAUTO:
5540 smsg("%s%4d STOREAUTO %s", pfx, current, iptr->isn_arg.string);
5541 break;
5542 case ISN_STOREG:
5543 smsg("%s%4d STOREG %s", pfx, current, iptr->isn_arg.string);
5544 break;
5545 case ISN_STOREB:
5546 smsg("%s%4d STOREB %s", pfx, current, iptr->isn_arg.string);
5547 break;
5548 case ISN_STOREW:
5549 smsg("%s%4d STOREW %s", pfx, current, iptr->isn_arg.string);
5550 break;
5551 case ISN_STORET:
5552 smsg("%s%4d STORET %s", pfx, current, iptr->isn_arg.string);
5553 break;
5554 case ISN_STORES:
5555 {
5556 scriptitem_T *si = SCRIPT_ITEM(
5557 iptr->isn_arg.loadstore.ls_sid);
5558
5559 smsg("%s%4d STORES %s in %s", pfx, current,
5560 iptr->isn_arg.loadstore.ls_name, si->sn_name);
5561 }
5562 break;
5563 case ISN_STORESCRIPT:
5564 {
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005565 scriptref_T *sref = iptr->isn_arg.script.scriptref;
5566 scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
5567 svar_T *sv;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005568
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005569 sv = get_script_svar(sref, -1);
5570 if (sv == NULL)
5571 smsg("%s%4d STORESCRIPT [deleted] in %s",
5572 pfx, current, si->sn_name);
5573 else
5574 smsg("%s%4d STORESCRIPT %s-%d in %s", pfx, current,
Bram Moolenaar4c137212021-04-19 16:48:48 +02005575 sv->sv_name,
5576 sref->sref_idx,
5577 si->sn_name);
5578 }
5579 break;
5580 case ISN_STOREOPT:
Bram Moolenaardcb53be2021-12-09 14:23:43 +00005581 case ISN_STOREFUNCOPT:
5582 smsg("%s%4d %s &%s", pfx, current,
5583 iptr->isn_type == ISN_STOREOPT ? "STOREOPT" : "STOREFUNCOPT",
Bram Moolenaar4c137212021-04-19 16:48:48 +02005584 iptr->isn_arg.storeopt.so_name);
5585 break;
5586 case ISN_STOREENV:
5587 smsg("%s%4d STOREENV $%s", pfx, current, iptr->isn_arg.string);
5588 break;
5589 case ISN_STOREREG:
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005590 smsg("%s%4d STOREREG @%c", pfx, current,
5591 (int)iptr->isn_arg.number);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005592 break;
5593 case ISN_STORENR:
5594 smsg("%s%4d STORE %lld in $%d", pfx, current,
5595 iptr->isn_arg.storenr.stnr_val,
5596 iptr->isn_arg.storenr.stnr_idx);
5597 break;
5598
5599 case ISN_STOREINDEX:
5600 smsg("%s%4d STOREINDEX %s", pfx, current,
5601 vartype_name(iptr->isn_arg.vartype));
5602 break;
5603
5604 case ISN_STORERANGE:
5605 smsg("%s%4d STORERANGE", pfx, current);
5606 break;
5607
5608 // constants
5609 case ISN_PUSHNR:
5610 smsg("%s%4d PUSHNR %lld", pfx, current,
5611 (varnumber_T)(iptr->isn_arg.number));
5612 break;
5613 case ISN_PUSHBOOL:
5614 case ISN_PUSHSPEC:
5615 smsg("%s%4d PUSH %s", pfx, current,
5616 get_var_special_name(iptr->isn_arg.number));
5617 break;
5618 case ISN_PUSHF:
5619#ifdef FEAT_FLOAT
5620 smsg("%s%4d PUSHF %g", pfx, current, iptr->isn_arg.fnumber);
5621#endif
5622 break;
5623 case ISN_PUSHS:
5624 smsg("%s%4d PUSHS \"%s\"", pfx, current, iptr->isn_arg.string);
5625 break;
5626 case ISN_PUSHBLOB:
5627 {
5628 char_u *r;
5629 char_u numbuf[NUMBUFLEN];
5630 char_u *tofree;
5631
5632 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
5633 smsg("%s%4d PUSHBLOB %s", pfx, current, r);
5634 vim_free(tofree);
5635 }
5636 break;
5637 case ISN_PUSHFUNC:
5638 {
5639 char *name = (char *)iptr->isn_arg.string;
5640
5641 smsg("%s%4d PUSHFUNC \"%s\"", pfx, current,
5642 name == NULL ? "[none]" : name);
5643 }
5644 break;
5645 case ISN_PUSHCHANNEL:
5646#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar397a87a2022-03-20 21:14:15 +00005647 smsg("%s%4d PUSHCHANNEL 0", pfx, current);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005648#endif
5649 break;
5650 case ISN_PUSHJOB:
5651#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar397a87a2022-03-20 21:14:15 +00005652 smsg("%s%4d PUSHJOB \"no process\"", pfx, current);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005653#endif
5654 break;
5655 case ISN_PUSHEXC:
5656 smsg("%s%4d PUSH v:exception", pfx, current);
5657 break;
Bram Moolenaar06b77222022-01-25 15:51:56 +00005658 case ISN_AUTOLOAD:
5659 smsg("%s%4d AUTOLOAD %s", pfx, current, iptr->isn_arg.string);
5660 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005661 case ISN_UNLET:
5662 smsg("%s%4d UNLET%s %s", pfx, current,
5663 iptr->isn_arg.unlet.ul_forceit ? "!" : "",
5664 iptr->isn_arg.unlet.ul_name);
5665 break;
5666 case ISN_UNLETENV:
5667 smsg("%s%4d UNLETENV%s $%s", pfx, current,
5668 iptr->isn_arg.unlet.ul_forceit ? "!" : "",
5669 iptr->isn_arg.unlet.ul_name);
5670 break;
5671 case ISN_UNLETINDEX:
5672 smsg("%s%4d UNLETINDEX", pfx, current);
5673 break;
5674 case ISN_UNLETRANGE:
5675 smsg("%s%4d UNLETRANGE", pfx, current);
5676 break;
Bram Moolenaaraacc9662021-08-13 19:40:51 +02005677 case ISN_LOCKUNLOCK:
5678 smsg("%s%4d LOCKUNLOCK %s", pfx, current, iptr->isn_arg.string);
5679 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005680 case ISN_LOCKCONST:
5681 smsg("%s%4d LOCKCONST", pfx, current);
5682 break;
5683 case ISN_NEWLIST:
5684 smsg("%s%4d NEWLIST size %lld", pfx, current,
5685 (varnumber_T)(iptr->isn_arg.number));
5686 break;
5687 case ISN_NEWDICT:
5688 smsg("%s%4d NEWDICT size %lld", pfx, current,
5689 (varnumber_T)(iptr->isn_arg.number));
5690 break;
Bram Moolenaar8acb9cc2022-03-08 13:18:55 +00005691 case ISN_NEWPARTIAL:
5692 smsg("%s%4d NEWPARTIAL", pfx, current);
5693 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005694
5695 // function call
5696 case ISN_BCALL:
5697 {
5698 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc;
5699
5700 smsg("%s%4d BCALL %s(argc %d)", pfx, current,
5701 internal_func_name(cbfunc->cbf_idx),
5702 cbfunc->cbf_argcount);
5703 }
5704 break;
5705 case ISN_DCALL:
5706 {
5707 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc;
5708 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
5709 + cdfunc->cdf_idx;
5710
5711 smsg("%s%4d DCALL %s(argc %d)", pfx, current,
Bram Moolenaar6db660b2021-08-01 14:08:54 +02005712 printable_func_name(df->df_ufunc),
5713 cdfunc->cdf_argcount);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005714 }
5715 break;
5716 case ISN_UCALL:
5717 {
5718 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
5719
5720 smsg("%s%4d UCALL %s(argc %d)", pfx, current,
5721 cufunc->cuf_name, cufunc->cuf_argcount);
5722 }
5723 break;
5724 case ISN_PCALL:
5725 {
5726 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc;
5727
5728 smsg("%s%4d PCALL%s (argc %d)", pfx, current,
5729 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
5730 }
5731 break;
5732 case ISN_PCALL_END:
5733 smsg("%s%4d PCALL end", pfx, current);
5734 break;
5735 case ISN_RETURN:
5736 smsg("%s%4d RETURN", pfx, current);
5737 break;
Bram Moolenaarf57b43c2021-06-15 22:13:27 +02005738 case ISN_RETURN_VOID:
5739 smsg("%s%4d RETURN void", pfx, current);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005740 break;
5741 case ISN_FUNCREF:
5742 {
5743 funcref_T *funcref = &iptr->isn_arg.funcref;
Bram Moolenaar38453522021-11-28 22:00:12 +00005744 char_u *name;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005745
Bram Moolenaar38453522021-11-28 22:00:12 +00005746 if (funcref->fr_func_name == NULL)
5747 {
5748 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
5749 + funcref->fr_dfunc_idx;
5750 name = df->df_ufunc->uf_name;
5751 }
5752 else
5753 name = funcref->fr_func_name;
5754 smsg("%s%4d FUNCREF %s", pfx, current, name);
Bram Moolenaar4c137212021-04-19 16:48:48 +02005755 }
5756 break;
5757
5758 case ISN_NEWFUNC:
5759 {
5760 newfunc_T *newfunc = &iptr->isn_arg.newfunc;
5761
5762 smsg("%s%4d NEWFUNC %s %s", pfx, current,
5763 newfunc->nf_lambda, newfunc->nf_global);
5764 }
5765 break;
5766
5767 case ISN_DEF:
5768 {
5769 char_u *name = iptr->isn_arg.string;
5770
5771 smsg("%s%4d DEF %s", pfx, current,
5772 name == NULL ? (char_u *)"" : name);
5773 }
5774 break;
5775
5776 case ISN_JUMP:
5777 {
5778 char *when = "?";
5779
5780 switch (iptr->isn_arg.jump.jump_when)
5781 {
5782 case JUMP_ALWAYS:
5783 when = "JUMP";
5784 break;
Bram Moolenaar1a7ee4d2021-09-16 16:15:07 +02005785 case JUMP_NEVER:
5786 iemsg("JUMP_NEVER should not be used");
5787 break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005788 case JUMP_AND_KEEP_IF_TRUE:
5789 when = "JUMP_AND_KEEP_IF_TRUE";
5790 break;
5791 case JUMP_IF_FALSE:
5792 when = "JUMP_IF_FALSE";
5793 break;
5794 case JUMP_AND_KEEP_IF_FALSE:
5795 when = "JUMP_AND_KEEP_IF_FALSE";
5796 break;
5797 case JUMP_IF_COND_FALSE:
5798 when = "JUMP_IF_COND_FALSE";
5799 break;
5800 case JUMP_IF_COND_TRUE:
5801 when = "JUMP_IF_COND_TRUE";
5802 break;
5803 }
5804 smsg("%s%4d %s -> %d", pfx, current, when,
5805 iptr->isn_arg.jump.jump_where);
5806 }
5807 break;
5808
5809 case ISN_JUMP_IF_ARG_SET:
5810 smsg("%s%4d JUMP_IF_ARG_SET arg[%d] -> %d", pfx, current,
5811 iptr->isn_arg.jumparg.jump_arg_off + STACK_FRAME_SIZE,
5812 iptr->isn_arg.jump.jump_where);
5813 break;
5814
5815 case ISN_FOR:
5816 {
5817 forloop_T *forloop = &iptr->isn_arg.forloop;
5818
5819 smsg("%s%4d FOR $%d -> %d", pfx, current,
5820 forloop->for_idx, forloop->for_end);
5821 }
5822 break;
5823
5824 case ISN_TRY:
5825 {
Bram Moolenaar0d807102021-12-21 09:42:09 +00005826 try_T *try = &iptr->isn_arg.tryref;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005827
5828 if (try->try_ref->try_finally == 0)
5829 smsg("%s%4d TRY catch -> %d, endtry -> %d",
5830 pfx, current,
5831 try->try_ref->try_catch,
5832 try->try_ref->try_endtry);
5833 else
5834 smsg("%s%4d TRY catch -> %d, finally -> %d, endtry -> %d",
5835 pfx, current,
5836 try->try_ref->try_catch,
5837 try->try_ref->try_finally,
5838 try->try_ref->try_endtry);
5839 }
5840 break;
5841 case ISN_CATCH:
Bram Moolenaar4c137212021-04-19 16:48:48 +02005842 smsg("%s%4d CATCH", pfx, current);
5843 break;
5844 case ISN_TRYCONT:
5845 {
5846 trycont_T *trycont = &iptr->isn_arg.trycont;
5847
5848 smsg("%s%4d TRY-CONTINUE %d level%s -> %d", pfx, current,
5849 trycont->tct_levels,
5850 trycont->tct_levels == 1 ? "" : "s",
5851 trycont->tct_where);
5852 }
5853 break;
5854 case ISN_FINALLY:
5855 smsg("%s%4d FINALLY", pfx, current);
5856 break;
5857 case ISN_ENDTRY:
5858 smsg("%s%4d ENDTRY", pfx, current);
5859 break;
5860 case ISN_THROW:
5861 smsg("%s%4d THROW", pfx, current);
5862 break;
5863
5864 // expression operations on number
5865 case ISN_OPNR:
5866 case ISN_OPFLOAT:
5867 case ISN_OPANY:
5868 {
5869 char *what;
5870 char *ins;
5871
5872 switch (iptr->isn_arg.op.op_type)
5873 {
5874 case EXPR_MULT: what = "*"; break;
5875 case EXPR_DIV: what = "/"; break;
5876 case EXPR_REM: what = "%"; break;
5877 case EXPR_SUB: what = "-"; break;
5878 case EXPR_ADD: what = "+"; break;
5879 default: what = "???"; break;
5880 }
5881 switch (iptr->isn_type)
5882 {
5883 case ISN_OPNR: ins = "OPNR"; break;
5884 case ISN_OPFLOAT: ins = "OPFLOAT"; break;
5885 case ISN_OPANY: ins = "OPANY"; break;
5886 default: ins = "???"; break;
5887 }
5888 smsg("%s%4d %s %s", pfx, current, ins, what);
5889 }
5890 break;
5891
5892 case ISN_COMPAREBOOL:
5893 case ISN_COMPARESPECIAL:
Bram Moolenaar7a222242022-03-01 19:23:24 +00005894 case ISN_COMPARENULL:
Bram Moolenaar4c137212021-04-19 16:48:48 +02005895 case ISN_COMPARENR:
5896 case ISN_COMPAREFLOAT:
5897 case ISN_COMPARESTRING:
5898 case ISN_COMPAREBLOB:
5899 case ISN_COMPARELIST:
5900 case ISN_COMPAREDICT:
5901 case ISN_COMPAREFUNC:
5902 case ISN_COMPAREANY:
5903 {
5904 char *p;
5905 char buf[10];
5906 char *type;
5907
5908 switch (iptr->isn_arg.op.op_type)
5909 {
5910 case EXPR_EQUAL: p = "=="; break;
5911 case EXPR_NEQUAL: p = "!="; break;
5912 case EXPR_GREATER: p = ">"; break;
5913 case EXPR_GEQUAL: p = ">="; break;
5914 case EXPR_SMALLER: p = "<"; break;
5915 case EXPR_SEQUAL: p = "<="; break;
5916 case EXPR_MATCH: p = "=~"; break;
5917 case EXPR_IS: p = "is"; break;
5918 case EXPR_ISNOT: p = "isnot"; break;
5919 case EXPR_NOMATCH: p = "!~"; break;
5920 default: p = "???"; break;
5921 }
5922 STRCPY(buf, p);
5923 if (iptr->isn_arg.op.op_ic == TRUE)
5924 strcat(buf, "?");
5925 switch(iptr->isn_type)
5926 {
5927 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
5928 case ISN_COMPARESPECIAL:
5929 type = "COMPARESPECIAL"; break;
Bram Moolenaar7a222242022-03-01 19:23:24 +00005930 case ISN_COMPARENULL: type = "COMPARENULL"; break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005931 case ISN_COMPARENR: type = "COMPARENR"; break;
5932 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
5933 case ISN_COMPARESTRING:
5934 type = "COMPARESTRING"; break;
5935 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
5936 case ISN_COMPARELIST: type = "COMPARELIST"; break;
5937 case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
5938 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
5939 case ISN_COMPAREANY: type = "COMPAREANY"; break;
5940 default: type = "???"; break;
5941 }
5942
5943 smsg("%s%4d %s %s", pfx, current, type, buf);
5944 }
5945 break;
5946
5947 case ISN_ADDLIST: smsg("%s%4d ADDLIST", pfx, current); break;
5948 case ISN_ADDBLOB: smsg("%s%4d ADDBLOB", pfx, current); break;
5949
5950 // expression operations
5951 case ISN_CONCAT: smsg("%s%4d CONCAT", pfx, current); break;
5952 case ISN_STRINDEX: smsg("%s%4d STRINDEX", pfx, current); break;
5953 case ISN_STRSLICE: smsg("%s%4d STRSLICE", pfx, current); break;
5954 case ISN_BLOBINDEX: smsg("%s%4d BLOBINDEX", pfx, current); break;
5955 case ISN_BLOBSLICE: smsg("%s%4d BLOBSLICE", pfx, current); break;
5956 case ISN_LISTAPPEND: smsg("%s%4d LISTAPPEND", pfx, current); break;
5957 case ISN_BLOBAPPEND: smsg("%s%4d BLOBAPPEND", pfx, current); break;
5958 case ISN_LISTINDEX: smsg("%s%4d LISTINDEX", pfx, current); break;
5959 case ISN_LISTSLICE: smsg("%s%4d LISTSLICE", pfx, current); break;
5960 case ISN_ANYINDEX: smsg("%s%4d ANYINDEX", pfx, current); break;
5961 case ISN_ANYSLICE: smsg("%s%4d ANYSLICE", pfx, current); break;
5962 case ISN_SLICE: smsg("%s%4d SLICE %lld",
Bram Moolenaar4f0884d2021-08-11 21:49:23 +02005963 pfx, current, iptr->isn_arg.number); break;
Bram Moolenaar035bd1c2021-06-21 19:44:11 +02005964 case ISN_GETITEM: smsg("%s%4d ITEM %lld%s", pfx, current,
5965 iptr->isn_arg.getitem.gi_index,
5966 iptr->isn_arg.getitem.gi_with_op ?
5967 " with op" : ""); break;
Bram Moolenaar4c137212021-04-19 16:48:48 +02005968 case ISN_MEMBER: smsg("%s%4d MEMBER", pfx, current); break;
5969 case ISN_STRINGMEMBER: smsg("%s%4d MEMBER %s", pfx, current,
5970 iptr->isn_arg.string); break;
Bram Moolenaarb1b6f4d2021-09-13 18:25:54 +02005971 case ISN_CLEARDICT: smsg("%s%4d CLEARDICT", pfx, current); break;
5972 case ISN_USEDICT: smsg("%s%4d USEDICT", pfx, current); break;
5973
Bram Moolenaar4c137212021-04-19 16:48:48 +02005974 case ISN_NEGATENR: smsg("%s%4d NEGATENR", pfx, current); break;
5975
5976 case ISN_CHECKNR: smsg("%s%4d CHECKNR", pfx, current); break;
5977 case ISN_CHECKTYPE:
5978 {
5979 checktype_T *ct = &iptr->isn_arg.type;
5980 char *tofree;
5981
5982 if (ct->ct_arg_idx == 0)
5983 smsg("%s%4d CHECKTYPE %s stack[%d]", pfx, current,
5984 type_name(ct->ct_type, &tofree),
5985 (int)ct->ct_off);
5986 else
Bram Moolenaar4f0884d2021-08-11 21:49:23 +02005987 smsg("%s%4d CHECKTYPE %s stack[%d] arg %d",
5988 pfx, current,
Bram Moolenaar4c137212021-04-19 16:48:48 +02005989 type_name(ct->ct_type, &tofree),
5990 (int)ct->ct_off,
5991 (int)ct->ct_arg_idx);
5992 vim_free(tofree);
5993 break;
5994 }
5995 case ISN_CHECKLEN: smsg("%s%4d CHECKLEN %s%d", pfx, current,
5996 iptr->isn_arg.checklen.cl_more_OK ? ">= " : "",
5997 iptr->isn_arg.checklen.cl_min_len);
5998 break;
5999 case ISN_SETTYPE:
6000 {
6001 char *tofree;
6002
6003 smsg("%s%4d SETTYPE %s", pfx, current,
6004 type_name(iptr->isn_arg.type.ct_type, &tofree));
6005 vim_free(tofree);
6006 break;
6007 }
6008 case ISN_COND2BOOL: smsg("%s%4d COND2BOOL", pfx, current); break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006009 case ISN_2BOOL: if (iptr->isn_arg.tobool.invert)
6010 smsg("%s%4d INVERT %d (!val)", pfx, current,
6011 iptr->isn_arg.tobool.offset);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006012 else
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006013 smsg("%s%4d 2BOOL %d (!!val)", pfx, current,
6014 iptr->isn_arg.tobool.offset);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006015 break;
6016 case ISN_2STRING: smsg("%s%4d 2STRING stack[%lld]", pfx, current,
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006017 (varnumber_T)(iptr->isn_arg.tostring.offset));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006018 break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006019 case ISN_2STRING_ANY: smsg("%s%4d 2STRING_ANY stack[%lld]",
6020 pfx, current,
6021 (varnumber_T)(iptr->isn_arg.tostring.offset));
Bram Moolenaar4c137212021-04-19 16:48:48 +02006022 break;
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006023 case ISN_RANGE: smsg("%s%4d RANGE %s", pfx, current,
6024 iptr->isn_arg.string);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006025 break;
6026 case ISN_PUT:
6027 if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE_ABOVE)
6028 smsg("%s%4d PUT %c above range",
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006029 pfx, current, iptr->isn_arg.put.put_regname);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006030 else if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE)
6031 smsg("%s%4d PUT %c range",
Bram Moolenaar5fa9b242021-06-04 21:00:32 +02006032 pfx, current, iptr->isn_arg.put.put_regname);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006033 else
6034 smsg("%s%4d PUT %c %ld", pfx, current,
6035 iptr->isn_arg.put.put_regname,
6036 (long)iptr->isn_arg.put.put_lnum);
6037 break;
6038
Bram Moolenaar4c137212021-04-19 16:48:48 +02006039 case ISN_CMDMOD:
6040 {
6041 char_u *buf;
6042 size_t len = produce_cmdmods(
6043 NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
6044
6045 buf = alloc(len + 1);
Dominique Pelle5a9e5842021-07-24 19:32:12 +02006046 if (likely(buf != NULL))
Bram Moolenaar4c137212021-04-19 16:48:48 +02006047 {
6048 (void)produce_cmdmods(
6049 buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
6050 smsg("%s%4d CMDMOD %s", pfx, current, buf);
6051 vim_free(buf);
6052 }
6053 break;
6054 }
6055 case ISN_CMDMOD_REV: smsg("%s%4d CMDMOD_REV", pfx, current); break;
6056
6057 case ISN_PROF_START:
Bram Moolenaare99d4222021-06-13 14:01:26 +02006058 smsg("%s%4d PROFILE START line %d", pfx, current,
6059 iptr->isn_lnum);
Bram Moolenaar4c137212021-04-19 16:48:48 +02006060 break;
6061
6062 case ISN_PROF_END:
6063 smsg("%s%4d PROFILE END", pfx, current);
6064 break;
6065
Bram Moolenaare99d4222021-06-13 14:01:26 +02006066 case ISN_DEBUG:
Bram Moolenaar8cec9272021-06-23 20:20:53 +02006067 smsg("%s%4d DEBUG line %d-%d varcount %lld", pfx, current,
6068 iptr->isn_arg.debug.dbg_break_lnum + 1,
6069 iptr->isn_lnum,
6070 iptr->isn_arg.debug.dbg_var_names_len);
Bram Moolenaare99d4222021-06-13 14:01:26 +02006071 break;
6072
Bram Moolenaar4c137212021-04-19 16:48:48 +02006073 case ISN_UNPACK: smsg("%s%4d UNPACK %d%s", pfx, current,
6074 iptr->isn_arg.unpack.unp_count,
6075 iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");
6076 break;
6077 case ISN_SHUFFLE: smsg("%s%4d SHUFFLE %d up %d", pfx, current,
6078 iptr->isn_arg.shuffle.shfl_item,
6079 iptr->isn_arg.shuffle.shfl_up);
6080 break;
6081 case ISN_DROP: smsg("%s%4d DROP", pfx, current); break;
6082
6083 case ISN_FINISH: // End of list of instructions for ISN_SUBSTITUTE.
6084 return;
6085 }
6086
6087 out_flush(); // output one line at a time
6088 ui_breakcheck();
6089 if (got_int)
6090 break;
6091 }
6092}
6093
6094/*
Bram Moolenaar4ee9d8e2021-06-13 18:38:48 +02006095 * Handle command line completion for the :disassemble command.
6096 */
6097 void
6098set_context_in_disassemble_cmd(expand_T *xp, char_u *arg)
6099{
6100 char_u *p;
6101
6102 // Default: expand user functions, "debug" and "profile"
6103 xp->xp_context = EXPAND_DISASSEMBLE;
6104 xp->xp_pattern = arg;
6105
6106 // first argument already typed: only user function names
6107 if (*arg != NUL && *(p = skiptowhite(arg)) != NUL)
6108 {
6109 xp->xp_context = EXPAND_USER_FUNC;
6110 xp->xp_pattern = skipwhite(p);
6111 }
6112}
6113
6114/*
6115 * Function given to ExpandGeneric() to obtain the list of :disassemble
6116 * arguments.
6117 */
6118 char_u *
6119get_disassemble_argument(expand_T *xp, int idx)
6120{
6121 if (idx == 0)
6122 return (char_u *)"debug";
6123 if (idx == 1)
6124 return (char_u *)"profile";
6125 return get_user_func_name(xp, idx - 2);
6126}
6127
6128/*
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01006129 * ":disassemble".
Bram Moolenaar777770f2020-02-06 21:27:08 +01006130 * We don't really need this at runtime, but we do have tests that require it,
6131 * so always include this.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006132 */
6133 void
6134ex_disassemble(exarg_T *eap)
6135{
Bram Moolenaar21456cd2020-02-13 21:29:32 +01006136 char_u *arg = eap->arg;
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01006137 char_u *fname;
6138 ufunc_T *ufunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006139 dfunc_T *dfunc;
6140 isn_T *instr;
Bram Moolenaarb2049902021-01-24 12:53:53 +01006141 int instr_count;
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02006142 int is_global = FALSE;
Bram Moolenaare99d4222021-06-13 14:01:26 +02006143 compiletype_T compile_type = CT_NONE;
6144
Bram Moolenaarc7d5fc82021-12-05 17:20:24 +00006145 if (STRNCMP(arg, "profile", 7) == 0 && VIM_ISWHITE(arg[7]))
Bram Moolenaare99d4222021-06-13 14:01:26 +02006146 {
6147 compile_type = CT_PROFILE;
6148 arg = skipwhite(arg + 7);
6149 }
Bram Moolenaarc7d5fc82021-12-05 17:20:24 +00006150 else if (STRNCMP(arg, "debug", 5) == 0 && VIM_ISWHITE(arg[5]))
Bram Moolenaare99d4222021-06-13 14:01:26 +02006151 {
6152 compile_type = CT_DEBUG;
6153 arg = skipwhite(arg + 5);
6154 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006155
Bram Moolenaarbfd65582020-07-13 18:18:00 +02006156 if (STRNCMP(arg, "<lambda>", 8) == 0)
6157 {
6158 arg += 8;
6159 (void)getdigits(&arg);
6160 fname = vim_strnsave(eap->arg, arg - eap->arg);
6161 }
6162 else
6163 fname = trans_function_name(&arg, &is_global, FALSE,
Bram Moolenaar32b3f822021-01-06 21:59:39 +01006164 TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL);
Bram Moolenaar21456cd2020-02-13 21:29:32 +01006165 if (fname == NULL)
6166 {
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00006167 semsg(_(e_invalid_argument_str), eap->arg);
Bram Moolenaar21456cd2020-02-13 21:29:32 +01006168 return;
6169 }
6170
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00006171 ufunc = find_func(fname, is_global);
Bram Moolenaara26b9702020-04-18 19:53:28 +02006172 if (ufunc == NULL)
6173 {
6174 char_u *p = untrans_function_name(fname);
6175
6176 if (p != NULL)
6177 // Try again without making it script-local.
Bram Moolenaard9d2fd02022-01-13 21:15:21 +00006178 ufunc = find_func(p, FALSE);
Bram Moolenaara26b9702020-04-18 19:53:28 +02006179 }
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01006180 vim_free(fname);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006181 if (ufunc == NULL)
6182 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006183 semsg(_(e_cannot_find_function_str), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006184 return;
6185 }
Bram Moolenaare99d4222021-06-13 14:01:26 +02006186 if (func_needs_compiling(ufunc, compile_type)
6187 && compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02006188 return;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02006189 if (ufunc->uf_def_status != UF_COMPILED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006190 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006191 semsg(_(e_function_is_not_compiled_str), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006192 return;
6193 }
Bram Moolenaar6db660b2021-08-01 14:08:54 +02006194 msg((char *)printable_func_name(ufunc));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006195
6196 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
Bram Moolenaare99d4222021-06-13 14:01:26 +02006197 switch (compile_type)
6198 {
6199 case CT_PROFILE:
Bram Moolenaarf002a412021-01-24 13:34:18 +01006200#ifdef FEAT_PROFILE
Bram Moolenaare99d4222021-06-13 14:01:26 +02006201 instr = dfunc->df_instr_prof;
6202 instr_count = dfunc->df_instr_prof_count;
6203 break;
Bram Moolenaarf002a412021-01-24 13:34:18 +01006204#endif
Bram Moolenaare99d4222021-06-13 14:01:26 +02006205 // FALLTHROUGH
6206 case CT_NONE:
6207 instr = dfunc->df_instr;
6208 instr_count = dfunc->df_instr_count;
6209 break;
6210 case CT_DEBUG:
6211 instr = dfunc->df_instr_debug;
6212 instr_count = dfunc->df_instr_debug_count;
6213 break;
6214 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006215
Bram Moolenaar4c137212021-04-19 16:48:48 +02006216 list_instructions("", instr, instr_count, ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006217}
6218
6219/*
Bram Moolenaar13106602020-10-04 16:06:05 +02006220 * Return TRUE when "tv" is not falsy: non-zero, non-empty string, non-empty
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006221 * list, etc. Mostly like what JavaScript does, except that empty list and
6222 * empty dictionary are FALSE.
6223 */
6224 int
6225tv2bool(typval_T *tv)
6226{
6227 switch (tv->v_type)
6228 {
6229 case VAR_NUMBER:
6230 return tv->vval.v_number != 0;
6231 case VAR_FLOAT:
6232#ifdef FEAT_FLOAT
6233 return tv->vval.v_float != 0.0;
6234#else
6235 break;
6236#endif
6237 case VAR_PARTIAL:
6238 return tv->vval.v_partial != NULL;
6239 case VAR_FUNC:
6240 case VAR_STRING:
6241 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
6242 case VAR_LIST:
6243 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
6244 case VAR_DICT:
6245 return tv->vval.v_dict != NULL
6246 && tv->vval.v_dict->dv_hashtab.ht_used > 0;
6247 case VAR_BOOL:
6248 case VAR_SPECIAL:
6249 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
6250 case VAR_JOB:
6251#ifdef FEAT_JOB_CHANNEL
6252 return tv->vval.v_job != NULL;
6253#else
6254 break;
6255#endif
6256 case VAR_CHANNEL:
6257#ifdef FEAT_JOB_CHANNEL
6258 return tv->vval.v_channel != NULL;
6259#else
6260 break;
6261#endif
6262 case VAR_BLOB:
6263 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
6264 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02006265 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006266 case VAR_VOID:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02006267 case VAR_INSTR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006268 break;
6269 }
6270 return FALSE;
6271}
6272
Bram Moolenaarea2d4072020-11-12 12:08:51 +01006273 void
6274emsg_using_string_as(typval_T *tv, int as_number)
6275{
6276 semsg(_(as_number ? e_using_string_as_number_str
6277 : e_using_string_as_bool_str),
6278 tv->vval.v_string == NULL
6279 ? (char_u *)"" : tv->vval.v_string);
6280}
6281
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006282/*
6283 * If "tv" is a string give an error and return FAIL.
6284 */
6285 int
6286check_not_string(typval_T *tv)
6287{
6288 if (tv->v_type == VAR_STRING)
6289 {
Bram Moolenaarea2d4072020-11-12 12:08:51 +01006290 emsg_using_string_as(tv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006291 clear_tv(tv);
6292 return FAIL;
6293 }
6294 return OK;
6295}
6296
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006297
6298#endif // FEAT_EVAL