blob: cd6eff56cfaa1b6294a12afe5562174c87309d3b [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9execute.c: execute Vim9 script instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#include "vim9.h"
24
25// Structure put on ec_trystack when ISN_TRY is encountered.
26typedef struct {
Bram Moolenaarbf67ea12020-05-02 17:52:42 +020027 int tcd_frame_idx; // ec_frame_idx when ISN_TRY was encountered
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010028 int tcd_catch_idx; // instruction of the first catch
29 int tcd_finally_idx; // instruction of the finally block
30 int tcd_caught; // catch block entered
31 int tcd_return; // when TRUE return from end of :finally
32} trycmd_T;
33
34
35// A stack is used to store:
36// - arguments passed to a :def function
37// - info about the calling function, to use when returning
38// - local variables
39// - temporary values
40//
41// In detail (FP == Frame Pointer):
42// arg1 first argument from caller (if present)
43// arg2 second argument from caller (if present)
44// extra_arg1 any missing optional argument default value
45// FP -> cur_func calling function
46// current previous instruction pointer
47// frame_ptr previous Frame Pointer
48// var1 space for local variable
49// var2 space for local variable
50// .... fixed space for max. number of local variables
51// temp temporary values
52// .... flexible space for temporary values (can grow big)
53
54/*
55 * Execution context.
56 */
57typedef struct {
58 garray_T ec_stack; // stack of typval_T values
Bram Moolenaarbf67ea12020-05-02 17:52:42 +020059 int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010060
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +020061 garray_T *ec_outer_stack; // stack used for closures
62 int ec_outer_frame; // stack frame in ec_outer_stack
63
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010064 garray_T ec_trystack; // stack of trycmd_T values
65 int ec_in_catch; // when TRUE in catch or finally block
66
67 int ec_dfunc_idx; // current function index
68 isn_T *ec_instr; // array with instructions
69 int ec_iidx; // index in ec_instr: instruction to execute
70} ectx_T;
71
72// Get pointer to item relative to the bottom of the stack, -1 is the last one.
Bram Moolenaar11107ba2020-08-15 21:10:16 +020073#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 +010074
Bram Moolenaar418f1df2020-08-12 21:34:49 +020075 void
76to_string_error(vartype_T vartype)
77{
Bram Moolenaar451c2e32020-08-15 16:33:28 +020078 semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype));
Bram Moolenaar418f1df2020-08-12 21:34:49 +020079}
80
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010081/*
Bram Moolenaar170fcfc2020-02-06 17:51:35 +010082 * Return the number of arguments, including optional arguments and any vararg.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010083 */
84 static int
85ufunc_argcount(ufunc_T *ufunc)
86{
87 return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0);
88}
89
90/*
Bram Moolenaar170fcfc2020-02-06 17:51:35 +010091 * Set the instruction index, depending on omitted arguments, where the default
92 * values are to be computed. If all optional arguments are present, start
93 * with the function body.
94 * The expression evaluation is at the start of the instructions:
95 * 0 -> EVAL default1
96 * STORE arg[-2]
97 * 1 -> EVAL default2
98 * STORE arg[-1]
99 * 2 -> function body
100 */
101 static void
102init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx)
103{
104 if (ufunc->uf_def_args.ga_len == 0)
105 ectx->ec_iidx = 0;
106 else
107 {
108 int defcount = ufunc->uf_args.ga_len - argcount;
109
110 // If there is a varargs argument defcount can be negative, no defaults
111 // to evaluate then.
112 if (defcount < 0)
113 defcount = 0;
114 ectx->ec_iidx = ufunc->uf_def_arg_idx[
115 ufunc->uf_def_args.ga_len - defcount];
116 }
117}
118
119/*
Bram Moolenaarfe270812020-04-11 22:31:27 +0200120 * Create a new list from "count" items at the bottom of the stack.
121 * When "count" is zero an empty list is added to the stack.
122 */
123 static int
124exe_newlist(int count, ectx_T *ectx)
125{
126 list_T *list = list_alloc_with_items(count);
127 int idx;
128 typval_T *tv;
129
130 if (list == NULL)
131 return FAIL;
132 for (idx = 0; idx < count; ++idx)
133 list_set_item(list, idx, STACK_TV_BOT(idx - count));
134
135 if (count > 0)
136 ectx->ec_stack.ga_len -= count - 1;
Bram Moolenaar270d0382020-05-15 21:42:53 +0200137 else if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
Bram Moolenaarfe270812020-04-11 22:31:27 +0200138 return FAIL;
139 else
140 ++ectx->ec_stack.ga_len;
141 tv = STACK_TV_BOT(-1);
142 tv->v_type = VAR_LIST;
143 tv->vval.v_list = list;
144 ++list->lv_refcount;
145 return OK;
146}
147
148/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100149 * Call compiled function "cdf_idx" from compiled code.
150 *
151 * Stack has:
152 * - current arguments (already there)
153 * - omitted optional argument (default values) added here
154 * - stack frame:
155 * - pointer to calling function
156 * - Index of next instruction in calling function
157 * - previous frame pointer
158 * - reserved space for local variables
159 */
160 static int
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200161call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100162{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200163 int argcount = argcount_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100164 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
165 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200166 int arg_to_add;
167 int vararg_count = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100168 int idx;
Bram Moolenaarc620c052020-07-08 15:16:19 +0200169 estack_T *entry;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100170
171 if (dfunc->df_deleted)
172 {
173 emsg_funcname(e_func_deleted, ufunc->uf_name);
174 return FAIL;
175 }
176
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200177 if (ufunc->uf_va_name != NULL)
178 {
Bram Moolenaarfe270812020-04-11 22:31:27 +0200179 // Need to make a list out of the vararg arguments.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200180 // Stack at time of call with 2 varargs:
181 // normal_arg
182 // optional_arg
183 // vararg_1
184 // vararg_2
Bram Moolenaarfe270812020-04-11 22:31:27 +0200185 // After creating the list:
186 // normal_arg
187 // optional_arg
188 // vararg-list
189 // With missing optional arguments we get:
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200190 // normal_arg
Bram Moolenaarfe270812020-04-11 22:31:27 +0200191 // After creating the list
192 // normal_arg
193 // (space for optional_arg)
194 // vararg-list
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200195 vararg_count = argcount - ufunc->uf_args.ga_len;
196 if (vararg_count < 0)
197 vararg_count = 0;
198 else
199 argcount -= vararg_count;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200200 if (exe_newlist(vararg_count, ectx) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200201 return FAIL;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200202
203 vararg_count = 1;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200204 }
205
Bram Moolenaarfe270812020-04-11 22:31:27 +0200206 arg_to_add = ufunc->uf_args.ga_len - argcount;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200207 if (arg_to_add < 0)
208 {
Bram Moolenaar79e8db92020-08-14 22:16:33 +0200209 if (arg_to_add == -1)
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200210 emsg(_(e_one_argument_too_many));
Bram Moolenaar79e8db92020-08-14 22:16:33 +0200211 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200212 semsg(_(e_nr_arguments_too_many), -arg_to_add);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200213 return FAIL;
214 }
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200215 if (ga_grow(&ectx->ec_stack, arg_to_add + 3
216 + dfunc->df_varcount + dfunc->df_closure_count) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100217 return FAIL;
218
Bram Moolenaarfe270812020-04-11 22:31:27 +0200219 // Move the vararg-list to below the missing optional arguments.
220 if (vararg_count > 0 && arg_to_add > 0)
221 *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100222
223 // Reserve space for omitted optional arguments, filled in soon.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200224 for (idx = 0; idx < arg_to_add; ++idx)
Bram Moolenaarfe270812020-04-11 22:31:27 +0200225 STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200226 ectx->ec_stack.ga_len += arg_to_add;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100227
228 // Store current execution state in stack frame for ISN_RETURN.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100229 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx;
230 STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200231 STACK_TV_BOT(2)->vval.v_number = ectx->ec_frame_idx;
232 ectx->ec_frame_idx = ectx->ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100233
234 // Initialize local variables
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200235 for (idx = 0; idx < dfunc->df_varcount + dfunc->df_closure_count; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100236 STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200237 ectx->ec_stack.ga_len += STACK_FRAME_SIZE
238 + dfunc->df_varcount + dfunc->df_closure_count;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100239
240 // Set execution state to the start of the called function.
241 ectx->ec_dfunc_idx = cdf_idx;
242 ectx->ec_instr = dfunc->df_instr;
Bram Moolenaarc620c052020-07-08 15:16:19 +0200243 entry = estack_push_ufunc(dfunc->df_ufunc, 1);
244 if (entry != NULL)
245 {
246 // Set the script context to the script where the function was defined.
247 // TODO: save more than the SID?
248 entry->es_save_sid = current_sctx.sc_sid;
249 current_sctx.sc_sid = ufunc->uf_script_ctx.sc_sid;
250 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100251
252 // Decide where to start execution, handles optional arguments.
253 init_instr_idx(ufunc, argcount, ectx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100254
255 return OK;
256}
257
258// Get pointer to item in the stack.
259#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
260
261/*
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200262 * Used when returning from a function: Check if any closure is still
263 * referenced. If so then move the arguments and variables to a separate piece
264 * of stack to be used when the closure is called.
265 * When "free_arguments" is TRUE the arguments are to be freed.
266 * Returns FAIL when out of memory.
267 */
268 static int
269handle_closure_in_use(ectx_T *ectx, int free_arguments)
270{
271 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
272 + ectx->ec_dfunc_idx;
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200273 int argcount;
274 int top;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200275 int idx;
276 typval_T *tv;
277 int closure_in_use = FALSE;
278
Bram Moolenaarfdeab652020-09-19 15:16:50 +0200279 if (dfunc->df_ufunc == NULL)
280 // function was freed
281 return OK;
282 argcount = ufunc_argcount(dfunc->df_ufunc);
283 top = ectx->ec_frame_idx - argcount;
284
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200285 // Check if any created closure is still in use.
286 for (idx = 0; idx < dfunc->df_closure_count; ++idx)
287 {
288 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE
289 + dfunc->df_varcount + idx);
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200290 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL
291 && tv->vval.v_partial->pt_refcount > 1)
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200292 {
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200293 int refcount = tv->vval.v_partial->pt_refcount;
294 int i;
295
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200296 // A Reference in a local variables doesn't count, it gets
Bram Moolenaar221fcc72020-05-05 19:46:20 +0200297 // unreferenced on return.
298 for (i = 0; i < dfunc->df_varcount; ++i)
299 {
300 typval_T *stv = STACK_TV(ectx->ec_frame_idx
301 + STACK_FRAME_SIZE + i);
302 if (stv->v_type == VAR_PARTIAL
303 && tv->vval.v_partial == stv->vval.v_partial)
304 --refcount;
305 }
306 if (refcount > 1)
307 {
308 closure_in_use = TRUE;
309 break;
310 }
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200311 }
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200312 }
313
314 if (closure_in_use)
315 {
316 funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T);
317 typval_T *stack;
318
319 // A closure is using the arguments and/or local variables.
320 // Move them to the called function.
321 if (funcstack == NULL)
322 return FAIL;
323 funcstack->fs_ga.ga_len = argcount + STACK_FRAME_SIZE
324 + dfunc->df_varcount;
325 stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len);
326 funcstack->fs_ga.ga_data = stack;
327 if (stack == NULL)
328 {
329 vim_free(funcstack);
330 return FAIL;
331 }
332
333 // Move or copy the arguments.
334 for (idx = 0; idx < argcount; ++idx)
335 {
336 tv = STACK_TV(top + idx);
337 if (free_arguments)
338 {
339 *(stack + idx) = *tv;
340 tv->v_type = VAR_UNKNOWN;
341 }
342 else
343 copy_tv(tv, stack + idx);
344 }
345 // Move the local variables.
346 for (idx = 0; idx < dfunc->df_varcount; ++idx)
347 {
348 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx);
Bram Moolenaarf821dda2020-05-06 22:18:17 +0200349
350 // Do not copy a partial created for a local function.
351 // TODO: this won't work if the closure actually uses it. But when
352 // keeping it it gets complicated: it will create a reference cycle
353 // inside the partial, thus needs special handling for garbage
354 // collection.
355 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL)
356 {
357 int i;
358 typval_T *ctv;
359
360 for (i = 0; i < dfunc->df_closure_count; ++i)
361 {
362 ctv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE
363 + dfunc->df_varcount + i);
364 if (tv->vval.v_partial == ctv->vval.v_partial)
365 break;
366 }
367 if (i < dfunc->df_closure_count)
368 {
369 (stack + argcount + STACK_FRAME_SIZE + idx)->v_type =
370 VAR_UNKNOWN;
371 continue;
372 }
373 }
374
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200375 *(stack + argcount + STACK_FRAME_SIZE + idx) = *tv;
376 tv->v_type = VAR_UNKNOWN;
377 }
378
379 for (idx = 0; idx < dfunc->df_closure_count; ++idx)
380 {
381 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE
382 + dfunc->df_varcount + idx);
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200383 if (tv->v_type == VAR_PARTIAL)
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200384 {
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200385 partial_T *partial = tv->vval.v_partial;
386
387 if (partial->pt_refcount > 1)
388 {
389 ++funcstack->fs_refcount;
390 partial->pt_funcstack = funcstack;
391 partial->pt_ectx_stack = &funcstack->fs_ga;
392 partial->pt_ectx_frame = ectx->ec_frame_idx - top;
393 }
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200394 }
395 }
396 }
397
398 return OK;
399}
400
401/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100402 * Return from the current function.
403 */
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200404 static int
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100405func_return(ectx_T *ectx)
406{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100407 int idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200408 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
409 + ectx->ec_dfunc_idx;
410 int argcount = ufunc_argcount(dfunc->df_ufunc);
411 int top = ectx->ec_frame_idx - argcount;
Bram Moolenaarc620c052020-07-08 15:16:19 +0200412 estack_T *entry;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100413
414 // execution context goes one level up
Bram Moolenaarc620c052020-07-08 15:16:19 +0200415 entry = estack_pop();
416 if (entry != NULL)
417 current_sctx.sc_sid = entry->es_save_sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100418
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200419 if (handle_closure_in_use(ectx, TRUE) == FAIL)
420 return FAIL;
421
422 // Clear the arguments.
423 for (idx = top; idx < ectx->ec_frame_idx; ++idx)
424 clear_tv(STACK_TV(idx));
425
426 // Clear local variables and temp values, but not the return value.
427 for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100428 idx < ectx->ec_stack.ga_len - 1; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100429 clear_tv(STACK_TV(idx));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100430
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100431 // Restore the previous frame.
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200432 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame_idx)->vval.v_number;
433 ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx + 1)->vval.v_number;
434 ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx + 2)->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100435 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
436 ectx->ec_instr = dfunc->df_instr;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100437
438 // Reset the stack to the position before the call, move the return value
439 // to the top of the stack.
440 idx = ectx->ec_stack.ga_len - 1;
441 ectx->ec_stack.ga_len = top + 1;
442 *STACK_TV_BOT(-1) = *STACK_TV(idx);
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200443
444 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100445}
446
447#undef STACK_TV
448
449/*
450 * Prepare arguments and rettv for calling a builtin or user function.
451 */
452 static int
453call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
454{
455 int idx;
456 typval_T *tv;
457
458 // Move arguments from bottom of the stack to argvars[] and add terminator.
459 for (idx = 0; idx < argcount; ++idx)
460 argvars[idx] = *STACK_TV_BOT(idx - argcount);
461 argvars[argcount].v_type = VAR_UNKNOWN;
462
463 // Result replaces the arguments on the stack.
464 if (argcount > 0)
465 ectx->ec_stack.ga_len -= argcount - 1;
Bram Moolenaar270d0382020-05-15 21:42:53 +0200466 else if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100467 return FAIL;
468 else
469 ++ectx->ec_stack.ga_len;
470
471 // Default return value is zero.
472 tv = STACK_TV_BOT(-1);
473 tv->v_type = VAR_NUMBER;
474 tv->vval.v_number = 0;
475
476 return OK;
477}
478
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200479// Ugly global to avoid passing the execution context around through many
480// layers.
481static ectx_T *current_ectx = NULL;
482
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100483/*
484 * Call a builtin function by index.
485 */
486 static int
487call_bfunc(int func_idx, int argcount, ectx_T *ectx)
488{
489 typval_T argvars[MAX_FUNC_ARGS];
490 int idx;
Bram Moolenaar8a1c1012020-05-07 14:07:25 +0200491 int did_emsg_before = did_emsg;
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200492 ectx_T *prev_ectx = current_ectx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100493
494 if (call_prepare(argcount, argvars, ectx) == FAIL)
495 return FAIL;
496
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200497 // Call the builtin function. Set "current_ectx" so that when it
498 // recursively invokes call_def_function() a closure context can be set.
499 current_ectx = ectx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100500 call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1));
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200501 current_ectx = prev_ectx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100502
503 // Clear the arguments.
504 for (idx = 0; idx < argcount; ++idx)
505 clear_tv(&argvars[idx]);
Bram Moolenaar015f4262020-05-05 21:25:22 +0200506
Bram Moolenaar8a1c1012020-05-07 14:07:25 +0200507 if (did_emsg != did_emsg_before)
Bram Moolenaar015f4262020-05-05 21:25:22 +0200508 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100509 return OK;
510}
511
512/*
513 * Execute a user defined function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100514 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100515 */
516 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100517call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100518{
519 typval_T argvars[MAX_FUNC_ARGS];
520 funcexe_T funcexe;
521 int error;
522 int idx;
Bram Moolenaared677f52020-08-12 16:38:10 +0200523 int called_emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100524
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +0200525 if (ufunc->uf_def_status == UF_TO_BE_COMPILED
Bram Moolenaar822ba242020-05-24 23:00:18 +0200526 && compile_def_function(ufunc, FALSE, NULL) == FAIL)
527 return FAIL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +0200528 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100529 {
530 // The function has been compiled, can call it quickly. For a function
531 // that was defined later: we can call it directly next time.
532 if (iptr != NULL)
533 {
Bram Moolenaar20431c92020-03-20 18:39:46 +0100534 delete_instr(iptr);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100535 iptr->isn_type = ISN_DCALL;
536 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
537 iptr->isn_arg.dfunc.cdf_argcount = argcount;
538 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100539 return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100540 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100541
542 if (call_prepare(argcount, argvars, ectx) == FAIL)
543 return FAIL;
Bram Moolenaara80faa82020-04-12 19:37:17 +0200544 CLEAR_FIELD(funcexe);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100545 funcexe.evaluate = TRUE;
546
547 // Call the user function. Result goes in last position on the stack.
548 // TODO: add selfdict if there is one
549 error = call_user_func_check(ufunc, argcount, argvars,
550 STACK_TV_BOT(-1), &funcexe, NULL);
551
552 // Clear the arguments.
553 for (idx = 0; idx < argcount; ++idx)
554 clear_tv(&argvars[idx]);
555
556 if (error != FCERR_NONE)
557 {
558 user_func_error(error, ufunc->uf_name);
559 return FAIL;
560 }
Bram Moolenaared677f52020-08-12 16:38:10 +0200561 if (called_emsg > called_emsg_before)
562 // Error other than from calling the function itself.
563 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100564 return OK;
565}
566
567/*
Bram Moolenaara1773442020-08-12 15:21:22 +0200568 * Return TRUE if an error was given or CTRL-C was pressed.
569 */
570 static int
571vim9_aborting(int prev_called_emsg)
572{
573 return called_emsg > prev_called_emsg || got_int || did_throw;
574}
575
576/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100577 * Execute a function by "name".
578 * This can be a builtin function or a user function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100579 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100580 * Returns FAIL if not found without an error message.
581 */
582 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100583call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100584{
585 ufunc_T *ufunc;
586
587 if (builtin_function(name, -1))
588 {
589 int func_idx = find_internal_func(name);
590
591 if (func_idx < 0)
592 return FAIL;
Bram Moolenaar389df252020-07-09 21:20:47 +0200593 if (check_internal_func(func_idx, argcount) < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100594 return FAIL;
595 return call_bfunc(func_idx, argcount, ectx);
596 }
597
Bram Moolenaar4c17ad92020-04-27 22:47:51 +0200598 ufunc = find_func(name, FALSE, NULL);
Bram Moolenaara1773442020-08-12 15:21:22 +0200599
600 if (ufunc == NULL)
601 {
602 int called_emsg_before = called_emsg;
603
604 if (script_autoload(name, TRUE))
605 // loaded a package, search for the function again
606 ufunc = find_func(name, FALSE, NULL);
607 if (vim9_aborting(called_emsg_before))
608 return FAIL; // bail out if loading the script caused an error
609 }
610
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100611 if (ufunc != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100612 return call_ufunc(ufunc, argcount, ectx, iptr);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100613
614 return FAIL;
615}
616
617 static int
Bram Moolenaara90afb92020-07-15 22:38:56 +0200618call_partial(typval_T *tv, int argcount_arg, ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100619{
Bram Moolenaara90afb92020-07-15 22:38:56 +0200620 int argcount = argcount_arg;
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200621 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100622 int called_emsg_before = called_emsg;
Bram Moolenaar95006e32020-08-29 17:47:08 +0200623 int res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100624
625 if (tv->v_type == VAR_PARTIAL)
626 {
Bram Moolenaara90afb92020-07-15 22:38:56 +0200627 partial_T *pt = tv->vval.v_partial;
628 int i;
629
630 if (pt->pt_argc > 0)
631 {
632 // Make space for arguments from the partial, shift the "argcount"
633 // arguments up.
634 if (ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL)
635 return FAIL;
636 for (i = 1; i <= argcount; ++i)
637 *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i);
638 ectx->ec_stack.ga_len += pt->pt_argc;
639 argcount += pt->pt_argc;
640
641 // copy the arguments from the partial onto the stack
642 for (i = 0; i < pt->pt_argc; ++i)
643 copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i));
644 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100645
646 if (pt->pt_func != NULL)
Bram Moolenaarf7779c62020-05-03 15:38:16 +0200647 {
648 int ret = call_ufunc(pt->pt_func, argcount, ectx, NULL);
649
650 // closure may need the function context where it was defined
651 ectx->ec_outer_stack = pt->pt_ectx_stack;
652 ectx->ec_outer_frame = pt->pt_ectx_frame;
653
654 return ret;
655 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100656 name = pt->pt_name;
657 }
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200658 else if (tv->v_type == VAR_FUNC)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100659 name = tv->vval.v_string;
Bram Moolenaar95006e32020-08-29 17:47:08 +0200660 if (name != NULL)
661 {
662 char_u fname_buf[FLEN_FIXED + 1];
663 char_u *tofree = NULL;
664 int error = FCERR_NONE;
665 char_u *fname;
666
667 // May need to translate <SNR>123_ to K_SNR.
668 fname = fname_trans_sid(name, fname_buf, &tofree, &error);
669 if (error != FCERR_NONE)
670 res = FAIL;
671 else
672 res = call_by_name(fname, argcount, ectx, NULL);
673 vim_free(tofree);
674 }
675
676 if (name == NULL || res == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100677 {
678 if (called_emsg == called_emsg_before)
Bram Moolenaar015f4262020-05-05 21:25:22 +0200679 semsg(_(e_unknownfunc),
680 name == NULL ? (char_u *)"[unknown]" : name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100681 return FAIL;
682 }
683 return OK;
684}
685
686/*
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +0200687 * Check if "lock" is VAR_LOCKED or VAR_FIXED. If so give an error and return
688 * TRUE.
689 */
690 static int
691error_if_locked(int lock, char *error)
692{
693 if (lock & (VAR_LOCKED | VAR_FIXED))
694 {
695 emsg(_(error));
696 return TRUE;
697 }
698 return FALSE;
699}
700
701/*
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100702 * Store "tv" in variable "name".
703 * This is for s: and g: variables.
704 */
705 static void
706store_var(char_u *name, typval_T *tv)
707{
708 funccal_entry_T entry;
709
710 save_funccal(&entry);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200711 set_var_const(name, NULL, tv, FALSE, LET_NO_COMMAND);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100712 restore_funccal();
713}
714
Bram Moolenaard3aac292020-04-19 14:32:17 +0200715
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100716/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100717 * Execute a function by "name".
718 * This can be a builtin function, user function or a funcref.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100719 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100720 */
721 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100722call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100723{
Bram Moolenaared677f52020-08-12 16:38:10 +0200724 int called_emsg_before = called_emsg;
725 int res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100726
Bram Moolenaared677f52020-08-12 16:38:10 +0200727 res = call_by_name(name, argcount, ectx, iptr);
728 if (res == FAIL && called_emsg == called_emsg_before)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100729 {
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +0200730 dictitem_T *v;
731
732 v = find_var(name, NULL, FALSE);
733 if (v == NULL)
734 {
735 semsg(_(e_unknownfunc), name);
736 return FAIL;
737 }
738 if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC)
739 {
740 semsg(_(e_unknownfunc), name);
741 return FAIL;
742 }
743 return call_partial(&v->di_tv, argcount, ectx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100744 }
Bram Moolenaared677f52020-08-12 16:38:10 +0200745 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100746}
747
748/*
749 * Call a "def" function from old Vim script.
750 * Return OK or FAIL.
751 */
752 int
753call_def_function(
754 ufunc_T *ufunc,
Bram Moolenaar23e03252020-04-12 22:22:31 +0200755 int argc_arg, // nr of arguments
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100756 typval_T *argv, // arguments
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +0200757 partial_T *partial, // optional partial for context
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100758 typval_T *rettv) // return value
759{
760 ectx_T ectx; // execution context
Bram Moolenaar23e03252020-04-12 22:22:31 +0200761 int argc = argc_arg;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200762 int initial_frame_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100763 typval_T *tv;
764 int idx;
765 int ret = FAIL;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100766 int defcount = ufunc->uf_args.ga_len - argc;
Bram Moolenaaree8580e2020-08-28 17:19:07 +0200767 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar270d0382020-05-15 21:42:53 +0200768 int breakcheck_count = 0;
Bram Moolenaar25e0f582020-05-25 22:36:50 +0200769 int called_emsg_before = called_emsg;
Bram Moolenaar77e5dcc2020-09-17 21:29:03 +0200770 int save_suppress_errthrow = suppress_errthrow;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100771
772// Get pointer to item in the stack.
773#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
774
775// Get pointer to item at the bottom of the stack, -1 is the bottom.
776#undef STACK_TV_BOT
777#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
778
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200779// Get pointer to a local variable on the stack. Negative for arguments.
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200780#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 +0100781
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200782// Like STACK_TV_VAR but use the outer scope
783#define STACK_OUT_TV_VAR(idx) (((typval_T *)ectx.ec_outer_stack->ga_data) + ectx.ec_outer_frame + STACK_FRAME_SIZE + idx)
784
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +0200785 if (ufunc->uf_def_status == UF_NOT_COMPILED
786 || (ufunc->uf_def_status == UF_TO_BE_COMPILED
Bram Moolenaar822ba242020-05-24 23:00:18 +0200787 && compile_def_function(ufunc, FALSE, NULL) == FAIL))
Bram Moolenaar25e0f582020-05-25 22:36:50 +0200788 {
789 if (called_emsg == called_emsg_before)
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200790 semsg(_(e_function_is_not_compiled_str),
Bram Moolenaar682d0a12020-07-19 20:48:59 +0200791 printable_func_name(ufunc));
Bram Moolenaar822ba242020-05-24 23:00:18 +0200792 return FAIL;
Bram Moolenaar25e0f582020-05-25 22:36:50 +0200793 }
Bram Moolenaar822ba242020-05-24 23:00:18 +0200794
Bram Moolenaar09689a02020-05-09 22:50:08 +0200795 {
Bram Moolenaar822ba242020-05-24 23:00:18 +0200796 // Check the function was really compiled.
Bram Moolenaar09689a02020-05-09 22:50:08 +0200797 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
798 + ufunc->uf_dfunc_idx;
799 if (dfunc->df_instr == NULL)
Bram Moolenaar38ddf332020-07-31 22:05:04 +0200800 {
801 iemsg("using call_def_function() on not compiled function");
Bram Moolenaar09689a02020-05-09 22:50:08 +0200802 return FAIL;
Bram Moolenaar38ddf332020-07-31 22:05:04 +0200803 }
Bram Moolenaar09689a02020-05-09 22:50:08 +0200804 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100805
Bram Moolenaar3b6a6eb2020-05-09 23:20:20 +0200806 CLEAR_FIELD(ectx);
807 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
808 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
809 if (ga_grow(&ectx.ec_stack, 20) == FAIL)
810 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100811 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
812
813 // Put arguments on the stack.
814 for (idx = 0; idx < argc; ++idx)
815 {
Bram Moolenaar65b95452020-07-19 14:03:09 +0200816 if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
Bram Moolenaar8b565c22020-08-30 23:24:20 +0200817 && check_typval_type(ufunc->uf_arg_types[idx], &argv[idx],
818 idx + 1) == FAIL)
Bram Moolenaar65b95452020-07-19 14:03:09 +0200819 goto failed_early;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100820 copy_tv(&argv[idx], STACK_TV_BOT(0));
821 ++ectx.ec_stack.ga_len;
822 }
Bram Moolenaar23e03252020-04-12 22:22:31 +0200823
824 // Turn varargs into a list. Empty list if no args.
825 if (ufunc->uf_va_name != NULL)
826 {
827 int vararg_count = argc - ufunc->uf_args.ga_len;
828
829 if (vararg_count < 0)
830 vararg_count = 0;
831 else
832 argc -= vararg_count;
833 if (exe_newlist(vararg_count, &ectx) == FAIL)
Bram Moolenaar1a2f4bf2020-04-12 23:09:25 +0200834 goto failed_early;
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200835
836 // Check the type of the list items.
837 tv = STACK_TV_BOT(-1);
838 if (ufunc->uf_va_type != NULL
Bram Moolenaar2f8cbc42020-09-16 17:22:59 +0200839 && ufunc->uf_va_type != &t_any
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200840 && ufunc->uf_va_type->tt_member != &t_any
841 && tv->vval.v_list != NULL)
842 {
843 type_T *expected = ufunc->uf_va_type->tt_member;
844 listitem_T *li = tv->vval.v_list->lv_first;
845
846 for (idx = 0; idx < vararg_count; ++idx)
847 {
Bram Moolenaar8b565c22020-08-30 23:24:20 +0200848 if (check_typval_type(expected, &li->li_tv,
849 argc + idx + 1) == FAIL)
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200850 goto failed_early;
851 li = li->li_next;
852 }
853 }
854
Bram Moolenaar23e03252020-04-12 22:22:31 +0200855 if (defcount > 0)
856 // Move varargs list to below missing default arguments.
Bram Moolenaar24aa48b2020-07-25 16:33:02 +0200857 *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1);
Bram Moolenaar23e03252020-04-12 22:22:31 +0200858 --ectx.ec_stack.ga_len;
859 }
860
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100861 // Make space for omitted arguments, will store default value below.
Bram Moolenaar23e03252020-04-12 22:22:31 +0200862 // Any varargs list goes after them.
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100863 if (defcount > 0)
864 for (idx = 0; idx < defcount; ++idx)
865 {
866 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
867 ++ectx.ec_stack.ga_len;
868 }
Bram Moolenaar23e03252020-04-12 22:22:31 +0200869 if (ufunc->uf_va_name != NULL)
870 ++ectx.ec_stack.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100871
872 // Frame pointer points to just after arguments.
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200873 ectx.ec_frame_idx = ectx.ec_stack.ga_len;
874 initial_frame_idx = ectx.ec_frame_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100875
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +0200876 if (partial != NULL)
877 {
Bram Moolenaar08f7a412020-07-13 20:41:08 +0200878 if (partial->pt_ectx_stack == NULL && current_ectx != NULL)
879 {
880 // TODO: is this always the right way?
881 ectx.ec_outer_stack = &current_ectx->ec_stack;
882 ectx.ec_outer_frame = current_ectx->ec_frame_idx;
883 }
884 else
885 {
886 ectx.ec_outer_stack = partial->pt_ectx_stack;
887 ectx.ec_outer_frame = partial->pt_ectx_frame;
888 }
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +0200889 }
890
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100891 // dummy frame entries
892 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
893 {
894 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
895 ++ectx.ec_stack.ga_len;
896 }
897
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200898 {
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200899 // Reserve space for local variables and closure references.
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200900 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
901 + ufunc->uf_dfunc_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200902 int count = dfunc->df_varcount + dfunc->df_closure_count;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100903
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200904 for (idx = 0; idx < count; ++idx)
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200905 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200906 ectx.ec_stack.ga_len += count;
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200907
908 ectx.ec_instr = dfunc->df_instr;
909 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100910
Bram Moolenaaree8580e2020-08-28 17:19:07 +0200911 // Following errors are in the function, not the caller.
Bram Moolenaara26b9702020-04-18 19:53:28 +0200912 // Commands behave like vim9script.
Bram Moolenaaree8580e2020-08-28 17:19:07 +0200913 estack_push_ufunc(ufunc, 1);
914 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaara26b9702020-04-18 19:53:28 +0200915 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
916
Bram Moolenaar77e5dcc2020-09-17 21:29:03 +0200917 // Do turn errors into exceptions.
918 suppress_errthrow = FALSE;
919
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100920 // Decide where to start execution, handles optional arguments.
921 init_instr_idx(ufunc, argc, &ectx);
922
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100923 for (;;)
924 {
925 isn_T *iptr;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100926
Bram Moolenaar270d0382020-05-15 21:42:53 +0200927 if (++breakcheck_count >= 100)
928 {
929 line_breakcheck();
930 breakcheck_count = 0;
931 }
Bram Moolenaar20431c92020-03-20 18:39:46 +0100932 if (got_int)
933 {
934 // Turn CTRL-C into an exception.
935 got_int = FALSE;
Bram Moolenaar97acfc72020-03-22 13:44:28 +0100936 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
Bram Moolenaar20431c92020-03-20 18:39:46 +0100937 goto failed;
938 did_throw = TRUE;
939 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100940
Bram Moolenaara26b9702020-04-18 19:53:28 +0200941 if (did_emsg && msg_list != NULL && *msg_list != NULL)
942 {
943 // Turn an error message into an exception.
944 did_emsg = FALSE;
945 if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL)
946 goto failed;
947 did_throw = TRUE;
948 *msg_list = NULL;
949 }
950
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100951 if (did_throw && !ectx.ec_in_catch)
952 {
953 garray_T *trystack = &ectx.ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100954 trycmd_T *trycmd = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100955
956 // An exception jumps to the first catch, finally, or returns from
957 // the current function.
958 if (trystack->ga_len > 0)
959 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200960 if (trycmd != NULL && trycmd->tcd_frame_idx == ectx.ec_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100961 {
962 // jump to ":catch" or ":finally"
963 ectx.ec_in_catch = TRUE;
964 ectx.ec_iidx = trycmd->tcd_catch_idx;
965 }
966 else
967 {
Bram Moolenaarcdd70f02020-08-13 21:40:18 +0200968 // Not inside try or need to return from current functions.
969 // Push a dummy return value.
970 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
971 goto failed;
972 tv = STACK_TV_BOT(0);
973 tv->v_type = VAR_NUMBER;
974 tv->vval.v_number = 0;
975 ++ectx.ec_stack.ga_len;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200976 if (ectx.ec_frame_idx == initial_frame_idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100977 {
Bram Moolenaarcdd70f02020-08-13 21:40:18 +0200978 // At the toplevel we are done.
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100979 need_rethrow = TRUE;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200980 if (handle_closure_in_use(&ectx, FALSE) == FAIL)
981 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100982 goto done;
983 }
984
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200985 if (func_return(&ectx) == FAIL)
986 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100987 }
988 continue;
989 }
990
991 iptr = &ectx.ec_instr[ectx.ec_iidx++];
992 switch (iptr->isn_type)
993 {
994 // execute Ex command line
995 case ISN_EXEC:
Bram Moolenaar6378c4f2020-04-26 13:50:41 +0200996 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100997 do_cmdline_cmd(iptr->isn_arg.string);
998 break;
999
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001000 // execute Ex command from pieces on the stack
1001 case ISN_EXECCONCAT:
1002 {
1003 int count = iptr->isn_arg.number;
Bram Moolenaar7f6f56f2020-04-30 20:21:43 +02001004 size_t len = 0;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001005 int pass;
1006 int i;
1007 char_u *cmd = NULL;
1008 char_u *str;
1009
1010 for (pass = 1; pass <= 2; ++pass)
1011 {
1012 for (i = 0; i < count; ++i)
1013 {
1014 tv = STACK_TV_BOT(i - count);
1015 str = tv->vval.v_string;
1016 if (str != NULL && *str != NUL)
1017 {
1018 if (pass == 2)
1019 STRCPY(cmd + len, str);
1020 len += STRLEN(str);
1021 }
1022 if (pass == 2)
1023 clear_tv(tv);
1024 }
1025 if (pass == 1)
1026 {
1027 cmd = alloc(len + 1);
1028 if (cmd == NULL)
1029 goto failed;
1030 len = 0;
1031 }
1032 }
1033
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02001034 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001035 do_cmdline_cmd(cmd);
1036 vim_free(cmd);
1037 }
1038 break;
1039
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001040 // execute :echo {string} ...
1041 case ISN_ECHO:
1042 {
1043 int count = iptr->isn_arg.echo.echo_count;
1044 int atstart = TRUE;
1045 int needclr = TRUE;
1046
1047 for (idx = 0; idx < count; ++idx)
1048 {
1049 tv = STACK_TV_BOT(idx - count);
1050 echo_one(tv, iptr->isn_arg.echo.echo_with_white,
1051 &atstart, &needclr);
1052 clear_tv(tv);
1053 }
Bram Moolenaare0807ea2020-02-20 22:18:06 +01001054 if (needclr)
1055 msg_clr_eos();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001056 ectx.ec_stack.ga_len -= count;
1057 }
1058 break;
1059
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001060 // :execute {string} ...
1061 // :echomsg {string} ...
1062 // :echoerr {string} ...
Bram Moolenaarad39c092020-02-26 18:23:43 +01001063 case ISN_EXECUTE:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001064 case ISN_ECHOMSG:
1065 case ISN_ECHOERR:
Bram Moolenaarad39c092020-02-26 18:23:43 +01001066 {
1067 int count = iptr->isn_arg.number;
1068 garray_T ga;
1069 char_u buf[NUMBUFLEN];
1070 char_u *p;
1071 int len;
1072 int failed = FALSE;
1073
1074 ga_init2(&ga, 1, 80);
1075 for (idx = 0; idx < count; ++idx)
1076 {
1077 tv = STACK_TV_BOT(idx - count);
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001078 if (iptr->isn_type == ISN_EXECUTE)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001079 {
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001080 if (tv->v_type == VAR_CHANNEL
1081 || tv->v_type == VAR_JOB)
1082 {
1083 SOURCING_LNUM = iptr->isn_lnum;
1084 emsg(_(e_inval_string));
1085 break;
1086 }
1087 else
1088 p = tv_get_string_buf(tv, buf);
Bram Moolenaarad39c092020-02-26 18:23:43 +01001089 }
1090 else
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001091 p = tv_stringify(tv, buf);
Bram Moolenaarad39c092020-02-26 18:23:43 +01001092
1093 len = (int)STRLEN(p);
1094 if (ga_grow(&ga, len + 2) == FAIL)
1095 failed = TRUE;
1096 else
1097 {
1098 if (ga.ga_len > 0)
1099 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
1100 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
1101 ga.ga_len += len;
1102 }
1103 clear_tv(tv);
1104 }
1105 ectx.ec_stack.ga_len -= count;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001106 if (failed)
1107 goto on_error;
Bram Moolenaarad39c092020-02-26 18:23:43 +01001108
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02001109 if (ga.ga_data != NULL)
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001110 {
1111 if (iptr->isn_type == ISN_EXECUTE)
Bram Moolenaar430deb12020-08-23 16:29:11 +02001112 {
1113 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001114 do_cmdline_cmd((char_u *)ga.ga_data);
Bram Moolenaar430deb12020-08-23 16:29:11 +02001115 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001116 else
1117 {
1118 msg_sb_eol();
1119 if (iptr->isn_type == ISN_ECHOMSG)
1120 {
1121 msg_attr(ga.ga_data, echo_attr);
1122 out_flush();
1123 }
1124 else
1125 {
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001126 SOURCING_LNUM = iptr->isn_lnum;
1127 emsg(ga.ga_data);
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001128 }
1129 }
1130 }
Bram Moolenaarad39c092020-02-26 18:23:43 +01001131 ga_clear(&ga);
1132 }
1133 break;
1134
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001135 // load local variable or argument
1136 case ISN_LOAD:
Bram Moolenaar270d0382020-05-15 21:42:53 +02001137 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001138 goto failed;
1139 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
1140 ++ectx.ec_stack.ga_len;
1141 break;
1142
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001143 // load variable or argument from outer scope
1144 case ISN_LOADOUTER:
Bram Moolenaar270d0382020-05-15 21:42:53 +02001145 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001146 goto failed;
1147 copy_tv(STACK_OUT_TV_VAR(iptr->isn_arg.number),
1148 STACK_TV_BOT(0));
1149 ++ectx.ec_stack.ga_len;
1150 break;
1151
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001152 // load v: variable
1153 case ISN_LOADV:
Bram Moolenaar270d0382020-05-15 21:42:53 +02001154 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001155 goto failed;
1156 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
1157 ++ectx.ec_stack.ga_len;
1158 break;
1159
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001160 // load s: variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001161 case ISN_LOADSCRIPT:
1162 {
1163 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001164 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001165 svar_T *sv;
1166
1167 sv = ((svar_T *)si->sn_var_vals.ga_data)
1168 + iptr->isn_arg.script.script_idx;
Bram Moolenaar270d0382020-05-15 21:42:53 +02001169 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001170 goto failed;
1171 copy_tv(sv->sv_tv, STACK_TV_BOT(0));
1172 ++ectx.ec_stack.ga_len;
1173 }
1174 break;
1175
1176 // load s: variable in old script
1177 case ISN_LOADS:
1178 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001179 hashtab_T *ht = &SCRIPT_VARS(
1180 iptr->isn_arg.loadstore.ls_sid);
1181 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001182 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001183
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001184 if (di == NULL)
1185 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001186 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001187 semsg(_(e_undefined_variable_str), name);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02001188 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001189 }
1190 else
1191 {
Bram Moolenaar270d0382020-05-15 21:42:53 +02001192 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001193 goto failed;
1194 copy_tv(&di->di_tv, STACK_TV_BOT(0));
1195 ++ectx.ec_stack.ga_len;
1196 }
1197 }
1198 break;
1199
Bram Moolenaard3aac292020-04-19 14:32:17 +02001200 // load g:/b:/w:/t: variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001201 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02001202 case ISN_LOADB:
1203 case ISN_LOADW:
1204 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001205 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02001206 dictitem_T *di = NULL;
1207 hashtab_T *ht = NULL;
1208 char namespace;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001209
Bram Moolenaard3aac292020-04-19 14:32:17 +02001210 switch (iptr->isn_type)
1211 {
1212 case ISN_LOADG:
1213 ht = get_globvar_ht();
1214 namespace = 'g';
1215 break;
1216 case ISN_LOADB:
1217 ht = &curbuf->b_vars->dv_hashtab;
1218 namespace = 'b';
1219 break;
1220 case ISN_LOADW:
1221 ht = &curwin->w_vars->dv_hashtab;
1222 namespace = 'w';
1223 break;
1224 case ISN_LOADT:
1225 ht = &curtab->tp_vars->dv_hashtab;
1226 namespace = 't';
1227 break;
1228 default: // Cannot reach here
1229 goto failed;
1230 }
1231 di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001232
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001233 if (di == NULL)
1234 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001235 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001236 semsg(_(e_undefined_variable_char_str),
Bram Moolenaard3aac292020-04-19 14:32:17 +02001237 namespace, iptr->isn_arg.string);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02001238 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001239 }
1240 else
1241 {
Bram Moolenaar270d0382020-05-15 21:42:53 +02001242 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001243 goto failed;
1244 copy_tv(&di->di_tv, STACK_TV_BOT(0));
1245 ++ectx.ec_stack.ga_len;
1246 }
1247 }
1248 break;
1249
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001250 // load g:/b:/w:/t: namespace
1251 case ISN_LOADGDICT:
1252 case ISN_LOADBDICT:
1253 case ISN_LOADWDICT:
1254 case ISN_LOADTDICT:
1255 {
1256 dict_T *d = NULL;
1257
1258 switch (iptr->isn_type)
1259 {
Bram Moolenaar682d0a12020-07-19 20:48:59 +02001260 case ISN_LOADGDICT: d = get_globvar_dict(); break;
1261 case ISN_LOADBDICT: d = curbuf->b_vars; break;
1262 case ISN_LOADWDICT: d = curwin->w_vars; break;
1263 case ISN_LOADTDICT: d = curtab->tp_vars; break;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001264 default: // Cannot reach here
1265 goto failed;
1266 }
1267 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
1268 goto failed;
1269 tv = STACK_TV_BOT(0);
1270 tv->v_type = VAR_DICT;
1271 tv->v_lock = 0;
1272 tv->vval.v_dict = d;
1273 ++ectx.ec_stack.ga_len;
1274 }
1275 break;
1276
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001277 // load &option
1278 case ISN_LOADOPT:
1279 {
1280 typval_T optval;
1281 char_u *name = iptr->isn_arg.string;
1282
Bram Moolenaara8c17702020-04-01 21:17:24 +02001283 // This is not expected to fail, name is checked during
1284 // compilation: don't set SOURCING_LNUM.
Bram Moolenaar270d0382020-05-15 21:42:53 +02001285 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001286 goto failed;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02001287 if (eval_option(&name, &optval, TRUE) == FAIL)
Bram Moolenaar58ceca52020-01-28 22:46:22 +01001288 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001289 *STACK_TV_BOT(0) = optval;
1290 ++ectx.ec_stack.ga_len;
1291 }
1292 break;
1293
1294 // load $ENV
1295 case ISN_LOADENV:
1296 {
1297 typval_T optval;
1298 char_u *name = iptr->isn_arg.string;
1299
Bram Moolenaar270d0382020-05-15 21:42:53 +02001300 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001301 goto failed;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001302 // name is always valid, checked when compiling
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02001303 (void)eval_env_var(&name, &optval, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001304 *STACK_TV_BOT(0) = optval;
1305 ++ectx.ec_stack.ga_len;
1306 }
1307 break;
1308
1309 // load @register
1310 case ISN_LOADREG:
Bram Moolenaar270d0382020-05-15 21:42:53 +02001311 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001312 goto failed;
1313 tv = STACK_TV_BOT(0);
1314 tv->v_type = VAR_STRING;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001315 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001316 tv->vval.v_string = get_reg_contents(
1317 iptr->isn_arg.number, GREG_EXPR_SRC);
1318 ++ectx.ec_stack.ga_len;
1319 break;
1320
1321 // store local variable
1322 case ISN_STORE:
1323 --ectx.ec_stack.ga_len;
1324 tv = STACK_TV_VAR(iptr->isn_arg.number);
1325 clear_tv(tv);
1326 *tv = *STACK_TV_BOT(0);
1327 break;
1328
Bram Moolenaarb68b3462020-05-06 21:06:30 +02001329 // store variable or argument in outer scope
1330 case ISN_STOREOUTER:
1331 --ectx.ec_stack.ga_len;
1332 tv = STACK_OUT_TV_VAR(iptr->isn_arg.number);
1333 clear_tv(tv);
1334 *tv = *STACK_TV_BOT(0);
1335 break;
1336
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001337 // store s: variable in old script
1338 case ISN_STORES:
1339 {
1340 hashtab_T *ht = &SCRIPT_VARS(
1341 iptr->isn_arg.loadstore.ls_sid);
1342 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001343 dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001344
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001345 --ectx.ec_stack.ga_len;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001346 if (di == NULL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001347 store_var(name, STACK_TV_BOT(0));
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001348 else
1349 {
1350 clear_tv(&di->di_tv);
1351 di->di_tv = *STACK_TV_BOT(0);
1352 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001353 }
1354 break;
1355
1356 // store script-local variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001357 case ISN_STORESCRIPT:
1358 {
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001359 scriptitem_T *si = SCRIPT_ITEM(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001360 iptr->isn_arg.script.script_sid);
1361 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1362 + iptr->isn_arg.script.script_idx;
1363
1364 --ectx.ec_stack.ga_len;
1365 clear_tv(sv->sv_tv);
1366 *sv->sv_tv = *STACK_TV_BOT(0);
1367 }
1368 break;
1369
1370 // store option
1371 case ISN_STOREOPT:
1372 {
1373 long n = 0;
1374 char_u *s = NULL;
1375 char *msg;
1376
1377 --ectx.ec_stack.ga_len;
1378 tv = STACK_TV_BOT(0);
1379 if (tv->v_type == VAR_STRING)
Bram Moolenaar97a2af32020-01-28 22:52:48 +01001380 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001381 s = tv->vval.v_string;
Bram Moolenaar97a2af32020-01-28 22:52:48 +01001382 if (s == NULL)
1383 s = (char_u *)"";
1384 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001385 else
Bram Moolenaara6e67e42020-05-15 23:36:40 +02001386 // must be VAR_NUMBER, CHECKTYPE makes sure
1387 n = tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001388 msg = set_option_value(iptr->isn_arg.storeopt.so_name,
1389 n, s, iptr->isn_arg.storeopt.so_flags);
Bram Moolenaare75ba262020-05-16 15:43:31 +02001390 clear_tv(tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001391 if (msg != NULL)
1392 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001393 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001394 emsg(_(msg));
Bram Moolenaare8593122020-07-18 15:17:02 +02001395 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001396 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001397 }
1398 break;
1399
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001400 // store $ENV
1401 case ISN_STOREENV:
1402 --ectx.ec_stack.ga_len;
Bram Moolenaar20431c92020-03-20 18:39:46 +01001403 tv = STACK_TV_BOT(0);
1404 vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
1405 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001406 break;
1407
1408 // store @r
1409 case ISN_STOREREG:
1410 {
1411 int reg = iptr->isn_arg.number;
1412
1413 --ectx.ec_stack.ga_len;
Bram Moolenaar401d9ff2020-02-19 18:14:44 +01001414 tv = STACK_TV_BOT(0);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001415 write_reg_contents(reg == '@' ? '"' : reg,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +01001416 tv_get_string(tv), -1, FALSE);
1417 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001418 }
1419 break;
1420
1421 // store v: variable
1422 case ISN_STOREV:
1423 --ectx.ec_stack.ga_len;
1424 if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
1425 == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02001426 // should not happen, type is checked when compiling
1427 goto on_error;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001428 break;
1429
Bram Moolenaard3aac292020-04-19 14:32:17 +02001430 // store g:/b:/w:/t: variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001431 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02001432 case ISN_STOREB:
1433 case ISN_STOREW:
1434 case ISN_STORET:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001435 {
1436 dictitem_T *di;
Bram Moolenaard3aac292020-04-19 14:32:17 +02001437 hashtab_T *ht;
1438 switch (iptr->isn_type)
1439 {
1440 case ISN_STOREG:
1441 ht = get_globvar_ht();
1442 break;
1443 case ISN_STOREB:
1444 ht = &curbuf->b_vars->dv_hashtab;
1445 break;
1446 case ISN_STOREW:
1447 ht = &curwin->w_vars->dv_hashtab;
1448 break;
1449 case ISN_STORET:
1450 ht = &curtab->tp_vars->dv_hashtab;
1451 break;
1452 default: // Cannot reach here
1453 goto failed;
1454 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001455
1456 --ectx.ec_stack.ga_len;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001457 di = find_var_in_ht(ht, 0, iptr->isn_arg.string + 2, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001458 if (di == NULL)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001459 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001460 else
1461 {
1462 clear_tv(&di->di_tv);
1463 di->di_tv = *STACK_TV_BOT(0);
1464 }
1465 }
1466 break;
1467
1468 // store number in local variable
1469 case ISN_STORENR:
Bram Moolenaara471eea2020-03-04 22:20:26 +01001470 tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001471 clear_tv(tv);
1472 tv->v_type = VAR_NUMBER;
Bram Moolenaara471eea2020-03-04 22:20:26 +01001473 tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001474 break;
1475
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001476 // store value in list variable
1477 case ISN_STORELIST:
1478 {
1479 typval_T *tv_idx = STACK_TV_BOT(-2);
1480 varnumber_T lidx = tv_idx->vval.v_number;
1481 typval_T *tv_list = STACK_TV_BOT(-1);
1482 list_T *list = tv_list->vval.v_list;
1483
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001484 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001485 if (lidx < 0 && list->lv_len + lidx >= 0)
1486 // negative index is relative to the end
1487 lidx = list->lv_len + lidx;
1488 if (lidx < 0 || lidx > list->lv_len)
1489 {
1490 semsg(_(e_listidx), lidx);
Bram Moolenaare8593122020-07-18 15:17:02 +02001491 goto on_error;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001492 }
1493 tv = STACK_TV_BOT(-3);
1494 if (lidx < list->lv_len)
1495 {
1496 listitem_T *li = list_find(list, lidx);
1497
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001498 if (error_if_locked(li->li_tv.v_lock,
1499 e_cannot_change_list_item))
1500 goto failed;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001501 // overwrite existing list item
1502 clear_tv(&li->li_tv);
1503 li->li_tv = *tv;
1504 }
1505 else
1506 {
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001507 if (error_if_locked(list->lv_lock,
1508 e_cannot_change_list))
1509 goto failed;
Bram Moolenaare8593122020-07-18 15:17:02 +02001510 // append to list, only fails when out of memory
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001511 if (list_append_tv(list, tv) == FAIL)
1512 goto failed;
1513 clear_tv(tv);
1514 }
1515 clear_tv(tv_idx);
1516 clear_tv(tv_list);
Bram Moolenaarf163bd52020-05-10 21:47:43 +02001517 ectx.ec_stack.ga_len -= 3;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001518 }
1519 break;
1520
1521 // store value in dict variable
1522 case ISN_STOREDICT:
1523 {
1524 typval_T *tv_key = STACK_TV_BOT(-2);
1525 char_u *key = tv_key->vval.v_string;
1526 typval_T *tv_dict = STACK_TV_BOT(-1);
1527 dict_T *dict = tv_dict->vval.v_dict;
1528 dictitem_T *di;
1529
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001530 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02001531 if (dict == NULL)
1532 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02001533 emsg(_(e_dictionary_not_set));
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02001534 goto on_error;
1535 }
Bram Moolenaar58626872020-08-01 14:06:38 +02001536 if (key == NULL)
1537 key = (char_u *)"";
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001538 tv = STACK_TV_BOT(-3);
1539 di = dict_find(dict, key, -1);
1540 if (di != NULL)
1541 {
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001542 if (error_if_locked(di->di_tv.v_lock,
1543 e_cannot_change_dict_item))
1544 goto failed;
Bram Moolenaare8593122020-07-18 15:17:02 +02001545 // overwrite existing value
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001546 clear_tv(&di->di_tv);
1547 di->di_tv = *tv;
1548 }
1549 else
1550 {
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001551 if (error_if_locked(dict->dv_lock,
1552 e_cannot_change_dict))
1553 goto failed;
Bram Moolenaare8593122020-07-18 15:17:02 +02001554 // add to dict, only fails when out of memory
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001555 if (dict_add_tv(dict, (char *)key, tv) == FAIL)
1556 goto failed;
1557 clear_tv(tv);
1558 }
1559 clear_tv(tv_key);
1560 clear_tv(tv_dict);
Bram Moolenaarf163bd52020-05-10 21:47:43 +02001561 ectx.ec_stack.ga_len -= 3;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001562 }
1563 break;
1564
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001565 // push constant
1566 case ISN_PUSHNR:
1567 case ISN_PUSHBOOL:
1568 case ISN_PUSHSPEC:
1569 case ISN_PUSHF:
1570 case ISN_PUSHS:
1571 case ISN_PUSHBLOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001572 case ISN_PUSHFUNC:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001573 case ISN_PUSHCHANNEL:
1574 case ISN_PUSHJOB:
Bram Moolenaar270d0382020-05-15 21:42:53 +02001575 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001576 goto failed;
1577 tv = STACK_TV_BOT(0);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001578 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001579 ++ectx.ec_stack.ga_len;
1580 switch (iptr->isn_type)
1581 {
1582 case ISN_PUSHNR:
1583 tv->v_type = VAR_NUMBER;
1584 tv->vval.v_number = iptr->isn_arg.number;
1585 break;
1586 case ISN_PUSHBOOL:
1587 tv->v_type = VAR_BOOL;
1588 tv->vval.v_number = iptr->isn_arg.number;
1589 break;
1590 case ISN_PUSHSPEC:
1591 tv->v_type = VAR_SPECIAL;
1592 tv->vval.v_number = iptr->isn_arg.number;
1593 break;
1594#ifdef FEAT_FLOAT
1595 case ISN_PUSHF:
1596 tv->v_type = VAR_FLOAT;
1597 tv->vval.v_float = iptr->isn_arg.fnumber;
1598 break;
1599#endif
1600 case ISN_PUSHBLOB:
1601 blob_copy(iptr->isn_arg.blob, tv);
1602 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001603 case ISN_PUSHFUNC:
1604 tv->v_type = VAR_FUNC;
Bram Moolenaar087d2e12020-03-01 15:36:42 +01001605 if (iptr->isn_arg.string == NULL)
1606 tv->vval.v_string = NULL;
1607 else
1608 tv->vval.v_string =
1609 vim_strsave(iptr->isn_arg.string);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001610 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001611 case ISN_PUSHCHANNEL:
1612#ifdef FEAT_JOB_CHANNEL
1613 tv->v_type = VAR_CHANNEL;
1614 tv->vval.v_channel = iptr->isn_arg.channel;
1615 if (tv->vval.v_channel != NULL)
1616 ++tv->vval.v_channel->ch_refcount;
1617#endif
1618 break;
1619 case ISN_PUSHJOB:
1620#ifdef FEAT_JOB_CHANNEL
1621 tv->v_type = VAR_JOB;
1622 tv->vval.v_job = iptr->isn_arg.job;
1623 if (tv->vval.v_job != NULL)
1624 ++tv->vval.v_job->jv_refcount;
1625#endif
1626 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001627 default:
1628 tv->v_type = VAR_STRING;
Bram Moolenaare69f6d02020-04-01 22:11:01 +02001629 tv->vval.v_string = vim_strsave(
1630 iptr->isn_arg.string == NULL
1631 ? (char_u *)"" : iptr->isn_arg.string);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001632 }
1633 break;
1634
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001635 case ISN_UNLET:
1636 if (do_unlet(iptr->isn_arg.unlet.ul_name,
1637 iptr->isn_arg.unlet.ul_forceit) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02001638 goto on_error;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001639 break;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001640 case ISN_UNLETENV:
1641 vim_unsetenv(iptr->isn_arg.unlet.ul_name);
1642 break;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001643
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001644 case ISN_LOCKCONST:
1645 item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE);
1646 break;
1647
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001648 // create a list from items on the stack; uses a single allocation
1649 // for the list header and the items
1650 case ISN_NEWLIST:
Bram Moolenaarfe270812020-04-11 22:31:27 +02001651 if (exe_newlist(iptr->isn_arg.number, &ectx) == FAIL)
1652 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001653 break;
1654
1655 // create a dict from items on the stack
1656 case ISN_NEWDICT:
1657 {
Bram Moolenaare8593122020-07-18 15:17:02 +02001658 int count = iptr->isn_arg.number;
1659 dict_T *dict = dict_alloc();
1660 dictitem_T *item;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001661
1662 if (dict == NULL)
1663 goto failed;
1664 for (idx = 0; idx < count; ++idx)
1665 {
Bram Moolenaare8593122020-07-18 15:17:02 +02001666 // have already checked key type is VAR_STRING
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001667 tv = STACK_TV_BOT(2 * (idx - count));
Bram Moolenaare8593122020-07-18 15:17:02 +02001668 // check key is unique
1669 item = dict_find(dict, tv->vval.v_string, -1);
1670 if (item != NULL)
1671 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001672 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaare8593122020-07-18 15:17:02 +02001673 semsg(_(e_duplicate_key), tv->vval.v_string);
1674 dict_unref(dict);
1675 goto on_error;
1676 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001677 item = dictitem_alloc(tv->vval.v_string);
1678 clear_tv(tv);
1679 if (item == NULL)
Bram Moolenaare8593122020-07-18 15:17:02 +02001680 {
1681 dict_unref(dict);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001682 goto failed;
Bram Moolenaare8593122020-07-18 15:17:02 +02001683 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001684 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
1685 item->di_tv.v_lock = 0;
1686 if (dict_add(dict, item) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02001687 {
Bram Moolenaard032f342020-07-18 18:13:02 +02001688 // can this ever happen?
Bram Moolenaare8593122020-07-18 15:17:02 +02001689 dict_unref(dict);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001690 goto failed;
Bram Moolenaare8593122020-07-18 15:17:02 +02001691 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001692 }
1693
1694 if (count > 0)
1695 ectx.ec_stack.ga_len -= 2 * count - 1;
Bram Moolenaar270d0382020-05-15 21:42:53 +02001696 else if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001697 goto failed;
1698 else
1699 ++ectx.ec_stack.ga_len;
1700 tv = STACK_TV_BOT(-1);
1701 tv->v_type = VAR_DICT;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001702 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001703 tv->vval.v_dict = dict;
1704 ++dict->dv_refcount;
1705 }
1706 break;
1707
1708 // call a :def function
1709 case ISN_DCALL:
Bram Moolenaardfa3d552020-09-10 22:05:08 +02001710 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001711 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
1712 iptr->isn_arg.dfunc.cdf_argcount,
1713 &ectx) == FAIL)
Bram Moolenaare8593122020-07-18 15:17:02 +02001714 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001715 break;
1716
1717 // call a builtin function
1718 case ISN_BCALL:
1719 SOURCING_LNUM = iptr->isn_lnum;
1720 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
1721 iptr->isn_arg.bfunc.cbf_argcount,
1722 &ectx) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02001723 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001724 break;
1725
1726 // call a funcref or partial
1727 case ISN_PCALL:
1728 {
1729 cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
1730 int r;
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02001731 typval_T partial_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001732
1733 SOURCING_LNUM = iptr->isn_lnum;
1734 if (pfunc->cpf_top)
1735 {
1736 // funcref is above the arguments
1737 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
1738 }
1739 else
1740 {
1741 // Get the funcref from the stack.
1742 --ectx.ec_stack.ga_len;
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02001743 partial_tv = *STACK_TV_BOT(0);
1744 tv = &partial_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001745 }
1746 r = call_partial(tv, pfunc->cpf_argcount, &ectx);
Bram Moolenaar6f5b6df2020-05-16 21:20:12 +02001747 if (tv == &partial_tv)
1748 clear_tv(&partial_tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001749 if (r == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02001750 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001751 }
1752 break;
1753
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001754 case ISN_PCALL_END:
1755 // PCALL finished, arguments have been consumed and replaced by
1756 // the return value. Now clear the funcref from the stack,
1757 // and move the return value in its place.
1758 --ectx.ec_stack.ga_len;
1759 clear_tv(STACK_TV_BOT(-1));
1760 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
1761 break;
1762
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001763 // call a user defined function or funcref/partial
1764 case ISN_UCALL:
1765 {
1766 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
1767
1768 SOURCING_LNUM = iptr->isn_lnum;
1769 if (call_eval_func(cufunc->cuf_name,
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001770 cufunc->cuf_argcount, &ectx, iptr) == FAIL)
Bram Moolenaard032f342020-07-18 18:13:02 +02001771 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001772 }
1773 break;
1774
1775 // return from a :def function call
1776 case ISN_RETURN:
1777 {
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001778 garray_T *trystack = &ectx.ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01001779 trycmd_T *trycmd = NULL;
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001780
1781 if (trystack->ga_len > 0)
1782 trycmd = ((trycmd_T *)trystack->ga_data)
1783 + trystack->ga_len - 1;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001784 if (trycmd != NULL
1785 && trycmd->tcd_frame_idx == ectx.ec_frame_idx
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001786 && trycmd->tcd_finally_idx != 0)
1787 {
1788 // jump to ":finally"
1789 ectx.ec_iidx = trycmd->tcd_finally_idx;
1790 trycmd->tcd_return = TRUE;
1791 }
1792 else
Bram Moolenaard032f342020-07-18 18:13:02 +02001793 goto func_return;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001794 }
1795 break;
1796
1797 // push a function reference to a compiled function
1798 case ISN_FUNCREF:
1799 {
1800 partial_T *pt = NULL;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001801 dfunc_T *pt_dfunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001802
1803 pt = ALLOC_CLEAR_ONE(partial_T);
1804 if (pt == NULL)
1805 goto failed;
Bram Moolenaar270d0382020-05-15 21:42:53 +02001806 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001807 {
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001808 vim_free(pt);
1809 goto failed;
1810 }
1811 pt_dfunc = ((dfunc_T *)def_functions.ga_data)
1812 + iptr->isn_arg.funcref.fr_func;
1813 pt->pt_func = pt_dfunc->df_ufunc;
1814 pt->pt_refcount = 1;
1815 ++pt_dfunc->df_ufunc->uf_refcount;
1816
1817 if (pt_dfunc->df_ufunc->uf_flags & FC_CLOSURE)
1818 {
1819 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1820 + ectx.ec_dfunc_idx;
1821
1822 // The closure needs to find arguments and local
1823 // variables in the current stack.
Bram Moolenaarf7779c62020-05-03 15:38:16 +02001824 pt->pt_ectx_stack = &ectx.ec_stack;
1825 pt->pt_ectx_frame = ectx.ec_frame_idx;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001826
1827 // If this function returns and the closure is still
1828 // used, we need to make a copy of the context
1829 // (arguments and local variables). Store a reference
1830 // to the partial so we can handle that.
1831 ++pt->pt_refcount;
1832 tv = STACK_TV_VAR(dfunc->df_varcount
1833 + iptr->isn_arg.funcref.fr_var_idx);
1834 if (tv->v_type == VAR_PARTIAL)
1835 {
1836 // TODO: use a garray_T on ectx.
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001837 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001838 emsg("Multiple closures not supported yet");
Bram Moolenaardec07512020-09-18 23:11:10 +02001839 vim_free(pt);
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001840 goto failed;
1841 }
1842 tv->v_type = VAR_PARTIAL;
1843 tv->vval.v_partial = pt;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001844 }
1845
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001846 tv = STACK_TV_BOT(0);
1847 ++ectx.ec_stack.ga_len;
1848 tv->vval.v_partial = pt;
1849 tv->v_type = VAR_PARTIAL;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001850 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001851 }
1852 break;
1853
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001854 // Create a global function from a lambda.
1855 case ISN_NEWFUNC:
1856 {
1857 newfunc_T *newfunc = &iptr->isn_arg.newfunc;
1858
1859 copy_func(newfunc->nf_lambda, newfunc->nf_global);
1860 }
1861 break;
1862
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001863 // jump if a condition is met
1864 case ISN_JUMP:
1865 {
1866 jumpwhen_T when = iptr->isn_arg.jump.jump_when;
1867 int jump = TRUE;
1868
1869 if (when != JUMP_ALWAYS)
1870 {
1871 tv = STACK_TV_BOT(-1);
1872 jump = tv2bool(tv);
1873 if (when == JUMP_IF_FALSE
1874 || when == JUMP_AND_KEEP_IF_FALSE)
1875 jump = !jump;
Bram Moolenaar777770f2020-02-06 21:27:08 +01001876 if (when == JUMP_IF_FALSE || !jump)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001877 {
1878 // drop the value from the stack
1879 clear_tv(tv);
1880 --ectx.ec_stack.ga_len;
1881 }
1882 }
1883 if (jump)
1884 ectx.ec_iidx = iptr->isn_arg.jump.jump_where;
1885 }
1886 break;
1887
1888 // top of a for loop
1889 case ISN_FOR:
1890 {
1891 list_T *list = STACK_TV_BOT(-1)->vval.v_list;
1892 typval_T *idxtv =
1893 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);
1894
1895 // push the next item from the list
Bram Moolenaar270d0382020-05-15 21:42:53 +02001896 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001897 goto failed;
Bram Moolenaar77e5dcc2020-09-17 21:29:03 +02001898 ++idxtv->vval.v_number;
1899 if (list == NULL || idxtv->vval.v_number >= list->lv_len)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001900 // past the end of the list, jump to "endfor"
1901 ectx.ec_iidx = iptr->isn_arg.forloop.for_end;
1902 else if (list->lv_first == &range_list_item)
1903 {
1904 // non-materialized range() list
1905 tv = STACK_TV_BOT(0);
1906 tv->v_type = VAR_NUMBER;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001907 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001908 tv->vval.v_number = list_find_nr(
1909 list, idxtv->vval.v_number, NULL);
1910 ++ectx.ec_stack.ga_len;
1911 }
1912 else
1913 {
1914 listitem_T *li = list_find(list, idxtv->vval.v_number);
1915
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001916 copy_tv(&li->li_tv, STACK_TV_BOT(0));
1917 ++ectx.ec_stack.ga_len;
1918 }
1919 }
1920 break;
1921
1922 // start of ":try" block
1923 case ISN_TRY:
1924 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001925 trycmd_T *trycmd = NULL;
1926
Bram Moolenaar270d0382020-05-15 21:42:53 +02001927 if (GA_GROW(&ectx.ec_trystack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001928 goto failed;
1929 trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data)
1930 + ectx.ec_trystack.ga_len;
1931 ++ectx.ec_trystack.ga_len;
1932 ++trylevel;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001933 trycmd->tcd_frame_idx = ectx.ec_frame_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001934 trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch;
1935 trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001936 trycmd->tcd_caught = FALSE;
Bram Moolenaar9939f572020-09-16 22:29:52 +02001937 trycmd->tcd_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001938 }
1939 break;
1940
1941 case ISN_PUSHEXC:
1942 if (current_exception == NULL)
1943 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02001944 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001945 iemsg("Evaluating catch while current_exception is NULL");
1946 goto failed;
1947 }
Bram Moolenaar270d0382020-05-15 21:42:53 +02001948 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001949 goto failed;
1950 tv = STACK_TV_BOT(0);
1951 ++ectx.ec_stack.ga_len;
1952 tv->v_type = VAR_STRING;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02001953 tv->v_lock = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001954 tv->vval.v_string = vim_strsave(
1955 (char_u *)current_exception->value);
1956 break;
1957
1958 case ISN_CATCH:
1959 {
1960 garray_T *trystack = &ectx.ec_trystack;
1961
1962 if (trystack->ga_len > 0)
1963 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001964 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001965 + trystack->ga_len - 1;
1966 trycmd->tcd_caught = TRUE;
1967 }
1968 did_emsg = got_int = did_throw = FALSE;
1969 catch_exception(current_exception);
1970 }
1971 break;
1972
1973 // end of ":try" block
1974 case ISN_ENDTRY:
1975 {
1976 garray_T *trystack = &ectx.ec_trystack;
1977
1978 if (trystack->ga_len > 0)
1979 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001980 trycmd_T *trycmd = NULL;
1981
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001982 --trystack->ga_len;
1983 --trylevel;
Bram Moolenaar68d130c2020-07-17 22:06:44 +02001984 ectx.ec_in_catch = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001985 trycmd = ((trycmd_T *)trystack->ga_data)
1986 + trystack->ga_len;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001987 if (trycmd->tcd_caught && current_exception != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001988 {
1989 // discard the exception
1990 if (caught_stack == current_exception)
1991 caught_stack = caught_stack->caught;
1992 discard_current_exception();
1993 }
1994
1995 if (trycmd->tcd_return)
Bram Moolenaard032f342020-07-18 18:13:02 +02001996 goto func_return;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001997 }
1998 }
1999 break;
2000
2001 case ISN_THROW:
2002 --ectx.ec_stack.ga_len;
2003 tv = STACK_TV_BOT(0);
2004 if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL)
2005 {
2006 vim_free(tv->vval.v_string);
2007 goto failed;
2008 }
2009 did_throw = TRUE;
2010 break;
2011
2012 // compare with special values
2013 case ISN_COMPAREBOOL:
2014 case ISN_COMPARESPECIAL:
2015 {
2016 typval_T *tv1 = STACK_TV_BOT(-2);
2017 typval_T *tv2 = STACK_TV_BOT(-1);
2018 varnumber_T arg1 = tv1->vval.v_number;
2019 varnumber_T arg2 = tv2->vval.v_number;
2020 int res;
2021
2022 switch (iptr->isn_arg.op.op_type)
2023 {
2024 case EXPR_EQUAL: res = arg1 == arg2; break;
2025 case EXPR_NEQUAL: res = arg1 != arg2; break;
2026 default: res = 0; break;
2027 }
2028
2029 --ectx.ec_stack.ga_len;
2030 tv1->v_type = VAR_BOOL;
2031 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
2032 }
2033 break;
2034
2035 // Operation with two number arguments
2036 case ISN_OPNR:
2037 case ISN_COMPARENR:
2038 {
2039 typval_T *tv1 = STACK_TV_BOT(-2);
2040 typval_T *tv2 = STACK_TV_BOT(-1);
2041 varnumber_T arg1 = tv1->vval.v_number;
2042 varnumber_T arg2 = tv2->vval.v_number;
2043 varnumber_T res;
2044
2045 switch (iptr->isn_arg.op.op_type)
2046 {
2047 case EXPR_MULT: res = arg1 * arg2; break;
2048 case EXPR_DIV: res = arg1 / arg2; break;
2049 case EXPR_REM: res = arg1 % arg2; break;
2050 case EXPR_SUB: res = arg1 - arg2; break;
2051 case EXPR_ADD: res = arg1 + arg2; break;
2052
2053 case EXPR_EQUAL: res = arg1 == arg2; break;
2054 case EXPR_NEQUAL: res = arg1 != arg2; break;
2055 case EXPR_GREATER: res = arg1 > arg2; break;
2056 case EXPR_GEQUAL: res = arg1 >= arg2; break;
2057 case EXPR_SMALLER: res = arg1 < arg2; break;
2058 case EXPR_SEQUAL: res = arg1 <= arg2; break;
2059 default: res = 0; break;
2060 }
2061
2062 --ectx.ec_stack.ga_len;
2063 if (iptr->isn_type == ISN_COMPARENR)
2064 {
2065 tv1->v_type = VAR_BOOL;
2066 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
2067 }
2068 else
2069 tv1->vval.v_number = res;
2070 }
2071 break;
2072
2073 // Computation with two float arguments
2074 case ISN_OPFLOAT:
2075 case ISN_COMPAREFLOAT:
Bram Moolenaara5d59532020-01-26 21:42:03 +01002076#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002077 {
2078 typval_T *tv1 = STACK_TV_BOT(-2);
2079 typval_T *tv2 = STACK_TV_BOT(-1);
2080 float_T arg1 = tv1->vval.v_float;
2081 float_T arg2 = tv2->vval.v_float;
2082 float_T res = 0;
2083 int cmp = FALSE;
2084
2085 switch (iptr->isn_arg.op.op_type)
2086 {
2087 case EXPR_MULT: res = arg1 * arg2; break;
2088 case EXPR_DIV: res = arg1 / arg2; break;
2089 case EXPR_SUB: res = arg1 - arg2; break;
2090 case EXPR_ADD: res = arg1 + arg2; break;
2091
2092 case EXPR_EQUAL: cmp = arg1 == arg2; break;
2093 case EXPR_NEQUAL: cmp = arg1 != arg2; break;
2094 case EXPR_GREATER: cmp = arg1 > arg2; break;
2095 case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
2096 case EXPR_SMALLER: cmp = arg1 < arg2; break;
2097 case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
2098 default: cmp = 0; break;
2099 }
2100 --ectx.ec_stack.ga_len;
2101 if (iptr->isn_type == ISN_COMPAREFLOAT)
2102 {
2103 tv1->v_type = VAR_BOOL;
2104 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
2105 }
2106 else
2107 tv1->vval.v_float = res;
2108 }
Bram Moolenaara5d59532020-01-26 21:42:03 +01002109#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002110 break;
2111
2112 case ISN_COMPARELIST:
2113 {
2114 typval_T *tv1 = STACK_TV_BOT(-2);
2115 typval_T *tv2 = STACK_TV_BOT(-1);
2116 list_T *arg1 = tv1->vval.v_list;
2117 list_T *arg2 = tv2->vval.v_list;
2118 int cmp = FALSE;
2119 int ic = iptr->isn_arg.op.op_ic;
2120
2121 switch (iptr->isn_arg.op.op_type)
2122 {
2123 case EXPR_EQUAL: cmp =
2124 list_equal(arg1, arg2, ic, FALSE); break;
2125 case EXPR_NEQUAL: cmp =
2126 !list_equal(arg1, arg2, ic, FALSE); break;
2127 case EXPR_IS: cmp = arg1 == arg2; break;
2128 case EXPR_ISNOT: cmp = arg1 != arg2; break;
2129 default: cmp = 0; break;
2130 }
2131 --ectx.ec_stack.ga_len;
2132 clear_tv(tv1);
2133 clear_tv(tv2);
2134 tv1->v_type = VAR_BOOL;
2135 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
2136 }
2137 break;
2138
2139 case ISN_COMPAREBLOB:
2140 {
2141 typval_T *tv1 = STACK_TV_BOT(-2);
2142 typval_T *tv2 = STACK_TV_BOT(-1);
2143 blob_T *arg1 = tv1->vval.v_blob;
2144 blob_T *arg2 = tv2->vval.v_blob;
2145 int cmp = FALSE;
2146
2147 switch (iptr->isn_arg.op.op_type)
2148 {
2149 case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break;
2150 case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break;
2151 case EXPR_IS: cmp = arg1 == arg2; break;
2152 case EXPR_ISNOT: cmp = arg1 != arg2; break;
2153 default: cmp = 0; break;
2154 }
2155 --ectx.ec_stack.ga_len;
2156 clear_tv(tv1);
2157 clear_tv(tv2);
2158 tv1->v_type = VAR_BOOL;
2159 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
2160 }
2161 break;
2162
2163 // TODO: handle separately
2164 case ISN_COMPARESTRING:
2165 case ISN_COMPAREDICT:
2166 case ISN_COMPAREFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002167 case ISN_COMPAREANY:
2168 {
2169 typval_T *tv1 = STACK_TV_BOT(-2);
2170 typval_T *tv2 = STACK_TV_BOT(-1);
2171 exptype_T exptype = iptr->isn_arg.op.op_type;
2172 int ic = iptr->isn_arg.op.op_ic;
2173
Bram Moolenaareb26f432020-09-14 16:50:05 +02002174 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002175 typval_compare(tv1, tv2, exptype, ic);
2176 clear_tv(tv2);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002177 --ectx.ec_stack.ga_len;
2178 }
2179 break;
2180
2181 case ISN_ADDLIST:
2182 case ISN_ADDBLOB:
2183 {
2184 typval_T *tv1 = STACK_TV_BOT(-2);
2185 typval_T *tv2 = STACK_TV_BOT(-1);
2186
2187 if (iptr->isn_type == ISN_ADDLIST)
2188 eval_addlist(tv1, tv2);
2189 else
2190 eval_addblob(tv1, tv2);
2191 clear_tv(tv2);
2192 --ectx.ec_stack.ga_len;
2193 }
2194 break;
2195
2196 // Computation with two arguments of unknown type
2197 case ISN_OPANY:
2198 {
2199 typval_T *tv1 = STACK_TV_BOT(-2);
2200 typval_T *tv2 = STACK_TV_BOT(-1);
2201 varnumber_T n1, n2;
2202#ifdef FEAT_FLOAT
2203 float_T f1 = 0, f2 = 0;
2204#endif
2205 int error = FALSE;
2206
2207 if (iptr->isn_arg.op.op_type == EXPR_ADD)
2208 {
2209 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
2210 {
2211 eval_addlist(tv1, tv2);
2212 clear_tv(tv2);
2213 --ectx.ec_stack.ga_len;
2214 break;
2215 }
2216 else if (tv1->v_type == VAR_BLOB
2217 && tv2->v_type == VAR_BLOB)
2218 {
2219 eval_addblob(tv1, tv2);
2220 clear_tv(tv2);
2221 --ectx.ec_stack.ga_len;
2222 break;
2223 }
2224 }
2225#ifdef FEAT_FLOAT
2226 if (tv1->v_type == VAR_FLOAT)
2227 {
2228 f1 = tv1->vval.v_float;
2229 n1 = 0;
2230 }
2231 else
2232#endif
2233 {
2234 n1 = tv_get_number_chk(tv1, &error);
2235 if (error)
Bram Moolenaard032f342020-07-18 18:13:02 +02002236 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002237#ifdef FEAT_FLOAT
2238 if (tv2->v_type == VAR_FLOAT)
2239 f1 = n1;
2240#endif
2241 }
2242#ifdef FEAT_FLOAT
2243 if (tv2->v_type == VAR_FLOAT)
2244 {
2245 f2 = tv2->vval.v_float;
2246 n2 = 0;
2247 }
2248 else
2249#endif
2250 {
2251 n2 = tv_get_number_chk(tv2, &error);
2252 if (error)
Bram Moolenaard032f342020-07-18 18:13:02 +02002253 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002254#ifdef FEAT_FLOAT
2255 if (tv1->v_type == VAR_FLOAT)
2256 f2 = n2;
2257#endif
2258 }
2259#ifdef FEAT_FLOAT
2260 // if there is a float on either side the result is a float
2261 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
2262 {
2263 switch (iptr->isn_arg.op.op_type)
2264 {
2265 case EXPR_MULT: f1 = f1 * f2; break;
2266 case EXPR_DIV: f1 = f1 / f2; break;
2267 case EXPR_SUB: f1 = f1 - f2; break;
2268 case EXPR_ADD: f1 = f1 + f2; break;
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002269 default: SOURCING_LNUM = iptr->isn_lnum;
2270 emsg(_(e_modulus));
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002271 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002272 }
2273 clear_tv(tv1);
2274 clear_tv(tv2);
2275 tv1->v_type = VAR_FLOAT;
2276 tv1->vval.v_float = f1;
2277 --ectx.ec_stack.ga_len;
2278 }
2279 else
2280#endif
2281 {
2282 switch (iptr->isn_arg.op.op_type)
2283 {
2284 case EXPR_MULT: n1 = n1 * n2; break;
2285 case EXPR_DIV: n1 = num_divide(n1, n2); break;
2286 case EXPR_SUB: n1 = n1 - n2; break;
2287 case EXPR_ADD: n1 = n1 + n2; break;
2288 default: n1 = num_modulus(n1, n2); break;
2289 }
2290 clear_tv(tv1);
2291 clear_tv(tv2);
2292 tv1->v_type = VAR_NUMBER;
2293 tv1->vval.v_number = n1;
2294 --ectx.ec_stack.ga_len;
2295 }
2296 }
2297 break;
2298
2299 case ISN_CONCAT:
2300 {
2301 char_u *str1 = STACK_TV_BOT(-2)->vval.v_string;
2302 char_u *str2 = STACK_TV_BOT(-1)->vval.v_string;
2303 char_u *res;
2304
2305 res = concat_str(str1, str2);
2306 clear_tv(STACK_TV_BOT(-2));
2307 clear_tv(STACK_TV_BOT(-1));
2308 --ectx.ec_stack.ga_len;
2309 STACK_TV_BOT(-1)->vval.v_string = res;
2310 }
2311 break;
2312
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02002313 case ISN_STRINDEX:
Bram Moolenaar11107ba2020-08-15 21:10:16 +02002314 case ISN_STRSLICE:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02002315 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02002316 int is_slice = iptr->isn_type == ISN_STRSLICE;
2317 varnumber_T n1 = 0, n2;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02002318 char_u *res;
2319
2320 // string index: string is at stack-2, index at stack-1
Bram Moolenaar11107ba2020-08-15 21:10:16 +02002321 // string slice: string is at stack-3, first index at
2322 // stack-2, second index at stack-1
Bram Moolenaar11107ba2020-08-15 21:10:16 +02002323 if (is_slice)
2324 {
2325 tv = STACK_TV_BOT(-2);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02002326 n1 = tv->vval.v_number;
2327 }
2328
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02002329 tv = STACK_TV_BOT(-1);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02002330 n2 = tv->vval.v_number;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02002331
Bram Moolenaar11107ba2020-08-15 21:10:16 +02002332 ectx.ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02002333 tv = STACK_TV_BOT(-1);
Bram Moolenaar11107ba2020-08-15 21:10:16 +02002334 if (is_slice)
2335 // Slice: Select the characters from the string
2336 res = string_slice(tv->vval.v_string, n1, n2);
2337 else
2338 // Index: The resulting variable is a string of a
2339 // single character. If the index is too big or
2340 // negative the result is empty.
2341 res = char_from_string(tv->vval.v_string, n2);
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02002342 vim_free(tv->vval.v_string);
2343 tv->vval.v_string = res;
2344 }
2345 break;
2346
2347 case ISN_LISTINDEX:
Bram Moolenaared591872020-08-15 22:14:53 +02002348 case ISN_LISTSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002349 {
Bram Moolenaared591872020-08-15 22:14:53 +02002350 int is_slice = iptr->isn_type == ISN_LISTSLICE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002351 list_T *list;
Bram Moolenaared591872020-08-15 22:14:53 +02002352 varnumber_T n1, n2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002353
2354 // list index: list is at stack-2, index at stack-1
Bram Moolenaared591872020-08-15 22:14:53 +02002355 // list slice: list is at stack-3, indexes at stack-2 and
2356 // stack-1
2357 tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002358 list = tv->vval.v_list;
2359
2360 tv = STACK_TV_BOT(-1);
Bram Moolenaared591872020-08-15 22:14:53 +02002361 n1 = n2 = tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002362 clear_tv(tv);
Bram Moolenaared591872020-08-15 22:14:53 +02002363
2364 if (is_slice)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002365 {
Bram Moolenaared591872020-08-15 22:14:53 +02002366 tv = STACK_TV_BOT(-2);
Bram Moolenaared591872020-08-15 22:14:53 +02002367 n1 = tv->vval.v_number;
2368 clear_tv(tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002369 }
Bram Moolenaared591872020-08-15 22:14:53 +02002370
2371 ectx.ec_stack.ga_len -= is_slice ? 2 : 1;
Bram Moolenaar435d8972020-07-05 16:42:13 +02002372 tv = STACK_TV_BOT(-1);
Bram Moolenaar1d634542020-08-18 13:41:50 +02002373 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaared591872020-08-15 22:14:53 +02002374 if (list_slice_or_index(list, is_slice, n1, n2, tv, TRUE)
2375 == FAIL)
2376 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002377 }
2378 break;
2379
Bram Moolenaarcc673e72020-08-16 17:33:35 +02002380 case ISN_ANYINDEX:
2381 case ISN_ANYSLICE:
2382 {
2383 int is_slice = iptr->isn_type == ISN_ANYSLICE;
2384 typval_T *var1, *var2;
2385 int res;
2386
2387 // index: composite is at stack-2, index at stack-1
2388 // slice: composite is at stack-3, indexes at stack-2 and
2389 // stack-1
2390 tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
Bram Moolenaar3affe7a2020-08-18 20:34:13 +02002391 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02002392 if (check_can_index(tv, TRUE, TRUE) == FAIL)
2393 goto on_error;
2394 var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1);
2395 var2 = is_slice ? STACK_TV_BOT(-1) : NULL;
2396 res = eval_index_inner(tv, is_slice,
2397 var1, var2, NULL, -1, TRUE);
2398 clear_tv(var1);
2399 if (is_slice)
2400 clear_tv(var2);
2401 ectx.ec_stack.ga_len -= is_slice ? 2 : 1;
2402 if (res == FAIL)
2403 goto on_error;
2404 }
2405 break;
2406
Bram Moolenaar9af78762020-06-16 11:34:42 +02002407 case ISN_SLICE:
2408 {
2409 list_T *list;
2410 int count = iptr->isn_arg.number;
2411
Bram Moolenaarc5b1c202020-06-18 22:43:27 +02002412 // type will have been checked to be a list
Bram Moolenaar9af78762020-06-16 11:34:42 +02002413 tv = STACK_TV_BOT(-1);
Bram Moolenaar9af78762020-06-16 11:34:42 +02002414 list = tv->vval.v_list;
2415
2416 // no error for short list, expect it to be checked earlier
2417 if (list != NULL && list->lv_len >= count)
2418 {
2419 list_T *newlist = list_slice(list,
2420 count, list->lv_len - 1);
2421
2422 if (newlist != NULL)
2423 {
2424 list_unref(list);
2425 tv->vval.v_list = newlist;
2426 ++newlist->lv_refcount;
2427 }
2428 }
2429 }
2430 break;
2431
Bram Moolenaar47a519a2020-06-14 23:05:10 +02002432 case ISN_GETITEM:
2433 {
2434 listitem_T *li;
2435 int index = iptr->isn_arg.number;
2436
Bram Moolenaarc785b9a2020-06-19 18:34:15 +02002437 // Get list item: list is at stack-1, push item.
2438 // List type and length is checked for when compiling.
Bram Moolenaar47a519a2020-06-14 23:05:10 +02002439 tv = STACK_TV_BOT(-1);
Bram Moolenaarc785b9a2020-06-19 18:34:15 +02002440 li = list_find(tv->vval.v_list, index);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02002441
2442 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
2443 goto failed;
2444 ++ectx.ec_stack.ga_len;
2445 copy_tv(&li->li_tv, STACK_TV_BOT(-1));
2446 }
2447 break;
2448
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002449 case ISN_MEMBER:
2450 {
2451 dict_T *dict;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002452 char_u *key;
2453 dictitem_T *di;
Bram Moolenaar50788ef2020-07-05 16:51:26 +02002454 typval_T temp_tv;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002455
2456 // dict member: dict is at stack-2, key at stack-1
2457 tv = STACK_TV_BOT(-2);
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02002458 // no need to check for VAR_DICT, CHECKTYPE will check.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002459 dict = tv->vval.v_dict;
2460
2461 tv = STACK_TV_BOT(-1);
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02002462 // no need to check for VAR_STRING, 2STRING will check.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002463 key = tv->vval.v_string;
Bram Moolenaar4dac32c2020-05-15 21:44:19 +02002464
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002465 if ((di = dict_find(dict, key, -1)) == NULL)
2466 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002467 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002468 semsg(_(e_dictkey), key);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002469 goto on_error;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002470 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002471 clear_tv(tv);
Bram Moolenaar50788ef2020-07-05 16:51:26 +02002472 --ectx.ec_stack.ga_len;
2473 // Clear the dict after getting the item, to avoid that it
2474 // make the item invalid.
2475 tv = STACK_TV_BOT(-1);
2476 temp_tv = *tv;
2477 copy_tv(&di->di_tv, tv);
2478 clear_tv(&temp_tv);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002479 }
2480 break;
2481
2482 // dict member with string key
2483 case ISN_STRINGMEMBER:
2484 {
2485 dict_T *dict;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002486 dictitem_T *di;
Bram Moolenaarfb9d5c52020-07-04 19:19:43 +02002487 typval_T temp_tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002488
2489 tv = STACK_TV_BOT(-1);
2490 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
2491 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002492 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002493 emsg(_(e_dictreq));
Bram Moolenaard032f342020-07-18 18:13:02 +02002494 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002495 }
2496 dict = tv->vval.v_dict;
2497
2498 if ((di = dict_find(dict, iptr->isn_arg.string, -1))
2499 == NULL)
2500 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002501 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002502 semsg(_(e_dictkey), iptr->isn_arg.string);
Bram Moolenaard032f342020-07-18 18:13:02 +02002503 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002504 }
Bram Moolenaarfb9d5c52020-07-04 19:19:43 +02002505 // Clear the dict after getting the item, to avoid that it
2506 // make the item invalid.
2507 temp_tv = *tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002508 copy_tv(&di->di_tv, tv);
Bram Moolenaarfb9d5c52020-07-04 19:19:43 +02002509 clear_tv(&temp_tv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002510 }
2511 break;
2512
2513 case ISN_NEGATENR:
2514 tv = STACK_TV_BOT(-1);
Bram Moolenaarc58164c2020-03-29 18:40:30 +02002515 if (tv->v_type != VAR_NUMBER
2516#ifdef FEAT_FLOAT
2517 && tv->v_type != VAR_FLOAT
2518#endif
2519 )
2520 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002521 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaarc58164c2020-03-29 18:40:30 +02002522 emsg(_(e_number_exp));
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002523 goto on_error;
Bram Moolenaarc58164c2020-03-29 18:40:30 +02002524 }
2525#ifdef FEAT_FLOAT
2526 if (tv->v_type == VAR_FLOAT)
2527 tv->vval.v_float = -tv->vval.v_float;
2528 else
2529#endif
2530 tv->vval.v_number = -tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002531 break;
2532
2533 case ISN_CHECKNR:
2534 {
2535 int error = FALSE;
2536
2537 tv = STACK_TV_BOT(-1);
Bram Moolenaar3affe7a2020-08-18 20:34:13 +02002538 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002539 if (check_not_string(tv) == FAIL)
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002540 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002541 (void)tv_get_number_chk(tv, &error);
2542 if (error)
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002543 goto on_error;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002544 }
2545 break;
2546
2547 case ISN_CHECKTYPE:
2548 {
2549 checktype_T *ct = &iptr->isn_arg.type;
2550
2551 tv = STACK_TV_BOT(ct->ct_off);
Bram Moolenaar5e654232020-09-16 15:22:00 +02002552 SOURCING_LNUM = iptr->isn_lnum;
2553 if (check_typval_type(ct->ct_type, tv, 0) == FAIL)
2554 goto on_error;
2555
2556 // number 0 is FALSE, number 1 is TRUE
2557 if (tv->v_type == VAR_NUMBER
2558 && ct->ct_type->tt_type == VAR_BOOL
2559 && (tv->vval.v_number == 0
2560 || tv->vval.v_number == 1))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002561 {
Bram Moolenaar5e654232020-09-16 15:22:00 +02002562 tv->v_type = VAR_BOOL;
2563 tv->vval.v_number = tv->vval.v_number
Bram Moolenaardadaddd2020-09-12 19:11:23 +02002564 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002565 }
2566 }
2567 break;
2568
Bram Moolenaar9af78762020-06-16 11:34:42 +02002569 case ISN_CHECKLEN:
2570 {
2571 int min_len = iptr->isn_arg.checklen.cl_min_len;
2572 list_T *list = NULL;
2573
2574 tv = STACK_TV_BOT(-1);
2575 if (tv->v_type == VAR_LIST)
2576 list = tv->vval.v_list;
2577 if (list == NULL || list->lv_len < min_len
2578 || (list->lv_len > min_len
2579 && !iptr->isn_arg.checklen.cl_more_OK))
2580 {
Bram Moolenaar7517ffd2020-08-14 18:35:07 +02002581 SOURCING_LNUM = iptr->isn_lnum;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002582 semsg(_(e_expected_nr_items_but_got_nr),
Bram Moolenaar9af78762020-06-16 11:34:42 +02002583 min_len, list == NULL ? 0 : list->lv_len);
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002584 goto on_error;
Bram Moolenaar9af78762020-06-16 11:34:42 +02002585 }
2586 }
2587 break;
2588
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002589 case ISN_2BOOL:
2590 {
2591 int n;
2592
2593 tv = STACK_TV_BOT(-1);
2594 n = tv2bool(tv);
2595 if (iptr->isn_arg.number) // invert
2596 n = !n;
2597 clear_tv(tv);
2598 tv->v_type = VAR_BOOL;
2599 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
2600 }
2601 break;
2602
2603 case ISN_2STRING:
Bram Moolenaar418f1df2020-08-12 21:34:49 +02002604 case ISN_2STRING_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002605 {
2606 char_u *str;
2607
2608 tv = STACK_TV_BOT(iptr->isn_arg.number);
2609 if (tv->v_type != VAR_STRING)
2610 {
Bram Moolenaar418f1df2020-08-12 21:34:49 +02002611 if (iptr->isn_type == ISN_2STRING_ANY)
2612 {
2613 switch (tv->v_type)
2614 {
2615 case VAR_SPECIAL:
2616 case VAR_BOOL:
2617 case VAR_NUMBER:
2618 case VAR_FLOAT:
2619 case VAR_BLOB: break;
2620 default: to_string_error(tv->v_type);
2621 goto on_error;
2622 }
2623 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002624 str = typval_tostring(tv);
2625 clear_tv(tv);
2626 tv->v_type = VAR_STRING;
2627 tv->vval.v_string = str;
2628 }
2629 }
2630 break;
2631
Bram Moolenaarc3516f72020-09-08 22:45:35 +02002632 case ISN_PUT:
2633 {
2634 int regname = iptr->isn_arg.put.put_regname;
2635 linenr_T lnum = iptr->isn_arg.put.put_lnum;
2636 char_u *expr = NULL;
2637 int dir = FORWARD;
2638
2639 if (regname == '=')
2640 {
2641 tv = STACK_TV_BOT(-1);
2642 if (tv->v_type == VAR_STRING)
2643 expr = tv->vval.v_string;
2644 else
2645 {
2646 expr = typval_tostring(tv); // allocates value
2647 clear_tv(tv);
2648 }
2649 --ectx.ec_stack.ga_len;
2650 }
2651 if (lnum == -2)
2652 // :put! above cursor
2653 dir = BACKWARD;
2654 else if (lnum >= 0)
2655 curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum;
2656 check_cursor();
2657 do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
2658 vim_free(expr);
2659 }
2660 break;
2661
Bram Moolenaar389df252020-07-09 21:20:47 +02002662 case ISN_SHUFFLE:
2663 {
2664 typval_T tmp_tv;
2665 int item = iptr->isn_arg.shuffle.shfl_item;
2666 int up = iptr->isn_arg.shuffle.shfl_up;
2667
2668 tmp_tv = *STACK_TV_BOT(-item);
2669 for ( ; up > 0 && item > 1; --up)
2670 {
2671 *STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1);
2672 --item;
2673 }
2674 *STACK_TV_BOT(-item) = tmp_tv;
2675 }
2676 break;
2677
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002678 case ISN_DROP:
2679 --ectx.ec_stack.ga_len;
2680 clear_tv(STACK_TV_BOT(0));
2681 break;
2682 }
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002683 continue;
2684
Bram Moolenaard032f342020-07-18 18:13:02 +02002685func_return:
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02002686 // Restore previous function. If the frame pointer is where we started
2687 // then there is none and we are done.
Bram Moolenaard032f342020-07-18 18:13:02 +02002688 if (ectx.ec_frame_idx == initial_frame_idx)
Bram Moolenaard032f342020-07-18 18:13:02 +02002689 goto done;
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02002690
Bram Moolenaard032f342020-07-18 18:13:02 +02002691 if (func_return(&ectx) == FAIL)
2692 // only fails when out of memory
2693 goto failed;
Bram Moolenaarc7db5772020-07-21 20:55:50 +02002694 continue;
Bram Moolenaard032f342020-07-18 18:13:02 +02002695
Bram Moolenaarf0b9f432020-07-17 23:03:17 +02002696on_error:
2697 if (trylevel == 0)
2698 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002699 }
2700
2701done:
2702 // function finished, get result from the stack.
2703 tv = STACK_TV_BOT(-1);
2704 *rettv = *tv;
2705 tv->v_type = VAR_UNKNOWN;
2706 ret = OK;
2707
2708failed:
Bram Moolenaar7cbfaa52020-09-18 21:25:32 +02002709 // Also deal with closures when failed, they may already be in use
2710 // somewhere.
2711 handle_closure_in_use(&ectx, FALSE);
2712
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01002713 // When failed need to unwind the call stack.
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02002714 while (ectx.ec_frame_idx != initial_frame_idx)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01002715 func_return(&ectx);
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02002716
Bram Moolenaaree8580e2020-08-28 17:19:07 +02002717 estack_pop();
2718 current_sctx = save_current_sctx;
2719
2720failed_early:
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02002721 // Free all local variables, but not arguments.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002722 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
2723 clear_tv(STACK_TV(idx));
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02002724
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002725 vim_free(ectx.ec_stack.ga_data);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002726 vim_free(ectx.ec_trystack.ga_data);
Bram Moolenaar682d0a12020-07-19 20:48:59 +02002727
Bram Moolenaar77e5dcc2020-09-17 21:29:03 +02002728 // Not sure if this is necessary.
2729 suppress_errthrow = save_suppress_errthrow;
2730
Bram Moolenaar682d0a12020-07-19 20:48:59 +02002731 if (ret != OK && called_emsg == called_emsg_before)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002732 semsg(_(e_unknown_error_while_executing_str),
Bram Moolenaar682d0a12020-07-19 20:48:59 +02002733 printable_func_name(ufunc));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002734 return ret;
2735}
2736
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002737/*
2738 * ":dissassemble".
Bram Moolenaar777770f2020-02-06 21:27:08 +01002739 * We don't really need this at runtime, but we do have tests that require it,
2740 * so always include this.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002741 */
2742 void
2743ex_disassemble(exarg_T *eap)
2744{
Bram Moolenaar21456cd2020-02-13 21:29:32 +01002745 char_u *arg = eap->arg;
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01002746 char_u *fname;
2747 ufunc_T *ufunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002748 dfunc_T *dfunc;
2749 isn_T *instr;
2750 int current;
2751 int line_idx = 0;
2752 int prev_current = 0;
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002753 int is_global = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002754
Bram Moolenaarbfd65582020-07-13 18:18:00 +02002755 if (STRNCMP(arg, "<lambda>", 8) == 0)
2756 {
2757 arg += 8;
2758 (void)getdigits(&arg);
2759 fname = vim_strnsave(eap->arg, arg - eap->arg);
2760 }
2761 else
2762 fname = trans_function_name(&arg, &is_global, FALSE,
Bram Moolenaarb68b3462020-05-06 21:06:30 +02002763 TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL);
Bram Moolenaar21456cd2020-02-13 21:29:32 +01002764 if (fname == NULL)
2765 {
2766 semsg(_(e_invarg2), eap->arg);
2767 return;
2768 }
2769
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002770 ufunc = find_func(fname, is_global, NULL);
Bram Moolenaara26b9702020-04-18 19:53:28 +02002771 if (ufunc == NULL)
2772 {
2773 char_u *p = untrans_function_name(fname);
2774
2775 if (p != NULL)
2776 // Try again without making it script-local.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002777 ufunc = find_func(p, FALSE, NULL);
Bram Moolenaara26b9702020-04-18 19:53:28 +02002778 }
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01002779 vim_free(fname);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002780 if (ufunc == NULL)
2781 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002782 semsg(_(e_cannot_find_function_str), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002783 return;
2784 }
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02002785 if (ufunc->uf_def_status == UF_TO_BE_COMPILED
Bram Moolenaar822ba242020-05-24 23:00:18 +02002786 && compile_def_function(ufunc, FALSE, NULL) == FAIL)
2787 return;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02002788 if (ufunc->uf_def_status != UF_COMPILED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002789 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002790 semsg(_(e_function_is_not_compiled_str), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002791 return;
2792 }
2793 if (ufunc->uf_name_exp != NULL)
2794 msg((char *)ufunc->uf_name_exp);
2795 else
2796 msg((char *)ufunc->uf_name);
2797
2798 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
2799 instr = dfunc->df_instr;
2800 for (current = 0; current < dfunc->df_instr_count; ++current)
2801 {
2802 isn_T *iptr = &instr[current];
Bram Moolenaarf2460a32020-02-07 22:09:54 +01002803 char *line;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002804
2805 while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len)
2806 {
2807 if (current > prev_current)
2808 {
2809 msg_puts("\n\n");
2810 prev_current = current;
2811 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01002812 line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
2813 if (line != NULL)
2814 msg(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002815 }
2816
2817 switch (iptr->isn_type)
2818 {
2819 case ISN_EXEC:
2820 smsg("%4d EXEC %s", current, iptr->isn_arg.string);
2821 break;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02002822 case ISN_EXECCONCAT:
2823 smsg("%4d EXECCONCAT %lld", current,
2824 (long long)iptr->isn_arg.number);
2825 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002826 case ISN_ECHO:
2827 {
2828 echo_T *echo = &iptr->isn_arg.echo;
2829
2830 smsg("%4d %s %d", current,
2831 echo->echo_with_white ? "ECHO" : "ECHON",
2832 echo->echo_count);
2833 }
2834 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01002835 case ISN_EXECUTE:
Bram Moolenaar10827722020-03-23 22:53:22 +01002836 smsg("%4d EXECUTE %lld", current,
2837 (long long)(iptr->isn_arg.number));
Bram Moolenaarad39c092020-02-26 18:23:43 +01002838 break;
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002839 case ISN_ECHOMSG:
2840 smsg("%4d ECHOMSG %lld", current,
2841 (long long)(iptr->isn_arg.number));
2842 break;
2843 case ISN_ECHOERR:
2844 smsg("%4d ECHOERR %lld", current,
2845 (long long)(iptr->isn_arg.number));
2846 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002847 case ISN_LOAD:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002848 case ISN_LOADOUTER:
2849 {
2850 char *add = iptr->isn_type == ISN_LOAD ? "" : "OUTER";
2851
2852 if (iptr->isn_arg.number < 0)
2853 smsg("%4d LOAD%s arg[%lld]", current, add,
2854 (long long)(iptr->isn_arg.number
2855 + STACK_FRAME_SIZE));
2856 else
2857 smsg("%4d LOAD%s $%lld", current, add,
Bram Moolenaar10827722020-03-23 22:53:22 +01002858 (long long)(iptr->isn_arg.number));
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002859 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002860 break;
2861 case ISN_LOADV:
2862 smsg("%4d LOADV v:%s", current,
2863 get_vim_var_name(iptr->isn_arg.number));
2864 break;
2865 case ISN_LOADSCRIPT:
2866 {
2867 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002868 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002869 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
2870 + iptr->isn_arg.script.script_idx;
2871
2872 smsg("%4d LOADSCRIPT %s from %s", current,
2873 sv->sv_name, si->sn_name);
2874 }
2875 break;
2876 case ISN_LOADS:
2877 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002878 scriptitem_T *si = SCRIPT_ITEM(
2879 iptr->isn_arg.loadstore.ls_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002880
2881 smsg("%4d LOADS s:%s from %s", current,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002882 iptr->isn_arg.loadstore.ls_name, si->sn_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002883 }
2884 break;
2885 case ISN_LOADG:
2886 smsg("%4d LOADG g:%s", current, iptr->isn_arg.string);
2887 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02002888 case ISN_LOADB:
2889 smsg("%4d LOADB b:%s", current, iptr->isn_arg.string);
2890 break;
2891 case ISN_LOADW:
2892 smsg("%4d LOADW w:%s", current, iptr->isn_arg.string);
2893 break;
2894 case ISN_LOADT:
2895 smsg("%4d LOADT t:%s", current, iptr->isn_arg.string);
2896 break;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002897 case ISN_LOADGDICT:
2898 smsg("%4d LOAD g:", current);
2899 break;
2900 case ISN_LOADBDICT:
2901 smsg("%4d LOAD b:", current);
2902 break;
2903 case ISN_LOADWDICT:
2904 smsg("%4d LOAD w:", current);
2905 break;
2906 case ISN_LOADTDICT:
2907 smsg("%4d LOAD t:", current);
2908 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002909 case ISN_LOADOPT:
2910 smsg("%4d LOADOPT %s", current, iptr->isn_arg.string);
2911 break;
2912 case ISN_LOADENV:
2913 smsg("%4d LOADENV %s", current, iptr->isn_arg.string);
2914 break;
2915 case ISN_LOADREG:
Bram Moolenaar10827722020-03-23 22:53:22 +01002916 smsg("%4d LOADREG @%c", current, (int)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002917 break;
2918
2919 case ISN_STORE:
Bram Moolenaarb68b3462020-05-06 21:06:30 +02002920 case ISN_STOREOUTER:
2921 {
2922 char *add = iptr->isn_type == ISN_STORE ? "" : "OUTER";
2923
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01002924 if (iptr->isn_arg.number < 0)
Bram Moolenaarb68b3462020-05-06 21:06:30 +02002925 smsg("%4d STORE%s arg[%lld]", current, add,
Bram Moolenaar10827722020-03-23 22:53:22 +01002926 (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01002927 else
Bram Moolenaarb68b3462020-05-06 21:06:30 +02002928 smsg("%4d STORE%s $%lld", current, add,
Bram Moolenaar10827722020-03-23 22:53:22 +01002929 (long long)(iptr->isn_arg.number));
Bram Moolenaarb68b3462020-05-06 21:06:30 +02002930 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002931 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002932 case ISN_STOREV:
2933 smsg("%4d STOREV v:%s", current,
2934 get_vim_var_name(iptr->isn_arg.number));
2935 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002936 case ISN_STOREG:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002937 smsg("%4d STOREG %s", current, iptr->isn_arg.string);
2938 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02002939 case ISN_STOREB:
2940 smsg("%4d STOREB %s", current, iptr->isn_arg.string);
2941 break;
2942 case ISN_STOREW:
2943 smsg("%4d STOREW %s", current, iptr->isn_arg.string);
2944 break;
2945 case ISN_STORET:
2946 smsg("%4d STORET %s", current, iptr->isn_arg.string);
2947 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002948 case ISN_STORES:
2949 {
2950 scriptitem_T *si = SCRIPT_ITEM(
2951 iptr->isn_arg.loadstore.ls_sid);
2952
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01002953 smsg("%4d STORES %s in %s", current,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002954 iptr->isn_arg.loadstore.ls_name, si->sn_name);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002955 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002956 break;
2957 case ISN_STORESCRIPT:
2958 {
2959 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002960 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002961 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
2962 + iptr->isn_arg.script.script_idx;
2963
2964 smsg("%4d STORESCRIPT %s in %s", current,
2965 sv->sv_name, si->sn_name);
2966 }
2967 break;
2968 case ISN_STOREOPT:
2969 smsg("%4d STOREOPT &%s", current,
2970 iptr->isn_arg.storeopt.so_name);
2971 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002972 case ISN_STOREENV:
2973 smsg("%4d STOREENV $%s", current, iptr->isn_arg.string);
2974 break;
2975 case ISN_STOREREG:
Bram Moolenaar10827722020-03-23 22:53:22 +01002976 smsg("%4d STOREREG @%c", current, (int)iptr->isn_arg.number);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002977 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002978 case ISN_STORENR:
2979 smsg("%4d STORE %lld in $%d", current,
Bram Moolenaara471eea2020-03-04 22:20:26 +01002980 iptr->isn_arg.storenr.stnr_val,
2981 iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002982 break;
2983
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002984 case ISN_STORELIST:
2985 smsg("%4d STORELIST", current);
2986 break;
2987
2988 case ISN_STOREDICT:
2989 smsg("%4d STOREDICT", current);
2990 break;
2991
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002992 // constants
2993 case ISN_PUSHNR:
Bram Moolenaar10827722020-03-23 22:53:22 +01002994 smsg("%4d PUSHNR %lld", current,
2995 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002996 break;
2997 case ISN_PUSHBOOL:
2998 case ISN_PUSHSPEC:
2999 smsg("%4d PUSH %s", current,
3000 get_var_special_name(iptr->isn_arg.number));
3001 break;
3002 case ISN_PUSHF:
Bram Moolenaara5d59532020-01-26 21:42:03 +01003003#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003004 smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber);
Bram Moolenaara5d59532020-01-26 21:42:03 +01003005#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003006 break;
3007 case ISN_PUSHS:
3008 smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string);
3009 break;
3010 case ISN_PUSHBLOB:
3011 {
3012 char_u *r;
3013 char_u numbuf[NUMBUFLEN];
3014 char_u *tofree;
3015
3016 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01003017 smsg("%4d PUSHBLOB %s", current, r);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003018 vim_free(tofree);
3019 }
3020 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003021 case ISN_PUSHFUNC:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01003022 {
3023 char *name = (char *)iptr->isn_arg.string;
3024
3025 smsg("%4d PUSHFUNC \"%s\"", current,
3026 name == NULL ? "[none]" : name);
3027 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003028 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003029 case ISN_PUSHCHANNEL:
3030#ifdef FEAT_JOB_CHANNEL
3031 {
3032 channel_T *channel = iptr->isn_arg.channel;
3033
3034 smsg("%4d PUSHCHANNEL %d", current,
3035 channel == NULL ? 0 : channel->ch_id);
3036 }
3037#endif
3038 break;
3039 case ISN_PUSHJOB:
3040#ifdef FEAT_JOB_CHANNEL
3041 {
3042 typval_T tv;
3043 char_u *name;
3044
3045 tv.v_type = VAR_JOB;
3046 tv.vval.v_job = iptr->isn_arg.job;
3047 name = tv_get_string(&tv);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01003048 smsg("%4d PUSHJOB \"%s\"", current, name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003049 }
3050#endif
3051 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003052 case ISN_PUSHEXC:
3053 smsg("%4d PUSH v:exception", current);
3054 break;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02003055 case ISN_UNLET:
3056 smsg("%4d UNLET%s %s", current,
3057 iptr->isn_arg.unlet.ul_forceit ? "!" : "",
3058 iptr->isn_arg.unlet.ul_name);
3059 break;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02003060 case ISN_UNLETENV:
3061 smsg("%4d UNLETENV%s $%s", current,
3062 iptr->isn_arg.unlet.ul_forceit ? "!" : "",
3063 iptr->isn_arg.unlet.ul_name);
3064 break;
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02003065 case ISN_LOCKCONST:
3066 smsg("%4d LOCKCONST", current);
3067 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003068 case ISN_NEWLIST:
Bram Moolenaar10827722020-03-23 22:53:22 +01003069 smsg("%4d NEWLIST size %lld", current,
3070 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003071 break;
3072 case ISN_NEWDICT:
Bram Moolenaar10827722020-03-23 22:53:22 +01003073 smsg("%4d NEWDICT size %lld", current,
3074 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003075 break;
3076
3077 // function call
3078 case ISN_BCALL:
3079 {
3080 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc;
3081
3082 smsg("%4d BCALL %s(argc %d)", current,
3083 internal_func_name(cbfunc->cbf_idx),
3084 cbfunc->cbf_argcount);
3085 }
3086 break;
3087 case ISN_DCALL:
3088 {
3089 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc;
3090 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
3091 + cdfunc->cdf_idx;
3092
3093 smsg("%4d DCALL %s(argc %d)", current,
3094 df->df_ufunc->uf_name_exp != NULL
3095 ? df->df_ufunc->uf_name_exp
3096 : df->df_ufunc->uf_name, cdfunc->cdf_argcount);
3097 }
3098 break;
3099 case ISN_UCALL:
3100 {
3101 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
3102
3103 smsg("%4d UCALL %s(argc %d)", current,
3104 cufunc->cuf_name, cufunc->cuf_argcount);
3105 }
3106 break;
3107 case ISN_PCALL:
3108 {
3109 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc;
3110
3111 smsg("%4d PCALL%s (argc %d)", current,
3112 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
3113 }
3114 break;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02003115 case ISN_PCALL_END:
3116 smsg("%4d PCALL end", current);
3117 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003118 case ISN_RETURN:
3119 smsg("%4d RETURN", current);
3120 break;
3121 case ISN_FUNCREF:
3122 {
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02003123 funcref_T *funcref = &iptr->isn_arg.funcref;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003124 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02003125 + funcref->fr_func;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003126
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02003127 smsg("%4d FUNCREF %s $%d", current, df->df_ufunc->uf_name,
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02003128 funcref->fr_var_idx + dfunc->df_varcount);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003129 }
3130 break;
3131
Bram Moolenaar38ddf332020-07-31 22:05:04 +02003132 case ISN_NEWFUNC:
3133 {
3134 newfunc_T *newfunc = &iptr->isn_arg.newfunc;
3135
3136 smsg("%4d NEWFUNC %s %s", current,
3137 newfunc->nf_lambda, newfunc->nf_global);
3138 }
3139 break;
3140
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003141 case ISN_JUMP:
3142 {
3143 char *when = "?";
3144
3145 switch (iptr->isn_arg.jump.jump_when)
3146 {
3147 case JUMP_ALWAYS:
3148 when = "JUMP";
3149 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003150 case JUMP_AND_KEEP_IF_TRUE:
3151 when = "JUMP_AND_KEEP_IF_TRUE";
3152 break;
3153 case JUMP_IF_FALSE:
3154 when = "JUMP_IF_FALSE";
3155 break;
3156 case JUMP_AND_KEEP_IF_FALSE:
3157 when = "JUMP_AND_KEEP_IF_FALSE";
3158 break;
3159 }
Bram Moolenaar8a677a32020-03-12 19:15:45 +01003160 smsg("%4d %s -> %d", current, when,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003161 iptr->isn_arg.jump.jump_where);
3162 }
3163 break;
3164
3165 case ISN_FOR:
3166 {
3167 forloop_T *forloop = &iptr->isn_arg.forloop;
3168
3169 smsg("%4d FOR $%d -> %d", current,
3170 forloop->for_idx, forloop->for_end);
3171 }
3172 break;
3173
3174 case ISN_TRY:
3175 {
3176 try_T *try = &iptr->isn_arg.try;
3177
3178 smsg("%4d TRY catch -> %d, finally -> %d", current,
3179 try->try_catch, try->try_finally);
3180 }
3181 break;
3182 case ISN_CATCH:
3183 // TODO
3184 smsg("%4d CATCH", current);
3185 break;
3186 case ISN_ENDTRY:
3187 smsg("%4d ENDTRY", current);
3188 break;
3189 case ISN_THROW:
3190 smsg("%4d THROW", current);
3191 break;
3192
3193 // expression operations on number
3194 case ISN_OPNR:
3195 case ISN_OPFLOAT:
3196 case ISN_OPANY:
3197 {
3198 char *what;
3199 char *ins;
3200
3201 switch (iptr->isn_arg.op.op_type)
3202 {
3203 case EXPR_MULT: what = "*"; break;
3204 case EXPR_DIV: what = "/"; break;
3205 case EXPR_REM: what = "%"; break;
3206 case EXPR_SUB: what = "-"; break;
3207 case EXPR_ADD: what = "+"; break;
3208 default: what = "???"; break;
3209 }
3210 switch (iptr->isn_type)
3211 {
3212 case ISN_OPNR: ins = "OPNR"; break;
3213 case ISN_OPFLOAT: ins = "OPFLOAT"; break;
3214 case ISN_OPANY: ins = "OPANY"; break;
3215 default: ins = "???"; break;
3216 }
3217 smsg("%4d %s %s", current, ins, what);
3218 }
3219 break;
3220
3221 case ISN_COMPAREBOOL:
3222 case ISN_COMPARESPECIAL:
3223 case ISN_COMPARENR:
3224 case ISN_COMPAREFLOAT:
3225 case ISN_COMPARESTRING:
3226 case ISN_COMPAREBLOB:
3227 case ISN_COMPARELIST:
3228 case ISN_COMPAREDICT:
3229 case ISN_COMPAREFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003230 case ISN_COMPAREANY:
3231 {
3232 char *p;
3233 char buf[10];
3234 char *type;
3235
3236 switch (iptr->isn_arg.op.op_type)
3237 {
3238 case EXPR_EQUAL: p = "=="; break;
3239 case EXPR_NEQUAL: p = "!="; break;
3240 case EXPR_GREATER: p = ">"; break;
3241 case EXPR_GEQUAL: p = ">="; break;
3242 case EXPR_SMALLER: p = "<"; break;
3243 case EXPR_SEQUAL: p = "<="; break;
3244 case EXPR_MATCH: p = "=~"; break;
3245 case EXPR_IS: p = "is"; break;
3246 case EXPR_ISNOT: p = "isnot"; break;
3247 case EXPR_NOMATCH: p = "!~"; break;
3248 default: p = "???"; break;
3249 }
3250 STRCPY(buf, p);
3251 if (iptr->isn_arg.op.op_ic == TRUE)
3252 strcat(buf, "?");
3253 switch(iptr->isn_type)
3254 {
3255 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
3256 case ISN_COMPARESPECIAL:
3257 type = "COMPARESPECIAL"; break;
3258 case ISN_COMPARENR: type = "COMPARENR"; break;
3259 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
3260 case ISN_COMPARESTRING:
3261 type = "COMPARESTRING"; break;
3262 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
3263 case ISN_COMPARELIST: type = "COMPARELIST"; break;
3264 case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
3265 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003266 case ISN_COMPAREANY: type = "COMPAREANY"; break;
3267 default: type = "???"; break;
3268 }
3269
3270 smsg("%4d %s %s", current, type, buf);
3271 }
3272 break;
3273
3274 case ISN_ADDLIST: smsg("%4d ADDLIST", current); break;
3275 case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break;
3276
3277 // expression operations
3278 case ISN_CONCAT: smsg("%4d CONCAT", current); break;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003279 case ISN_STRINDEX: smsg("%4d STRINDEX", current); break;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02003280 case ISN_STRSLICE: smsg("%4d STRSLICE", current); break;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003281 case ISN_LISTINDEX: smsg("%4d LISTINDEX", current); break;
Bram Moolenaared591872020-08-15 22:14:53 +02003282 case ISN_LISTSLICE: smsg("%4d LISTSLICE", current); break;
Bram Moolenaarcc673e72020-08-16 17:33:35 +02003283 case ISN_ANYINDEX: smsg("%4d ANYINDEX", current); break;
3284 case ISN_ANYSLICE: smsg("%4d ANYSLICE", current); break;
Bram Moolenaar9af78762020-06-16 11:34:42 +02003285 case ISN_SLICE: smsg("%4d SLICE %lld",
3286 current, iptr->isn_arg.number); break;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02003287 case ISN_GETITEM: smsg("%4d ITEM %lld",
3288 current, iptr->isn_arg.number); break;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003289 case ISN_MEMBER: smsg("%4d MEMBER", current); break;
3290 case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003291 iptr->isn_arg.string); break;
3292 case ISN_NEGATENR: smsg("%4d NEGATENR", current); break;
3293
3294 case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
Bram Moolenaar5e654232020-09-16 15:22:00 +02003295 case ISN_CHECKTYPE:
3296 {
3297 char *tofree;
3298
3299 smsg("%4d CHECKTYPE %s stack[%d]", current,
3300 type_name(iptr->isn_arg.type.ct_type, &tofree),
3301 iptr->isn_arg.type.ct_off);
3302 vim_free(tofree);
3303 break;
3304 }
Bram Moolenaar9af78762020-06-16 11:34:42 +02003305 case ISN_CHECKLEN: smsg("%4d CHECKLEN %s%d", current,
3306 iptr->isn_arg.checklen.cl_more_OK ? ">= " : "",
3307 iptr->isn_arg.checklen.cl_min_len);
3308 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003309 case ISN_2BOOL: if (iptr->isn_arg.number)
3310 smsg("%4d INVERT (!val)", current);
3311 else
3312 smsg("%4d 2BOOL (!!val)", current);
3313 break;
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01003314 case ISN_2STRING: smsg("%4d 2STRING stack[%lld]", current,
3315 (long long)(iptr->isn_arg.number));
Bram Moolenaar389df252020-07-09 21:20:47 +02003316 break;
Bram Moolenaar418f1df2020-08-12 21:34:49 +02003317 case ISN_2STRING_ANY: smsg("%4d 2STRING_ANY stack[%lld]", current,
3318 (long long)(iptr->isn_arg.number));
3319 break;
Bram Moolenaarc3516f72020-09-08 22:45:35 +02003320 case ISN_PUT:
3321 smsg("%4d PUT %c %ld", current, iptr->isn_arg.put.put_regname,
3322 (long)iptr->isn_arg.put.put_lnum);
3323 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003324
Bram Moolenaar389df252020-07-09 21:20:47 +02003325 case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current,
3326 iptr->isn_arg.shuffle.shfl_item,
3327 iptr->isn_arg.shuffle.shfl_up);
3328 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003329 case ISN_DROP: smsg("%4d DROP", current); break;
3330 }
Bram Moolenaar793dcc52020-08-15 13:49:17 +02003331
3332 out_flush(); // output one line at a time
3333 ui_breakcheck();
3334 if (got_int)
3335 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003336 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003337}
3338
3339/*
3340 * Return TRUE when "tv" is not falsey: non-zero, non-empty string, non-empty
3341 * list, etc. Mostly like what JavaScript does, except that empty list and
3342 * empty dictionary are FALSE.
3343 */
3344 int
3345tv2bool(typval_T *tv)
3346{
3347 switch (tv->v_type)
3348 {
3349 case VAR_NUMBER:
3350 return tv->vval.v_number != 0;
3351 case VAR_FLOAT:
3352#ifdef FEAT_FLOAT
3353 return tv->vval.v_float != 0.0;
3354#else
3355 break;
3356#endif
3357 case VAR_PARTIAL:
3358 return tv->vval.v_partial != NULL;
3359 case VAR_FUNC:
3360 case VAR_STRING:
3361 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
3362 case VAR_LIST:
3363 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
3364 case VAR_DICT:
3365 return tv->vval.v_dict != NULL
3366 && tv->vval.v_dict->dv_hashtab.ht_used > 0;
3367 case VAR_BOOL:
3368 case VAR_SPECIAL:
3369 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
3370 case VAR_JOB:
3371#ifdef FEAT_JOB_CHANNEL
3372 return tv->vval.v_job != NULL;
3373#else
3374 break;
3375#endif
3376 case VAR_CHANNEL:
3377#ifdef FEAT_JOB_CHANNEL
3378 return tv->vval.v_channel != NULL;
3379#else
3380 break;
3381#endif
3382 case VAR_BLOB:
3383 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
3384 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02003385 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003386 case VAR_VOID:
3387 break;
3388 }
3389 return FALSE;
3390}
3391
3392/*
3393 * If "tv" is a string give an error and return FAIL.
3394 */
3395 int
3396check_not_string(typval_T *tv)
3397{
3398 if (tv->v_type == VAR_STRING)
3399 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003400 emsg(_(e_using_string_as_number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003401 clear_tv(tv);
3402 return FAIL;
3403 }
3404 return OK;
3405}
3406
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003407
3408#endif // FEAT_EVAL