blob: 9f829d69fbfa0cad3a8f31984c4aea18a8e59041 [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 {
27 int tcd_frame; // ec_frame when ISN_TRY was encountered
28 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
59 int ec_frame; // index in ec_stack: context of ec_dfunc_idx
60
61 garray_T ec_trystack; // stack of trycmd_T values
62 int ec_in_catch; // when TRUE in catch or finally block
63
64 int ec_dfunc_idx; // current function index
65 isn_T *ec_instr; // array with instructions
66 int ec_iidx; // index in ec_instr: instruction to execute
67} ectx_T;
68
69// Get pointer to item relative to the bottom of the stack, -1 is the last one.
70#define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx)
71
72/*
Bram Moolenaar170fcfc2020-02-06 17:51:35 +010073 * Return the number of arguments, including optional arguments and any vararg.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010074 */
75 static int
76ufunc_argcount(ufunc_T *ufunc)
77{
78 return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0);
79}
80
81/*
Bram Moolenaar170fcfc2020-02-06 17:51:35 +010082 * Set the instruction index, depending on omitted arguments, where the default
83 * values are to be computed. If all optional arguments are present, start
84 * with the function body.
85 * The expression evaluation is at the start of the instructions:
86 * 0 -> EVAL default1
87 * STORE arg[-2]
88 * 1 -> EVAL default2
89 * STORE arg[-1]
90 * 2 -> function body
91 */
92 static void
93init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx)
94{
95 if (ufunc->uf_def_args.ga_len == 0)
96 ectx->ec_iidx = 0;
97 else
98 {
99 int defcount = ufunc->uf_args.ga_len - argcount;
100
101 // If there is a varargs argument defcount can be negative, no defaults
102 // to evaluate then.
103 if (defcount < 0)
104 defcount = 0;
105 ectx->ec_iidx = ufunc->uf_def_arg_idx[
106 ufunc->uf_def_args.ga_len - defcount];
107 }
108}
109
110/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100111 * Call compiled function "cdf_idx" from compiled code.
112 *
113 * Stack has:
114 * - current arguments (already there)
115 * - omitted optional argument (default values) added here
116 * - stack frame:
117 * - pointer to calling function
118 * - Index of next instruction in calling function
119 * - previous frame pointer
120 * - reserved space for local variables
121 */
122 static int
123call_dfunc(int cdf_idx, int argcount, ectx_T *ectx)
124{
125 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
126 ufunc_T *ufunc = dfunc->df_ufunc;
127 int optcount = ufunc_argcount(ufunc) - argcount;
128 int idx;
129
130 if (dfunc->df_deleted)
131 {
132 emsg_funcname(e_func_deleted, ufunc->uf_name);
133 return FAIL;
134 }
135
136 if (ga_grow(&ectx->ec_stack, optcount + 3 + dfunc->df_varcount) == FAIL)
137 return FAIL;
138
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100139 if (optcount < 0)
140 {
141 emsg("argument count wrong?");
142 return FAIL;
143 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100144
145 // Reserve space for omitted optional arguments, filled in soon.
146 // Also any empty varargs argument.
147 ectx->ec_stack.ga_len += optcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100148
149 // Store current execution state in stack frame for ISN_RETURN.
150 // TODO: If the actual number of arguments doesn't match what the called
151 // function expects things go bad.
152 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx;
153 STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx;
154 STACK_TV_BOT(2)->vval.v_number = ectx->ec_frame;
155 ectx->ec_frame = ectx->ec_stack.ga_len;
156
157 // Initialize local variables
158 for (idx = 0; idx < dfunc->df_varcount; ++idx)
159 STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN;
160 ectx->ec_stack.ga_len += STACK_FRAME_SIZE + dfunc->df_varcount;
161
162 // Set execution state to the start of the called function.
163 ectx->ec_dfunc_idx = cdf_idx;
164 ectx->ec_instr = dfunc->df_instr;
165 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100166
167 // Decide where to start execution, handles optional arguments.
168 init_instr_idx(ufunc, argcount, ectx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100169
170 return OK;
171}
172
173// Get pointer to item in the stack.
174#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
175
176/*
177 * Return from the current function.
178 */
179 static void
180func_return(ectx_T *ectx)
181{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100182 int idx;
183 dfunc_T *dfunc;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100184 int top;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100185
186 // execution context goes one level up
187 estack_pop();
188
189 // Clear the local variables and temporary values, but not
190 // the return value.
191 for (idx = ectx->ec_frame + STACK_FRAME_SIZE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100192 idx < ectx->ec_stack.ga_len - 1; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100193 clear_tv(STACK_TV(idx));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100194
195 // Clear the arguments.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100196 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100197 top = ectx->ec_frame - ufunc_argcount(dfunc->df_ufunc);
198 for (idx = top; idx < ectx->ec_frame; ++idx)
199 clear_tv(STACK_TV(idx));
200
201 // Restore the previous frame.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100202 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame)->vval.v_number;
203 ectx->ec_iidx = STACK_TV(ectx->ec_frame + 1)->vval.v_number;
204 ectx->ec_frame = STACK_TV(ectx->ec_frame + 2)->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100205 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
206 ectx->ec_instr = dfunc->df_instr;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100207
208 // Reset the stack to the position before the call, move the return value
209 // to the top of the stack.
210 idx = ectx->ec_stack.ga_len - 1;
211 ectx->ec_stack.ga_len = top + 1;
212 *STACK_TV_BOT(-1) = *STACK_TV(idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100213}
214
215#undef STACK_TV
216
217/*
218 * Prepare arguments and rettv for calling a builtin or user function.
219 */
220 static int
221call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
222{
223 int idx;
224 typval_T *tv;
225
226 // Move arguments from bottom of the stack to argvars[] and add terminator.
227 for (idx = 0; idx < argcount; ++idx)
228 argvars[idx] = *STACK_TV_BOT(idx - argcount);
229 argvars[argcount].v_type = VAR_UNKNOWN;
230
231 // Result replaces the arguments on the stack.
232 if (argcount > 0)
233 ectx->ec_stack.ga_len -= argcount - 1;
234 else if (ga_grow(&ectx->ec_stack, 1) == FAIL)
235 return FAIL;
236 else
237 ++ectx->ec_stack.ga_len;
238
239 // Default return value is zero.
240 tv = STACK_TV_BOT(-1);
241 tv->v_type = VAR_NUMBER;
242 tv->vval.v_number = 0;
243
244 return OK;
245}
246
247/*
248 * Call a builtin function by index.
249 */
250 static int
251call_bfunc(int func_idx, int argcount, ectx_T *ectx)
252{
253 typval_T argvars[MAX_FUNC_ARGS];
254 int idx;
255
256 if (call_prepare(argcount, argvars, ectx) == FAIL)
257 return FAIL;
258
259 // Call the builtin function.
260 call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1));
261
262 // Clear the arguments.
263 for (idx = 0; idx < argcount; ++idx)
264 clear_tv(&argvars[idx]);
265 return OK;
266}
267
268/*
269 * Execute a user defined function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100270 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 */
272 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100273call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100274{
275 typval_T argvars[MAX_FUNC_ARGS];
276 funcexe_T funcexe;
277 int error;
278 int idx;
279
280 if (ufunc->uf_dfunc_idx >= 0)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100281 {
282 // The function has been compiled, can call it quickly. For a function
283 // that was defined later: we can call it directly next time.
284 if (iptr != NULL)
285 {
Bram Moolenaar20431c92020-03-20 18:39:46 +0100286 delete_instr(iptr);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100287 iptr->isn_type = ISN_DCALL;
288 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
289 iptr->isn_arg.dfunc.cdf_argcount = argcount;
290 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100291 return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100292 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100293
294 if (call_prepare(argcount, argvars, ectx) == FAIL)
295 return FAIL;
296 vim_memset(&funcexe, 0, sizeof(funcexe));
297 funcexe.evaluate = TRUE;
298
299 // Call the user function. Result goes in last position on the stack.
300 // TODO: add selfdict if there is one
301 error = call_user_func_check(ufunc, argcount, argvars,
302 STACK_TV_BOT(-1), &funcexe, NULL);
303
304 // Clear the arguments.
305 for (idx = 0; idx < argcount; ++idx)
306 clear_tv(&argvars[idx]);
307
308 if (error != FCERR_NONE)
309 {
310 user_func_error(error, ufunc->uf_name);
311 return FAIL;
312 }
313 return OK;
314}
315
316/*
317 * Execute a function by "name".
318 * This can be a builtin function or a user function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100319 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100320 * Returns FAIL if not found without an error message.
321 */
322 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100323call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100324{
325 ufunc_T *ufunc;
326
327 if (builtin_function(name, -1))
328 {
329 int func_idx = find_internal_func(name);
330
331 if (func_idx < 0)
332 return FAIL;
333 if (check_internal_func(func_idx, argcount) == FAIL)
334 return FAIL;
335 return call_bfunc(func_idx, argcount, ectx);
336 }
337
338 ufunc = find_func(name, NULL);
339 if (ufunc != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100340 return call_ufunc(ufunc, argcount, ectx, iptr);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100341
342 return FAIL;
343}
344
345 static int
346call_partial(typval_T *tv, int argcount, ectx_T *ectx)
347{
348 char_u *name;
349 int called_emsg_before = called_emsg;
350
351 if (tv->v_type == VAR_PARTIAL)
352 {
353 partial_T *pt = tv->vval.v_partial;
354
355 if (pt->pt_func != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100356 return call_ufunc(pt->pt_func, argcount, ectx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100357 name = pt->pt_name;
358 }
359 else
360 name = tv->vval.v_string;
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100361 if (call_by_name(name, argcount, ectx, NULL) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100362 {
363 if (called_emsg == called_emsg_before)
364 semsg(_(e_unknownfunc), name);
365 return FAIL;
366 }
367 return OK;
368}
369
370/*
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100371 * Store "tv" in variable "name".
372 * This is for s: and g: variables.
373 */
374 static void
375store_var(char_u *name, typval_T *tv)
376{
377 funccal_entry_T entry;
378
379 save_funccal(&entry);
380 set_var_const(name, NULL, tv, FALSE, 0);
381 restore_funccal();
382}
383
384/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100385 * Execute a function by "name".
386 * This can be a builtin function, user function or a funcref.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100387 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100388 */
389 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100390call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100391{
392 int called_emsg_before = called_emsg;
393
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100394 if (call_by_name(name, argcount, ectx, iptr) == FAIL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100395 && called_emsg == called_emsg_before)
396 {
397 // "name" may be a variable that is a funcref or partial
398 // if find variable
399 // call_partial()
400 // else
401 // semsg(_(e_unknownfunc), name);
402 emsg("call_eval_func(partial) not implemented yet");
403 return FAIL;
404 }
405 return OK;
406}
407
408/*
409 * Call a "def" function from old Vim script.
410 * Return OK or FAIL.
411 */
412 int
413call_def_function(
414 ufunc_T *ufunc,
415 int argc, // nr of arguments
416 typval_T *argv, // arguments
417 typval_T *rettv) // return value
418{
419 ectx_T ectx; // execution context
420 int initial_frame_ptr;
421 typval_T *tv;
422 int idx;
423 int ret = FAIL;
424 dfunc_T *dfunc;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100425 int defcount = ufunc->uf_args.ga_len - argc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100426
427// Get pointer to item in the stack.
428#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
429
430// Get pointer to item at the bottom of the stack, -1 is the bottom.
431#undef STACK_TV_BOT
432#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
433
434// Get pointer to local variable on the stack.
435#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame + STACK_FRAME_SIZE + idx)
436
437 vim_memset(&ectx, 0, sizeof(ectx));
438 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
439 if (ga_grow(&ectx.ec_stack, 20) == FAIL)
Bram Moolenaard5aec0c2020-02-27 21:48:51 +0100440 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100441 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
442
443 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
444
445 // Put arguments on the stack.
446 for (idx = 0; idx < argc; ++idx)
447 {
448 copy_tv(&argv[idx], STACK_TV_BOT(0));
449 ++ectx.ec_stack.ga_len;
450 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100451 // Make space for omitted arguments, will store default value below.
452 if (defcount > 0)
453 for (idx = 0; idx < defcount; ++idx)
454 {
455 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
456 ++ectx.ec_stack.ga_len;
457 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100458
459 // Frame pointer points to just after arguments.
460 ectx.ec_frame = ectx.ec_stack.ga_len;
461 initial_frame_ptr = ectx.ec_frame;
462
463 // dummy frame entries
464 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
465 {
466 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
467 ++ectx.ec_stack.ga_len;
468 }
469
470 // Reserve space for local variables.
471 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
472 for (idx = 0; idx < dfunc->df_varcount; ++idx)
473 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
474 ectx.ec_stack.ga_len += dfunc->df_varcount;
475
476 ectx.ec_instr = dfunc->df_instr;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100477
478 // Decide where to start execution, handles optional arguments.
479 init_instr_idx(ufunc, argc, &ectx);
480
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100481 for (;;)
482 {
483 isn_T *iptr;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100484
485 veryfast_breakcheck();
486 if (got_int)
487 {
488 // Turn CTRL-C into an exception.
489 got_int = FALSE;
Bram Moolenaar97acfc72020-03-22 13:44:28 +0100490 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
Bram Moolenaar20431c92020-03-20 18:39:46 +0100491 goto failed;
492 did_throw = TRUE;
493 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100494
495 if (did_throw && !ectx.ec_in_catch)
496 {
497 garray_T *trystack = &ectx.ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100498 trycmd_T *trycmd = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100499
500 // An exception jumps to the first catch, finally, or returns from
501 // the current function.
502 if (trystack->ga_len > 0)
503 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1;
504 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame)
505 {
506 // jump to ":catch" or ":finally"
507 ectx.ec_in_catch = TRUE;
508 ectx.ec_iidx = trycmd->tcd_catch_idx;
509 }
510 else
511 {
512 // not inside try or need to return from current functions.
513 if (ectx.ec_frame == initial_frame_ptr)
514 {
515 // At the toplevel we are done. Push a dummy return value.
516 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
517 goto failed;
518 tv = STACK_TV_BOT(0);
519 tv->v_type = VAR_NUMBER;
520 tv->vval.v_number = 0;
521 ++ectx.ec_stack.ga_len;
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100522 need_rethrow = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100523 goto done;
524 }
525
526 func_return(&ectx);
527 }
528 continue;
529 }
530
531 iptr = &ectx.ec_instr[ectx.ec_iidx++];
532 switch (iptr->isn_type)
533 {
534 // execute Ex command line
535 case ISN_EXEC:
536 do_cmdline_cmd(iptr->isn_arg.string);
537 break;
538
539 // execute :echo {string} ...
540 case ISN_ECHO:
541 {
542 int count = iptr->isn_arg.echo.echo_count;
543 int atstart = TRUE;
544 int needclr = TRUE;
545
546 for (idx = 0; idx < count; ++idx)
547 {
548 tv = STACK_TV_BOT(idx - count);
549 echo_one(tv, iptr->isn_arg.echo.echo_with_white,
550 &atstart, &needclr);
551 clear_tv(tv);
552 }
Bram Moolenaare0807ea2020-02-20 22:18:06 +0100553 if (needclr)
554 msg_clr_eos();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100555 ectx.ec_stack.ga_len -= count;
556 }
557 break;
558
Bram Moolenaarad39c092020-02-26 18:23:43 +0100559 // execute :execute {string} ...
560 case ISN_EXECUTE:
561 {
562 int count = iptr->isn_arg.number;
563 garray_T ga;
564 char_u buf[NUMBUFLEN];
565 char_u *p;
566 int len;
567 int failed = FALSE;
568
569 ga_init2(&ga, 1, 80);
570 for (idx = 0; idx < count; ++idx)
571 {
572 tv = STACK_TV_BOT(idx - count);
573 if (tv->v_type == VAR_CHANNEL || tv->v_type == VAR_JOB)
574 {
575 emsg(_(e_inval_string));
576 break;
577 }
578 else
579 p = tv_get_string_buf(tv, buf);
580
581 len = (int)STRLEN(p);
582 if (ga_grow(&ga, len + 2) == FAIL)
583 failed = TRUE;
584 else
585 {
586 if (ga.ga_len > 0)
587 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
588 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
589 ga.ga_len += len;
590 }
591 clear_tv(tv);
592 }
593 ectx.ec_stack.ga_len -= count;
594
595 if (!failed && ga.ga_data != NULL)
596 do_cmdline_cmd((char_u *)ga.ga_data);
597 ga_clear(&ga);
598 }
599 break;
600
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100601 // load local variable or argument
602 case ISN_LOAD:
603 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
604 goto failed;
605 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
606 ++ectx.ec_stack.ga_len;
607 break;
608
609 // load v: variable
610 case ISN_LOADV:
611 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
612 goto failed;
613 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
614 ++ectx.ec_stack.ga_len;
615 break;
616
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100617 // load s: variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100618 case ISN_LOADSCRIPT:
619 {
620 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +0100621 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100622 svar_T *sv;
623
624 sv = ((svar_T *)si->sn_var_vals.ga_data)
625 + iptr->isn_arg.script.script_idx;
626 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
627 goto failed;
628 copy_tv(sv->sv_tv, STACK_TV_BOT(0));
629 ++ectx.ec_stack.ga_len;
630 }
631 break;
632
633 // load s: variable in old script
634 case ISN_LOADS:
635 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100636 hashtab_T *ht = &SCRIPT_VARS(
637 iptr->isn_arg.loadstore.ls_sid);
638 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100639 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100640
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100641 if (di == NULL)
642 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100643 semsg(_(e_undefvar), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100644 goto failed;
645 }
646 else
647 {
648 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
649 goto failed;
650 copy_tv(&di->di_tv, STACK_TV_BOT(0));
651 ++ectx.ec_stack.ga_len;
652 }
653 }
654 break;
655
656 // load g: variable
657 case ISN_LOADG:
658 {
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100659 dictitem_T *di = find_var_in_ht(get_globvar_ht(), 0,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100660 iptr->isn_arg.string, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100661
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100662 if (di == NULL)
663 {
664 semsg(_("E121: Undefined variable: g:%s"),
665 iptr->isn_arg.string);
666 goto failed;
667 }
668 else
669 {
670 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
671 goto failed;
672 copy_tv(&di->di_tv, STACK_TV_BOT(0));
673 ++ectx.ec_stack.ga_len;
674 }
675 }
676 break;
677
678 // load &option
679 case ISN_LOADOPT:
680 {
681 typval_T optval;
682 char_u *name = iptr->isn_arg.string;
683
684 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
685 goto failed;
Bram Moolenaar58ceca52020-01-28 22:46:22 +0100686 if (get_option_tv(&name, &optval, TRUE) == FAIL)
687 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100688 *STACK_TV_BOT(0) = optval;
689 ++ectx.ec_stack.ga_len;
690 }
691 break;
692
693 // load $ENV
694 case ISN_LOADENV:
695 {
696 typval_T optval;
697 char_u *name = iptr->isn_arg.string;
698
699 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
700 goto failed;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100701 // name is always valid, checked when compiling
702 (void)get_env_tv(&name, &optval, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100703 *STACK_TV_BOT(0) = optval;
704 ++ectx.ec_stack.ga_len;
705 }
706 break;
707
708 // load @register
709 case ISN_LOADREG:
710 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
711 goto failed;
712 tv = STACK_TV_BOT(0);
713 tv->v_type = VAR_STRING;
714 tv->vval.v_string = get_reg_contents(
715 iptr->isn_arg.number, GREG_EXPR_SRC);
716 ++ectx.ec_stack.ga_len;
717 break;
718
719 // store local variable
720 case ISN_STORE:
721 --ectx.ec_stack.ga_len;
722 tv = STACK_TV_VAR(iptr->isn_arg.number);
723 clear_tv(tv);
724 *tv = *STACK_TV_BOT(0);
725 break;
726
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100727 // store s: variable in old script
728 case ISN_STORES:
729 {
730 hashtab_T *ht = &SCRIPT_VARS(
731 iptr->isn_arg.loadstore.ls_sid);
732 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100733 dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100734
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100735 --ectx.ec_stack.ga_len;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100736 if (di == NULL)
737 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
738 else
739 {
740 clear_tv(&di->di_tv);
741 di->di_tv = *STACK_TV_BOT(0);
742 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100743 }
744 break;
745
746 // store script-local variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100747 case ISN_STORESCRIPT:
748 {
Bram Moolenaar21b9e972020-01-26 19:26:46 +0100749 scriptitem_T *si = SCRIPT_ITEM(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100750 iptr->isn_arg.script.script_sid);
751 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
752 + iptr->isn_arg.script.script_idx;
753
754 --ectx.ec_stack.ga_len;
755 clear_tv(sv->sv_tv);
756 *sv->sv_tv = *STACK_TV_BOT(0);
757 }
758 break;
759
760 // store option
761 case ISN_STOREOPT:
762 {
763 long n = 0;
764 char_u *s = NULL;
765 char *msg;
766
767 --ectx.ec_stack.ga_len;
768 tv = STACK_TV_BOT(0);
769 if (tv->v_type == VAR_STRING)
Bram Moolenaar97a2af32020-01-28 22:52:48 +0100770 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100771 s = tv->vval.v_string;
Bram Moolenaar97a2af32020-01-28 22:52:48 +0100772 if (s == NULL)
773 s = (char_u *)"";
774 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100775 else if (tv->v_type == VAR_NUMBER)
776 n = tv->vval.v_number;
777 else
778 {
779 emsg(_("E1051: Expected string or number"));
780 goto failed;
781 }
782 msg = set_option_value(iptr->isn_arg.storeopt.so_name,
783 n, s, iptr->isn_arg.storeopt.so_flags);
784 if (msg != NULL)
785 {
786 emsg(_(msg));
787 goto failed;
788 }
789 clear_tv(tv);
790 }
791 break;
792
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100793 // store $ENV
794 case ISN_STOREENV:
795 --ectx.ec_stack.ga_len;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100796 tv = STACK_TV_BOT(0);
797 vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
798 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100799 break;
800
801 // store @r
802 case ISN_STOREREG:
803 {
804 int reg = iptr->isn_arg.number;
805
806 --ectx.ec_stack.ga_len;
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100807 tv = STACK_TV_BOT(0);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100808 write_reg_contents(reg == '@' ? '"' : reg,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100809 tv_get_string(tv), -1, FALSE);
810 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100811 }
812 break;
813
814 // store v: variable
815 case ISN_STOREV:
816 --ectx.ec_stack.ga_len;
817 if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
818 == FAIL)
819 goto failed;
820 break;
821
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100822 // store g: variable
823 case ISN_STOREG:
824 {
825 dictitem_T *di;
826
827 --ectx.ec_stack.ga_len;
828 di = find_var_in_ht(get_globvar_ht(), 0,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100829 iptr->isn_arg.string + 2, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100830 if (di == NULL)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100831 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100832 else
833 {
834 clear_tv(&di->di_tv);
835 di->di_tv = *STACK_TV_BOT(0);
836 }
837 }
838 break;
839
840 // store number in local variable
841 case ISN_STORENR:
Bram Moolenaara471eea2020-03-04 22:20:26 +0100842 tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100843 clear_tv(tv);
844 tv->v_type = VAR_NUMBER;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100845 tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100846 break;
847
848 // push constant
849 case ISN_PUSHNR:
850 case ISN_PUSHBOOL:
851 case ISN_PUSHSPEC:
852 case ISN_PUSHF:
853 case ISN_PUSHS:
854 case ISN_PUSHBLOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100855 case ISN_PUSHFUNC:
856 case ISN_PUSHPARTIAL:
857 case ISN_PUSHCHANNEL:
858 case ISN_PUSHJOB:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100859 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
860 goto failed;
861 tv = STACK_TV_BOT(0);
862 ++ectx.ec_stack.ga_len;
863 switch (iptr->isn_type)
864 {
865 case ISN_PUSHNR:
866 tv->v_type = VAR_NUMBER;
867 tv->vval.v_number = iptr->isn_arg.number;
868 break;
869 case ISN_PUSHBOOL:
870 tv->v_type = VAR_BOOL;
871 tv->vval.v_number = iptr->isn_arg.number;
872 break;
873 case ISN_PUSHSPEC:
874 tv->v_type = VAR_SPECIAL;
875 tv->vval.v_number = iptr->isn_arg.number;
876 break;
877#ifdef FEAT_FLOAT
878 case ISN_PUSHF:
879 tv->v_type = VAR_FLOAT;
880 tv->vval.v_float = iptr->isn_arg.fnumber;
881 break;
882#endif
883 case ISN_PUSHBLOB:
884 blob_copy(iptr->isn_arg.blob, tv);
885 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100886 case ISN_PUSHFUNC:
887 tv->v_type = VAR_FUNC;
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100888 if (iptr->isn_arg.string == NULL)
889 tv->vval.v_string = NULL;
890 else
891 tv->vval.v_string =
892 vim_strsave(iptr->isn_arg.string);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100893 break;
894 case ISN_PUSHPARTIAL:
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100895 tv->v_type = VAR_PARTIAL;
896 tv->vval.v_partial = iptr->isn_arg.partial;
897 if (tv->vval.v_partial != NULL)
898 ++tv->vval.v_partial->pt_refcount;
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100899 break;
900 case ISN_PUSHCHANNEL:
901#ifdef FEAT_JOB_CHANNEL
902 tv->v_type = VAR_CHANNEL;
903 tv->vval.v_channel = iptr->isn_arg.channel;
904 if (tv->vval.v_channel != NULL)
905 ++tv->vval.v_channel->ch_refcount;
906#endif
907 break;
908 case ISN_PUSHJOB:
909#ifdef FEAT_JOB_CHANNEL
910 tv->v_type = VAR_JOB;
911 tv->vval.v_job = iptr->isn_arg.job;
912 if (tv->vval.v_job != NULL)
913 ++tv->vval.v_job->jv_refcount;
914#endif
915 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100916 default:
917 tv->v_type = VAR_STRING;
918 tv->vval.v_string = vim_strsave(iptr->isn_arg.string);
919 }
920 break;
921
922 // create a list from items on the stack; uses a single allocation
923 // for the list header and the items
924 case ISN_NEWLIST:
925 {
926 int count = iptr->isn_arg.number;
927 list_T *list = list_alloc_with_items(count);
928
929 if (list == NULL)
930 goto failed;
931 for (idx = 0; idx < count; ++idx)
932 list_set_item(list, idx, STACK_TV_BOT(idx - count));
933
934 if (count > 0)
935 ectx.ec_stack.ga_len -= count - 1;
936 else if (ga_grow(&ectx.ec_stack, 1) == FAIL)
937 goto failed;
938 else
939 ++ectx.ec_stack.ga_len;
940 tv = STACK_TV_BOT(-1);
941 tv->v_type = VAR_LIST;
942 tv->vval.v_list = list;
943 ++list->lv_refcount;
944 }
945 break;
946
947 // create a dict from items on the stack
948 case ISN_NEWDICT:
949 {
950 int count = iptr->isn_arg.number;
951 dict_T *dict = dict_alloc();
952 dictitem_T *item;
953
954 if (dict == NULL)
955 goto failed;
956 for (idx = 0; idx < count; ++idx)
957 {
958 // check key type is VAR_STRING
959 tv = STACK_TV_BOT(2 * (idx - count));
960 item = dictitem_alloc(tv->vval.v_string);
961 clear_tv(tv);
962 if (item == NULL)
963 goto failed;
964 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
965 item->di_tv.v_lock = 0;
966 if (dict_add(dict, item) == FAIL)
967 goto failed;
968 }
969
970 if (count > 0)
971 ectx.ec_stack.ga_len -= 2 * count - 1;
972 else if (ga_grow(&ectx.ec_stack, 1) == FAIL)
973 goto failed;
974 else
975 ++ectx.ec_stack.ga_len;
976 tv = STACK_TV_BOT(-1);
977 tv->v_type = VAR_DICT;
978 tv->vval.v_dict = dict;
979 ++dict->dv_refcount;
980 }
981 break;
982
983 // call a :def function
984 case ISN_DCALL:
985 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
986 iptr->isn_arg.dfunc.cdf_argcount,
987 &ectx) == FAIL)
988 goto failed;
989 break;
990
991 // call a builtin function
992 case ISN_BCALL:
993 SOURCING_LNUM = iptr->isn_lnum;
994 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
995 iptr->isn_arg.bfunc.cbf_argcount,
996 &ectx) == FAIL)
997 goto failed;
998 break;
999
1000 // call a funcref or partial
1001 case ISN_PCALL:
1002 {
1003 cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
1004 int r;
1005 typval_T partial;
1006
1007 SOURCING_LNUM = iptr->isn_lnum;
1008 if (pfunc->cpf_top)
1009 {
1010 // funcref is above the arguments
1011 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
1012 }
1013 else
1014 {
1015 // Get the funcref from the stack.
1016 --ectx.ec_stack.ga_len;
1017 partial = *STACK_TV_BOT(0);
1018 tv = &partial;
1019 }
1020 r = call_partial(tv, pfunc->cpf_argcount, &ectx);
1021 if (tv == &partial)
1022 clear_tv(&partial);
1023 if (r == FAIL)
1024 goto failed;
1025
1026 if (pfunc->cpf_top)
1027 {
1028 // Get the funcref from the stack, overwrite with the
1029 // return value.
1030 clear_tv(tv);
1031 --ectx.ec_stack.ga_len;
1032 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
1033 }
1034 }
1035 break;
1036
1037 // call a user defined function or funcref/partial
1038 case ISN_UCALL:
1039 {
1040 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
1041
1042 SOURCING_LNUM = iptr->isn_lnum;
1043 if (call_eval_func(cufunc->cuf_name,
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001044 cufunc->cuf_argcount, &ectx, iptr) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001045 goto failed;
1046 }
1047 break;
1048
1049 // return from a :def function call
1050 case ISN_RETURN:
1051 {
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001052 garray_T *trystack = &ectx.ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01001053 trycmd_T *trycmd = NULL;
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001054
1055 if (trystack->ga_len > 0)
1056 trycmd = ((trycmd_T *)trystack->ga_data)
1057 + trystack->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001058 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame
1059 && trycmd->tcd_finally_idx != 0)
1060 {
1061 // jump to ":finally"
1062 ectx.ec_iidx = trycmd->tcd_finally_idx;
1063 trycmd->tcd_return = TRUE;
1064 }
1065 else
1066 {
1067 // Restore previous function. If the frame pointer
1068 // is zero then there is none and we are done.
1069 if (ectx.ec_frame == initial_frame_ptr)
1070 goto done;
1071
1072 func_return(&ectx);
1073 }
1074 }
1075 break;
1076
1077 // push a function reference to a compiled function
1078 case ISN_FUNCREF:
1079 {
1080 partial_T *pt = NULL;
1081
1082 pt = ALLOC_CLEAR_ONE(partial_T);
1083 if (pt == NULL)
1084 goto failed;
1085 dfunc = ((dfunc_T *)def_functions.ga_data)
1086 + iptr->isn_arg.number;
1087 pt->pt_func = dfunc->df_ufunc;
1088 pt->pt_refcount = 1;
1089 ++dfunc->df_ufunc->uf_refcount;
1090
1091 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1092 goto failed;
1093 tv = STACK_TV_BOT(0);
1094 ++ectx.ec_stack.ga_len;
1095 tv->vval.v_partial = pt;
1096 tv->v_type = VAR_PARTIAL;
1097 }
1098 break;
1099
1100 // jump if a condition is met
1101 case ISN_JUMP:
1102 {
1103 jumpwhen_T when = iptr->isn_arg.jump.jump_when;
1104 int jump = TRUE;
1105
1106 if (when != JUMP_ALWAYS)
1107 {
1108 tv = STACK_TV_BOT(-1);
1109 jump = tv2bool(tv);
1110 if (when == JUMP_IF_FALSE
1111 || when == JUMP_AND_KEEP_IF_FALSE)
1112 jump = !jump;
Bram Moolenaar777770f2020-02-06 21:27:08 +01001113 if (when == JUMP_IF_FALSE || !jump)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001114 {
1115 // drop the value from the stack
1116 clear_tv(tv);
1117 --ectx.ec_stack.ga_len;
1118 }
1119 }
1120 if (jump)
1121 ectx.ec_iidx = iptr->isn_arg.jump.jump_where;
1122 }
1123 break;
1124
1125 // top of a for loop
1126 case ISN_FOR:
1127 {
1128 list_T *list = STACK_TV_BOT(-1)->vval.v_list;
1129 typval_T *idxtv =
1130 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);
1131
1132 // push the next item from the list
1133 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1134 goto failed;
1135 if (++idxtv->vval.v_number >= list->lv_len)
1136 // past the end of the list, jump to "endfor"
1137 ectx.ec_iidx = iptr->isn_arg.forloop.for_end;
1138 else if (list->lv_first == &range_list_item)
1139 {
1140 // non-materialized range() list
1141 tv = STACK_TV_BOT(0);
1142 tv->v_type = VAR_NUMBER;
1143 tv->vval.v_number = list_find_nr(
1144 list, idxtv->vval.v_number, NULL);
1145 ++ectx.ec_stack.ga_len;
1146 }
1147 else
1148 {
1149 listitem_T *li = list_find(list, idxtv->vval.v_number);
1150
1151 if (li == NULL)
1152 goto failed;
1153 copy_tv(&li->li_tv, STACK_TV_BOT(0));
1154 ++ectx.ec_stack.ga_len;
1155 }
1156 }
1157 break;
1158
1159 // start of ":try" block
1160 case ISN_TRY:
1161 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001162 trycmd_T *trycmd = NULL;
1163
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001164 if (ga_grow(&ectx.ec_trystack, 1) == FAIL)
1165 goto failed;
1166 trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data)
1167 + ectx.ec_trystack.ga_len;
1168 ++ectx.ec_trystack.ga_len;
1169 ++trylevel;
1170 trycmd->tcd_frame = ectx.ec_frame;
1171 trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch;
1172 trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001173 trycmd->tcd_caught = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001174 }
1175 break;
1176
1177 case ISN_PUSHEXC:
1178 if (current_exception == NULL)
1179 {
1180 iemsg("Evaluating catch while current_exception is NULL");
1181 goto failed;
1182 }
1183 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1184 goto failed;
1185 tv = STACK_TV_BOT(0);
1186 ++ectx.ec_stack.ga_len;
1187 tv->v_type = VAR_STRING;
1188 tv->vval.v_string = vim_strsave(
1189 (char_u *)current_exception->value);
1190 break;
1191
1192 case ISN_CATCH:
1193 {
1194 garray_T *trystack = &ectx.ec_trystack;
1195
1196 if (trystack->ga_len > 0)
1197 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001198 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001199 + trystack->ga_len - 1;
1200 trycmd->tcd_caught = TRUE;
1201 }
1202 did_emsg = got_int = did_throw = FALSE;
1203 catch_exception(current_exception);
1204 }
1205 break;
1206
1207 // end of ":try" block
1208 case ISN_ENDTRY:
1209 {
1210 garray_T *trystack = &ectx.ec_trystack;
1211
1212 if (trystack->ga_len > 0)
1213 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001214 trycmd_T *trycmd = NULL;
1215
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001216 --trystack->ga_len;
1217 --trylevel;
1218 trycmd = ((trycmd_T *)trystack->ga_data)
1219 + trystack->ga_len;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001220 if (trycmd->tcd_caught && current_exception != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001221 {
1222 // discard the exception
1223 if (caught_stack == current_exception)
1224 caught_stack = caught_stack->caught;
1225 discard_current_exception();
1226 }
1227
1228 if (trycmd->tcd_return)
1229 {
1230 // Restore previous function. If the frame pointer
1231 // is zero then there is none and we are done.
1232 if (ectx.ec_frame == initial_frame_ptr)
1233 goto done;
1234
1235 func_return(&ectx);
1236 }
1237 }
1238 }
1239 break;
1240
1241 case ISN_THROW:
1242 --ectx.ec_stack.ga_len;
1243 tv = STACK_TV_BOT(0);
1244 if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL)
1245 {
1246 vim_free(tv->vval.v_string);
1247 goto failed;
1248 }
1249 did_throw = TRUE;
1250 break;
1251
1252 // compare with special values
1253 case ISN_COMPAREBOOL:
1254 case ISN_COMPARESPECIAL:
1255 {
1256 typval_T *tv1 = STACK_TV_BOT(-2);
1257 typval_T *tv2 = STACK_TV_BOT(-1);
1258 varnumber_T arg1 = tv1->vval.v_number;
1259 varnumber_T arg2 = tv2->vval.v_number;
1260 int res;
1261
1262 switch (iptr->isn_arg.op.op_type)
1263 {
1264 case EXPR_EQUAL: res = arg1 == arg2; break;
1265 case EXPR_NEQUAL: res = arg1 != arg2; break;
1266 default: res = 0; break;
1267 }
1268
1269 --ectx.ec_stack.ga_len;
1270 tv1->v_type = VAR_BOOL;
1271 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
1272 }
1273 break;
1274
1275 // Operation with two number arguments
1276 case ISN_OPNR:
1277 case ISN_COMPARENR:
1278 {
1279 typval_T *tv1 = STACK_TV_BOT(-2);
1280 typval_T *tv2 = STACK_TV_BOT(-1);
1281 varnumber_T arg1 = tv1->vval.v_number;
1282 varnumber_T arg2 = tv2->vval.v_number;
1283 varnumber_T res;
1284
1285 switch (iptr->isn_arg.op.op_type)
1286 {
1287 case EXPR_MULT: res = arg1 * arg2; break;
1288 case EXPR_DIV: res = arg1 / arg2; break;
1289 case EXPR_REM: res = arg1 % arg2; break;
1290 case EXPR_SUB: res = arg1 - arg2; break;
1291 case EXPR_ADD: res = arg1 + arg2; break;
1292
1293 case EXPR_EQUAL: res = arg1 == arg2; break;
1294 case EXPR_NEQUAL: res = arg1 != arg2; break;
1295 case EXPR_GREATER: res = arg1 > arg2; break;
1296 case EXPR_GEQUAL: res = arg1 >= arg2; break;
1297 case EXPR_SMALLER: res = arg1 < arg2; break;
1298 case EXPR_SEQUAL: res = arg1 <= arg2; break;
1299 default: res = 0; break;
1300 }
1301
1302 --ectx.ec_stack.ga_len;
1303 if (iptr->isn_type == ISN_COMPARENR)
1304 {
1305 tv1->v_type = VAR_BOOL;
1306 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
1307 }
1308 else
1309 tv1->vval.v_number = res;
1310 }
1311 break;
1312
1313 // Computation with two float arguments
1314 case ISN_OPFLOAT:
1315 case ISN_COMPAREFLOAT:
Bram Moolenaara5d59532020-01-26 21:42:03 +01001316#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001317 {
1318 typval_T *tv1 = STACK_TV_BOT(-2);
1319 typval_T *tv2 = STACK_TV_BOT(-1);
1320 float_T arg1 = tv1->vval.v_float;
1321 float_T arg2 = tv2->vval.v_float;
1322 float_T res = 0;
1323 int cmp = FALSE;
1324
1325 switch (iptr->isn_arg.op.op_type)
1326 {
1327 case EXPR_MULT: res = arg1 * arg2; break;
1328 case EXPR_DIV: res = arg1 / arg2; break;
1329 case EXPR_SUB: res = arg1 - arg2; break;
1330 case EXPR_ADD: res = arg1 + arg2; break;
1331
1332 case EXPR_EQUAL: cmp = arg1 == arg2; break;
1333 case EXPR_NEQUAL: cmp = arg1 != arg2; break;
1334 case EXPR_GREATER: cmp = arg1 > arg2; break;
1335 case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
1336 case EXPR_SMALLER: cmp = arg1 < arg2; break;
1337 case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
1338 default: cmp = 0; break;
1339 }
1340 --ectx.ec_stack.ga_len;
1341 if (iptr->isn_type == ISN_COMPAREFLOAT)
1342 {
1343 tv1->v_type = VAR_BOOL;
1344 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1345 }
1346 else
1347 tv1->vval.v_float = res;
1348 }
Bram Moolenaara5d59532020-01-26 21:42:03 +01001349#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001350 break;
1351
1352 case ISN_COMPARELIST:
1353 {
1354 typval_T *tv1 = STACK_TV_BOT(-2);
1355 typval_T *tv2 = STACK_TV_BOT(-1);
1356 list_T *arg1 = tv1->vval.v_list;
1357 list_T *arg2 = tv2->vval.v_list;
1358 int cmp = FALSE;
1359 int ic = iptr->isn_arg.op.op_ic;
1360
1361 switch (iptr->isn_arg.op.op_type)
1362 {
1363 case EXPR_EQUAL: cmp =
1364 list_equal(arg1, arg2, ic, FALSE); break;
1365 case EXPR_NEQUAL: cmp =
1366 !list_equal(arg1, arg2, ic, FALSE); break;
1367 case EXPR_IS: cmp = arg1 == arg2; break;
1368 case EXPR_ISNOT: cmp = arg1 != arg2; break;
1369 default: cmp = 0; break;
1370 }
1371 --ectx.ec_stack.ga_len;
1372 clear_tv(tv1);
1373 clear_tv(tv2);
1374 tv1->v_type = VAR_BOOL;
1375 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1376 }
1377 break;
1378
1379 case ISN_COMPAREBLOB:
1380 {
1381 typval_T *tv1 = STACK_TV_BOT(-2);
1382 typval_T *tv2 = STACK_TV_BOT(-1);
1383 blob_T *arg1 = tv1->vval.v_blob;
1384 blob_T *arg2 = tv2->vval.v_blob;
1385 int cmp = FALSE;
1386
1387 switch (iptr->isn_arg.op.op_type)
1388 {
1389 case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break;
1390 case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break;
1391 case EXPR_IS: cmp = arg1 == arg2; break;
1392 case EXPR_ISNOT: cmp = arg1 != arg2; break;
1393 default: cmp = 0; break;
1394 }
1395 --ectx.ec_stack.ga_len;
1396 clear_tv(tv1);
1397 clear_tv(tv2);
1398 tv1->v_type = VAR_BOOL;
1399 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1400 }
1401 break;
1402
1403 // TODO: handle separately
1404 case ISN_COMPARESTRING:
1405 case ISN_COMPAREDICT:
1406 case ISN_COMPAREFUNC:
1407 case ISN_COMPAREPARTIAL:
1408 case ISN_COMPAREANY:
1409 {
1410 typval_T *tv1 = STACK_TV_BOT(-2);
1411 typval_T *tv2 = STACK_TV_BOT(-1);
1412 exptype_T exptype = iptr->isn_arg.op.op_type;
1413 int ic = iptr->isn_arg.op.op_ic;
1414
1415 typval_compare(tv1, tv2, exptype, ic);
1416 clear_tv(tv2);
1417 tv1->v_type = VAR_BOOL;
1418 tv1->vval.v_number = tv1->vval.v_number
1419 ? VVAL_TRUE : VVAL_FALSE;
1420 --ectx.ec_stack.ga_len;
1421 }
1422 break;
1423
1424 case ISN_ADDLIST:
1425 case ISN_ADDBLOB:
1426 {
1427 typval_T *tv1 = STACK_TV_BOT(-2);
1428 typval_T *tv2 = STACK_TV_BOT(-1);
1429
1430 if (iptr->isn_type == ISN_ADDLIST)
1431 eval_addlist(tv1, tv2);
1432 else
1433 eval_addblob(tv1, tv2);
1434 clear_tv(tv2);
1435 --ectx.ec_stack.ga_len;
1436 }
1437 break;
1438
1439 // Computation with two arguments of unknown type
1440 case ISN_OPANY:
1441 {
1442 typval_T *tv1 = STACK_TV_BOT(-2);
1443 typval_T *tv2 = STACK_TV_BOT(-1);
1444 varnumber_T n1, n2;
1445#ifdef FEAT_FLOAT
1446 float_T f1 = 0, f2 = 0;
1447#endif
1448 int error = FALSE;
1449
1450 if (iptr->isn_arg.op.op_type == EXPR_ADD)
1451 {
1452 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
1453 {
1454 eval_addlist(tv1, tv2);
1455 clear_tv(tv2);
1456 --ectx.ec_stack.ga_len;
1457 break;
1458 }
1459 else if (tv1->v_type == VAR_BLOB
1460 && tv2->v_type == VAR_BLOB)
1461 {
1462 eval_addblob(tv1, tv2);
1463 clear_tv(tv2);
1464 --ectx.ec_stack.ga_len;
1465 break;
1466 }
1467 }
1468#ifdef FEAT_FLOAT
1469 if (tv1->v_type == VAR_FLOAT)
1470 {
1471 f1 = tv1->vval.v_float;
1472 n1 = 0;
1473 }
1474 else
1475#endif
1476 {
1477 n1 = tv_get_number_chk(tv1, &error);
1478 if (error)
1479 goto failed;
1480#ifdef FEAT_FLOAT
1481 if (tv2->v_type == VAR_FLOAT)
1482 f1 = n1;
1483#endif
1484 }
1485#ifdef FEAT_FLOAT
1486 if (tv2->v_type == VAR_FLOAT)
1487 {
1488 f2 = tv2->vval.v_float;
1489 n2 = 0;
1490 }
1491 else
1492#endif
1493 {
1494 n2 = tv_get_number_chk(tv2, &error);
1495 if (error)
1496 goto failed;
1497#ifdef FEAT_FLOAT
1498 if (tv1->v_type == VAR_FLOAT)
1499 f2 = n2;
1500#endif
1501 }
1502#ifdef FEAT_FLOAT
1503 // if there is a float on either side the result is a float
1504 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
1505 {
1506 switch (iptr->isn_arg.op.op_type)
1507 {
1508 case EXPR_MULT: f1 = f1 * f2; break;
1509 case EXPR_DIV: f1 = f1 / f2; break;
1510 case EXPR_SUB: f1 = f1 - f2; break;
1511 case EXPR_ADD: f1 = f1 + f2; break;
1512 default: emsg(_(e_modulus)); goto failed;
1513 }
1514 clear_tv(tv1);
1515 clear_tv(tv2);
1516 tv1->v_type = VAR_FLOAT;
1517 tv1->vval.v_float = f1;
1518 --ectx.ec_stack.ga_len;
1519 }
1520 else
1521#endif
1522 {
1523 switch (iptr->isn_arg.op.op_type)
1524 {
1525 case EXPR_MULT: n1 = n1 * n2; break;
1526 case EXPR_DIV: n1 = num_divide(n1, n2); break;
1527 case EXPR_SUB: n1 = n1 - n2; break;
1528 case EXPR_ADD: n1 = n1 + n2; break;
1529 default: n1 = num_modulus(n1, n2); break;
1530 }
1531 clear_tv(tv1);
1532 clear_tv(tv2);
1533 tv1->v_type = VAR_NUMBER;
1534 tv1->vval.v_number = n1;
1535 --ectx.ec_stack.ga_len;
1536 }
1537 }
1538 break;
1539
1540 case ISN_CONCAT:
1541 {
1542 char_u *str1 = STACK_TV_BOT(-2)->vval.v_string;
1543 char_u *str2 = STACK_TV_BOT(-1)->vval.v_string;
1544 char_u *res;
1545
1546 res = concat_str(str1, str2);
1547 clear_tv(STACK_TV_BOT(-2));
1548 clear_tv(STACK_TV_BOT(-1));
1549 --ectx.ec_stack.ga_len;
1550 STACK_TV_BOT(-1)->vval.v_string = res;
1551 }
1552 break;
1553
1554 case ISN_INDEX:
1555 {
1556 list_T *list;
1557 varnumber_T n;
1558 listitem_T *li;
1559
1560 // list index: list is at stack-2, index at stack-1
1561 tv = STACK_TV_BOT(-2);
1562 if (tv->v_type != VAR_LIST)
1563 {
1564 emsg(_(e_listreq));
1565 goto failed;
1566 }
1567 list = tv->vval.v_list;
1568
1569 tv = STACK_TV_BOT(-1);
1570 if (tv->v_type != VAR_NUMBER)
1571 {
1572 emsg(_(e_number_exp));
1573 goto failed;
1574 }
1575 n = tv->vval.v_number;
1576 clear_tv(tv);
1577 if ((li = list_find(list, n)) == NULL)
1578 {
1579 semsg(_(e_listidx), n);
1580 goto failed;
1581 }
1582 --ectx.ec_stack.ga_len;
1583 clear_tv(STACK_TV_BOT(-1));
1584 copy_tv(&li->li_tv, STACK_TV_BOT(-1));
1585 }
1586 break;
1587
1588 // dict member with string key
1589 case ISN_MEMBER:
1590 {
1591 dict_T *dict;
1592 dictitem_T *di;
1593
1594 tv = STACK_TV_BOT(-1);
1595 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
1596 {
1597 emsg(_(e_dictreq));
1598 goto failed;
1599 }
1600 dict = tv->vval.v_dict;
1601
1602 if ((di = dict_find(dict, iptr->isn_arg.string, -1))
1603 == NULL)
1604 {
1605 semsg(_(e_dictkey), iptr->isn_arg.string);
1606 goto failed;
1607 }
1608 clear_tv(tv);
1609 copy_tv(&di->di_tv, tv);
1610 }
1611 break;
1612
1613 case ISN_NEGATENR:
1614 tv = STACK_TV_BOT(-1);
1615 tv->vval.v_number = -tv->vval.v_number;
1616 break;
1617
1618 case ISN_CHECKNR:
1619 {
1620 int error = FALSE;
1621
1622 tv = STACK_TV_BOT(-1);
1623 if (check_not_string(tv) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001624 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001625 (void)tv_get_number_chk(tv, &error);
1626 if (error)
1627 goto failed;
1628 }
1629 break;
1630
1631 case ISN_CHECKTYPE:
1632 {
1633 checktype_T *ct = &iptr->isn_arg.type;
1634
1635 tv = STACK_TV_BOT(ct->ct_off);
1636 if (tv->v_type != ct->ct_type)
1637 {
1638 semsg(_("E1029: Expected %s but got %s"),
1639 vartype_name(ct->ct_type),
1640 vartype_name(tv->v_type));
1641 goto failed;
1642 }
1643 }
1644 break;
1645
1646 case ISN_2BOOL:
1647 {
1648 int n;
1649
1650 tv = STACK_TV_BOT(-1);
1651 n = tv2bool(tv);
1652 if (iptr->isn_arg.number) // invert
1653 n = !n;
1654 clear_tv(tv);
1655 tv->v_type = VAR_BOOL;
1656 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
1657 }
1658 break;
1659
1660 case ISN_2STRING:
1661 {
1662 char_u *str;
1663
1664 tv = STACK_TV_BOT(iptr->isn_arg.number);
1665 if (tv->v_type != VAR_STRING)
1666 {
1667 str = typval_tostring(tv);
1668 clear_tv(tv);
1669 tv->v_type = VAR_STRING;
1670 tv->vval.v_string = str;
1671 }
1672 }
1673 break;
1674
1675 case ISN_DROP:
1676 --ectx.ec_stack.ga_len;
1677 clear_tv(STACK_TV_BOT(0));
1678 break;
1679 }
1680 }
1681
1682done:
1683 // function finished, get result from the stack.
1684 tv = STACK_TV_BOT(-1);
1685 *rettv = *tv;
1686 tv->v_type = VAR_UNKNOWN;
1687 ret = OK;
1688
1689failed:
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001690 // When failed need to unwind the call stack.
1691 while (ectx.ec_frame != initial_frame_ptr)
1692 func_return(&ectx);
1693
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001694 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
1695 clear_tv(STACK_TV(idx));
1696 vim_free(ectx.ec_stack.ga_data);
Bram Moolenaar20431c92020-03-20 18:39:46 +01001697 vim_free(ectx.ec_trystack.ga_data);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001698 return ret;
1699}
1700
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001701/*
1702 * ":dissassemble".
Bram Moolenaar777770f2020-02-06 21:27:08 +01001703 * We don't really need this at runtime, but we do have tests that require it,
1704 * so always include this.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001705 */
1706 void
1707ex_disassemble(exarg_T *eap)
1708{
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001709 char_u *arg = eap->arg;
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001710 char_u *fname;
1711 ufunc_T *ufunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001712 dfunc_T *dfunc;
1713 isn_T *instr;
1714 int current;
1715 int line_idx = 0;
1716 int prev_current = 0;
1717
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001718 fname = trans_function_name(&arg, FALSE,
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001719 TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001720 if (fname == NULL)
1721 {
1722 semsg(_(e_invarg2), eap->arg);
1723 return;
1724 }
1725
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001726 ufunc = find_func(fname, NULL);
1727 vim_free(fname);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001728 if (ufunc == NULL)
1729 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01001730 semsg(_("E1061: Cannot find function %s"), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001731 return;
1732 }
1733 if (ufunc->uf_dfunc_idx < 0)
1734 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01001735 semsg(_("E1062: Function %s is not compiled"), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001736 return;
1737 }
1738 if (ufunc->uf_name_exp != NULL)
1739 msg((char *)ufunc->uf_name_exp);
1740 else
1741 msg((char *)ufunc->uf_name);
1742
1743 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
1744 instr = dfunc->df_instr;
1745 for (current = 0; current < dfunc->df_instr_count; ++current)
1746 {
1747 isn_T *iptr = &instr[current];
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001748 char *line;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001749
1750 while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len)
1751 {
1752 if (current > prev_current)
1753 {
1754 msg_puts("\n\n");
1755 prev_current = current;
1756 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001757 line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
1758 if (line != NULL)
1759 msg(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001760 }
1761
1762 switch (iptr->isn_type)
1763 {
1764 case ISN_EXEC:
1765 smsg("%4d EXEC %s", current, iptr->isn_arg.string);
1766 break;
1767 case ISN_ECHO:
1768 {
1769 echo_T *echo = &iptr->isn_arg.echo;
1770
1771 smsg("%4d %s %d", current,
1772 echo->echo_with_white ? "ECHO" : "ECHON",
1773 echo->echo_count);
1774 }
1775 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01001776 case ISN_EXECUTE:
1777 smsg("%4d EXECUTE %d", current, iptr->isn_arg.number);
1778 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001779 case ISN_LOAD:
1780 if (iptr->isn_arg.number < 0)
1781 smsg("%4d LOAD arg[%lld]", current,
1782 iptr->isn_arg.number + STACK_FRAME_SIZE);
1783 else
1784 smsg("%4d LOAD $%lld", current, iptr->isn_arg.number);
1785 break;
1786 case ISN_LOADV:
1787 smsg("%4d LOADV v:%s", current,
1788 get_vim_var_name(iptr->isn_arg.number));
1789 break;
1790 case ISN_LOADSCRIPT:
1791 {
1792 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001793 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001794 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1795 + iptr->isn_arg.script.script_idx;
1796
1797 smsg("%4d LOADSCRIPT %s from %s", current,
1798 sv->sv_name, si->sn_name);
1799 }
1800 break;
1801 case ISN_LOADS:
1802 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001803 scriptitem_T *si = SCRIPT_ITEM(
1804 iptr->isn_arg.loadstore.ls_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001805
1806 smsg("%4d LOADS s:%s from %s", current,
1807 iptr->isn_arg.string, si->sn_name);
1808 }
1809 break;
1810 case ISN_LOADG:
1811 smsg("%4d LOADG g:%s", current, iptr->isn_arg.string);
1812 break;
1813 case ISN_LOADOPT:
1814 smsg("%4d LOADOPT %s", current, iptr->isn_arg.string);
1815 break;
1816 case ISN_LOADENV:
1817 smsg("%4d LOADENV %s", current, iptr->isn_arg.string);
1818 break;
1819 case ISN_LOADREG:
1820 smsg("%4d LOADREG @%c", current, iptr->isn_arg.number);
1821 break;
1822
1823 case ISN_STORE:
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001824 if (iptr->isn_arg.number < 0)
1825 smsg("%4d STORE arg[%lld]", current,
1826 iptr->isn_arg.number + STACK_FRAME_SIZE);
1827 else
1828 smsg("%4d STORE $%lld", current, iptr->isn_arg.number);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001829 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001830 case ISN_STOREV:
1831 smsg("%4d STOREV v:%s", current,
1832 get_vim_var_name(iptr->isn_arg.number));
1833 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001834 case ISN_STOREG:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001835 smsg("%4d STOREG %s", current, iptr->isn_arg.string);
1836 break;
1837 case ISN_STORES:
1838 {
1839 scriptitem_T *si = SCRIPT_ITEM(
1840 iptr->isn_arg.loadstore.ls_sid);
1841
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001842 smsg("%4d STORES %s in %s", current,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001843 iptr->isn_arg.string, si->sn_name);
1844 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001845 break;
1846 case ISN_STORESCRIPT:
1847 {
1848 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001849 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001850 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1851 + iptr->isn_arg.script.script_idx;
1852
1853 smsg("%4d STORESCRIPT %s in %s", current,
1854 sv->sv_name, si->sn_name);
1855 }
1856 break;
1857 case ISN_STOREOPT:
1858 smsg("%4d STOREOPT &%s", current,
1859 iptr->isn_arg.storeopt.so_name);
1860 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001861 case ISN_STOREENV:
1862 smsg("%4d STOREENV $%s", current, iptr->isn_arg.string);
1863 break;
1864 case ISN_STOREREG:
1865 smsg("%4d STOREREG @%c", current, iptr->isn_arg.number);
1866 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001867 case ISN_STORENR:
1868 smsg("%4d STORE %lld in $%d", current,
Bram Moolenaara471eea2020-03-04 22:20:26 +01001869 iptr->isn_arg.storenr.stnr_val,
1870 iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001871 break;
1872
1873 // constants
1874 case ISN_PUSHNR:
1875 smsg("%4d PUSHNR %lld", current, iptr->isn_arg.number);
1876 break;
1877 case ISN_PUSHBOOL:
1878 case ISN_PUSHSPEC:
1879 smsg("%4d PUSH %s", current,
1880 get_var_special_name(iptr->isn_arg.number));
1881 break;
1882 case ISN_PUSHF:
Bram Moolenaara5d59532020-01-26 21:42:03 +01001883#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001884 smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber);
Bram Moolenaara5d59532020-01-26 21:42:03 +01001885#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001886 break;
1887 case ISN_PUSHS:
1888 smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string);
1889 break;
1890 case ISN_PUSHBLOB:
1891 {
1892 char_u *r;
1893 char_u numbuf[NUMBUFLEN];
1894 char_u *tofree;
1895
1896 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01001897 smsg("%4d PUSHBLOB %s", current, r);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001898 vim_free(tofree);
1899 }
1900 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001901 case ISN_PUSHFUNC:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01001902 {
1903 char *name = (char *)iptr->isn_arg.string;
1904
1905 smsg("%4d PUSHFUNC \"%s\"", current,
1906 name == NULL ? "[none]" : name);
1907 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001908 break;
1909 case ISN_PUSHPARTIAL:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01001910 {
1911 partial_T *part = iptr->isn_arg.partial;
1912
1913 smsg("%4d PUSHPARTIAL \"%s\"", current,
1914 part == NULL ? "[none]" : (char *)partial_name(part));
1915 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001916 break;
1917 case ISN_PUSHCHANNEL:
1918#ifdef FEAT_JOB_CHANNEL
1919 {
1920 channel_T *channel = iptr->isn_arg.channel;
1921
1922 smsg("%4d PUSHCHANNEL %d", current,
1923 channel == NULL ? 0 : channel->ch_id);
1924 }
1925#endif
1926 break;
1927 case ISN_PUSHJOB:
1928#ifdef FEAT_JOB_CHANNEL
1929 {
1930 typval_T tv;
1931 char_u *name;
1932
1933 tv.v_type = VAR_JOB;
1934 tv.vval.v_job = iptr->isn_arg.job;
1935 name = tv_get_string(&tv);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001936 smsg("%4d PUSHJOB \"%s\"", current, name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001937 }
1938#endif
1939 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001940 case ISN_PUSHEXC:
1941 smsg("%4d PUSH v:exception", current);
1942 break;
1943 case ISN_NEWLIST:
1944 smsg("%4d NEWLIST size %lld", current, iptr->isn_arg.number);
1945 break;
1946 case ISN_NEWDICT:
1947 smsg("%4d NEWDICT size %lld", current, iptr->isn_arg.number);
1948 break;
1949
1950 // function call
1951 case ISN_BCALL:
1952 {
1953 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc;
1954
1955 smsg("%4d BCALL %s(argc %d)", current,
1956 internal_func_name(cbfunc->cbf_idx),
1957 cbfunc->cbf_argcount);
1958 }
1959 break;
1960 case ISN_DCALL:
1961 {
1962 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc;
1963 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
1964 + cdfunc->cdf_idx;
1965
1966 smsg("%4d DCALL %s(argc %d)", current,
1967 df->df_ufunc->uf_name_exp != NULL
1968 ? df->df_ufunc->uf_name_exp
1969 : df->df_ufunc->uf_name, cdfunc->cdf_argcount);
1970 }
1971 break;
1972 case ISN_UCALL:
1973 {
1974 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
1975
1976 smsg("%4d UCALL %s(argc %d)", current,
1977 cufunc->cuf_name, cufunc->cuf_argcount);
1978 }
1979 break;
1980 case ISN_PCALL:
1981 {
1982 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc;
1983
1984 smsg("%4d PCALL%s (argc %d)", current,
1985 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
1986 }
1987 break;
1988 case ISN_RETURN:
1989 smsg("%4d RETURN", current);
1990 break;
1991 case ISN_FUNCREF:
1992 {
1993 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
1994 + iptr->isn_arg.number;
1995
1996 smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name);
1997 }
1998 break;
1999
2000 case ISN_JUMP:
2001 {
2002 char *when = "?";
2003
2004 switch (iptr->isn_arg.jump.jump_when)
2005 {
2006 case JUMP_ALWAYS:
2007 when = "JUMP";
2008 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002009 case JUMP_AND_KEEP_IF_TRUE:
2010 when = "JUMP_AND_KEEP_IF_TRUE";
2011 break;
2012 case JUMP_IF_FALSE:
2013 when = "JUMP_IF_FALSE";
2014 break;
2015 case JUMP_AND_KEEP_IF_FALSE:
2016 when = "JUMP_AND_KEEP_IF_FALSE";
2017 break;
2018 }
Bram Moolenaar8a677a32020-03-12 19:15:45 +01002019 smsg("%4d %s -> %d", current, when,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002020 iptr->isn_arg.jump.jump_where);
2021 }
2022 break;
2023
2024 case ISN_FOR:
2025 {
2026 forloop_T *forloop = &iptr->isn_arg.forloop;
2027
2028 smsg("%4d FOR $%d -> %d", current,
2029 forloop->for_idx, forloop->for_end);
2030 }
2031 break;
2032
2033 case ISN_TRY:
2034 {
2035 try_T *try = &iptr->isn_arg.try;
2036
2037 smsg("%4d TRY catch -> %d, finally -> %d", current,
2038 try->try_catch, try->try_finally);
2039 }
2040 break;
2041 case ISN_CATCH:
2042 // TODO
2043 smsg("%4d CATCH", current);
2044 break;
2045 case ISN_ENDTRY:
2046 smsg("%4d ENDTRY", current);
2047 break;
2048 case ISN_THROW:
2049 smsg("%4d THROW", current);
2050 break;
2051
2052 // expression operations on number
2053 case ISN_OPNR:
2054 case ISN_OPFLOAT:
2055 case ISN_OPANY:
2056 {
2057 char *what;
2058 char *ins;
2059
2060 switch (iptr->isn_arg.op.op_type)
2061 {
2062 case EXPR_MULT: what = "*"; break;
2063 case EXPR_DIV: what = "/"; break;
2064 case EXPR_REM: what = "%"; break;
2065 case EXPR_SUB: what = "-"; break;
2066 case EXPR_ADD: what = "+"; break;
2067 default: what = "???"; break;
2068 }
2069 switch (iptr->isn_type)
2070 {
2071 case ISN_OPNR: ins = "OPNR"; break;
2072 case ISN_OPFLOAT: ins = "OPFLOAT"; break;
2073 case ISN_OPANY: ins = "OPANY"; break;
2074 default: ins = "???"; break;
2075 }
2076 smsg("%4d %s %s", current, ins, what);
2077 }
2078 break;
2079
2080 case ISN_COMPAREBOOL:
2081 case ISN_COMPARESPECIAL:
2082 case ISN_COMPARENR:
2083 case ISN_COMPAREFLOAT:
2084 case ISN_COMPARESTRING:
2085 case ISN_COMPAREBLOB:
2086 case ISN_COMPARELIST:
2087 case ISN_COMPAREDICT:
2088 case ISN_COMPAREFUNC:
2089 case ISN_COMPAREPARTIAL:
2090 case ISN_COMPAREANY:
2091 {
2092 char *p;
2093 char buf[10];
2094 char *type;
2095
2096 switch (iptr->isn_arg.op.op_type)
2097 {
2098 case EXPR_EQUAL: p = "=="; break;
2099 case EXPR_NEQUAL: p = "!="; break;
2100 case EXPR_GREATER: p = ">"; break;
2101 case EXPR_GEQUAL: p = ">="; break;
2102 case EXPR_SMALLER: p = "<"; break;
2103 case EXPR_SEQUAL: p = "<="; break;
2104 case EXPR_MATCH: p = "=~"; break;
2105 case EXPR_IS: p = "is"; break;
2106 case EXPR_ISNOT: p = "isnot"; break;
2107 case EXPR_NOMATCH: p = "!~"; break;
2108 default: p = "???"; break;
2109 }
2110 STRCPY(buf, p);
2111 if (iptr->isn_arg.op.op_ic == TRUE)
2112 strcat(buf, "?");
2113 switch(iptr->isn_type)
2114 {
2115 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
2116 case ISN_COMPARESPECIAL:
2117 type = "COMPARESPECIAL"; break;
2118 case ISN_COMPARENR: type = "COMPARENR"; break;
2119 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
2120 case ISN_COMPARESTRING:
2121 type = "COMPARESTRING"; break;
2122 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
2123 case ISN_COMPARELIST: type = "COMPARELIST"; break;
2124 case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
2125 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
2126 case ISN_COMPAREPARTIAL:
2127 type = "COMPAREPARTIAL"; break;
2128 case ISN_COMPAREANY: type = "COMPAREANY"; break;
2129 default: type = "???"; break;
2130 }
2131
2132 smsg("%4d %s %s", current, type, buf);
2133 }
2134 break;
2135
2136 case ISN_ADDLIST: smsg("%4d ADDLIST", current); break;
2137 case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break;
2138
2139 // expression operations
2140 case ISN_CONCAT: smsg("%4d CONCAT", current); break;
2141 case ISN_INDEX: smsg("%4d INDEX", current); break;
2142 case ISN_MEMBER: smsg("%4d MEMBER %s", current,
2143 iptr->isn_arg.string); break;
2144 case ISN_NEGATENR: smsg("%4d NEGATENR", current); break;
2145
2146 case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
2147 case ISN_CHECKTYPE: smsg("%4d CHECKTYPE %s stack[%d]", current,
2148 vartype_name(iptr->isn_arg.type.ct_type),
2149 iptr->isn_arg.type.ct_off);
2150 break;
2151 case ISN_2BOOL: if (iptr->isn_arg.number)
2152 smsg("%4d INVERT (!val)", current);
2153 else
2154 smsg("%4d 2BOOL (!!val)", current);
2155 break;
2156 case ISN_2STRING: smsg("%4d 2STRING stack[%d]", current,
2157 iptr->isn_arg.number);
2158 break;
2159
2160 case ISN_DROP: smsg("%4d DROP", current); break;
2161 }
2162 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002163}
2164
2165/*
2166 * Return TRUE when "tv" is not falsey: non-zero, non-empty string, non-empty
2167 * list, etc. Mostly like what JavaScript does, except that empty list and
2168 * empty dictionary are FALSE.
2169 */
2170 int
2171tv2bool(typval_T *tv)
2172{
2173 switch (tv->v_type)
2174 {
2175 case VAR_NUMBER:
2176 return tv->vval.v_number != 0;
2177 case VAR_FLOAT:
2178#ifdef FEAT_FLOAT
2179 return tv->vval.v_float != 0.0;
2180#else
2181 break;
2182#endif
2183 case VAR_PARTIAL:
2184 return tv->vval.v_partial != NULL;
2185 case VAR_FUNC:
2186 case VAR_STRING:
2187 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
2188 case VAR_LIST:
2189 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
2190 case VAR_DICT:
2191 return tv->vval.v_dict != NULL
2192 && tv->vval.v_dict->dv_hashtab.ht_used > 0;
2193 case VAR_BOOL:
2194 case VAR_SPECIAL:
2195 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
2196 case VAR_JOB:
2197#ifdef FEAT_JOB_CHANNEL
2198 return tv->vval.v_job != NULL;
2199#else
2200 break;
2201#endif
2202 case VAR_CHANNEL:
2203#ifdef FEAT_JOB_CHANNEL
2204 return tv->vval.v_channel != NULL;
2205#else
2206 break;
2207#endif
2208 case VAR_BLOB:
2209 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
2210 case VAR_UNKNOWN:
2211 case VAR_VOID:
2212 break;
2213 }
2214 return FALSE;
2215}
2216
2217/*
2218 * If "tv" is a string give an error and return FAIL.
2219 */
2220 int
2221check_not_string(typval_T *tv)
2222{
2223 if (tv->v_type == VAR_STRING)
2224 {
2225 emsg(_("E1030: Using a String as a Number"));
2226 clear_tv(tv);
2227 return FAIL;
2228 }
2229 return OK;
2230}
2231
2232
2233#endif // FEAT_EVAL