blob: 9d187c4b44ec8f4ee71b665c35c1e2314c617597 [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 {
286 iptr->isn_type = ISN_DCALL;
287 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
288 iptr->isn_arg.dfunc.cdf_argcount = argcount;
289 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100290 return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100291 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100292
293 if (call_prepare(argcount, argvars, ectx) == FAIL)
294 return FAIL;
295 vim_memset(&funcexe, 0, sizeof(funcexe));
296 funcexe.evaluate = TRUE;
297
298 // Call the user function. Result goes in last position on the stack.
299 // TODO: add selfdict if there is one
300 error = call_user_func_check(ufunc, argcount, argvars,
301 STACK_TV_BOT(-1), &funcexe, NULL);
302
303 // Clear the arguments.
304 for (idx = 0; idx < argcount; ++idx)
305 clear_tv(&argvars[idx]);
306
307 if (error != FCERR_NONE)
308 {
309 user_func_error(error, ufunc->uf_name);
310 return FAIL;
311 }
312 return OK;
313}
314
315/*
316 * Execute a function by "name".
317 * This can be a builtin function or a user function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100318 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100319 * Returns FAIL if not found without an error message.
320 */
321 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100322call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100323{
324 ufunc_T *ufunc;
325
326 if (builtin_function(name, -1))
327 {
328 int func_idx = find_internal_func(name);
329
330 if (func_idx < 0)
331 return FAIL;
332 if (check_internal_func(func_idx, argcount) == FAIL)
333 return FAIL;
334 return call_bfunc(func_idx, argcount, ectx);
335 }
336
337 ufunc = find_func(name, NULL);
338 if (ufunc != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100339 return call_ufunc(ufunc, argcount, ectx, iptr);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100340
341 return FAIL;
342}
343
344 static int
345call_partial(typval_T *tv, int argcount, ectx_T *ectx)
346{
347 char_u *name;
348 int called_emsg_before = called_emsg;
349
350 if (tv->v_type == VAR_PARTIAL)
351 {
352 partial_T *pt = tv->vval.v_partial;
353
354 if (pt->pt_func != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100355 return call_ufunc(pt->pt_func, argcount, ectx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100356 name = pt->pt_name;
357 }
358 else
359 name = tv->vval.v_string;
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100360 if (call_by_name(name, argcount, ectx, NULL) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100361 {
362 if (called_emsg == called_emsg_before)
363 semsg(_(e_unknownfunc), name);
364 return FAIL;
365 }
366 return OK;
367}
368
369/*
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100370 * Store "tv" in variable "name".
371 * This is for s: and g: variables.
372 */
373 static void
374store_var(char_u *name, typval_T *tv)
375{
376 funccal_entry_T entry;
377
378 save_funccal(&entry);
379 set_var_const(name, NULL, tv, FALSE, 0);
380 restore_funccal();
381}
382
383/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100384 * Execute a function by "name".
385 * This can be a builtin function, user function or a funcref.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100386 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100387 */
388 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100389call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100390{
391 int called_emsg_before = called_emsg;
392
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100393 if (call_by_name(name, argcount, ectx, iptr) == FAIL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100394 && called_emsg == called_emsg_before)
395 {
396 // "name" may be a variable that is a funcref or partial
397 // if find variable
398 // call_partial()
399 // else
400 // semsg(_(e_unknownfunc), name);
401 emsg("call_eval_func(partial) not implemented yet");
402 return FAIL;
403 }
404 return OK;
405}
406
407/*
408 * Call a "def" function from old Vim script.
409 * Return OK or FAIL.
410 */
411 int
412call_def_function(
413 ufunc_T *ufunc,
414 int argc, // nr of arguments
415 typval_T *argv, // arguments
416 typval_T *rettv) // return value
417{
418 ectx_T ectx; // execution context
419 int initial_frame_ptr;
420 typval_T *tv;
421 int idx;
422 int ret = FAIL;
423 dfunc_T *dfunc;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100424 int defcount = ufunc->uf_args.ga_len - argc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100425
426// Get pointer to item in the stack.
427#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
428
429// Get pointer to item at the bottom of the stack, -1 is the bottom.
430#undef STACK_TV_BOT
431#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
432
433// Get pointer to local variable on the stack.
434#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame + STACK_FRAME_SIZE + idx)
435
436 vim_memset(&ectx, 0, sizeof(ectx));
437 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
438 if (ga_grow(&ectx.ec_stack, 20) == FAIL)
Bram Moolenaard5aec0c2020-02-27 21:48:51 +0100439 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100440 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
441
442 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
443
444 // Put arguments on the stack.
445 for (idx = 0; idx < argc; ++idx)
446 {
447 copy_tv(&argv[idx], STACK_TV_BOT(0));
448 ++ectx.ec_stack.ga_len;
449 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100450 // Make space for omitted arguments, will store default value below.
451 if (defcount > 0)
452 for (idx = 0; idx < defcount; ++idx)
453 {
454 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
455 ++ectx.ec_stack.ga_len;
456 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100457
458 // Frame pointer points to just after arguments.
459 ectx.ec_frame = ectx.ec_stack.ga_len;
460 initial_frame_ptr = ectx.ec_frame;
461
462 // dummy frame entries
463 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
464 {
465 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
466 ++ectx.ec_stack.ga_len;
467 }
468
469 // Reserve space for local variables.
470 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
471 for (idx = 0; idx < dfunc->df_varcount; ++idx)
472 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
473 ectx.ec_stack.ga_len += dfunc->df_varcount;
474
475 ectx.ec_instr = dfunc->df_instr;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100476
477 // Decide where to start execution, handles optional arguments.
478 init_instr_idx(ufunc, argc, &ectx);
479
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100480 for (;;)
481 {
482 isn_T *iptr;
483 trycmd_T *trycmd = NULL;
484
485 if (did_throw && !ectx.ec_in_catch)
486 {
487 garray_T *trystack = &ectx.ec_trystack;
488
489 // An exception jumps to the first catch, finally, or returns from
490 // the current function.
491 if (trystack->ga_len > 0)
492 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1;
493 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame)
494 {
495 // jump to ":catch" or ":finally"
496 ectx.ec_in_catch = TRUE;
497 ectx.ec_iidx = trycmd->tcd_catch_idx;
498 }
499 else
500 {
501 // not inside try or need to return from current functions.
502 if (ectx.ec_frame == initial_frame_ptr)
503 {
504 // At the toplevel we are done. Push a dummy return value.
505 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
506 goto failed;
507 tv = STACK_TV_BOT(0);
508 tv->v_type = VAR_NUMBER;
509 tv->vval.v_number = 0;
510 ++ectx.ec_stack.ga_len;
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100511 need_rethrow = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100512 goto done;
513 }
514
515 func_return(&ectx);
516 }
517 continue;
518 }
519
520 iptr = &ectx.ec_instr[ectx.ec_iidx++];
521 switch (iptr->isn_type)
522 {
523 // execute Ex command line
524 case ISN_EXEC:
525 do_cmdline_cmd(iptr->isn_arg.string);
526 break;
527
528 // execute :echo {string} ...
529 case ISN_ECHO:
530 {
531 int count = iptr->isn_arg.echo.echo_count;
532 int atstart = TRUE;
533 int needclr = TRUE;
534
535 for (idx = 0; idx < count; ++idx)
536 {
537 tv = STACK_TV_BOT(idx - count);
538 echo_one(tv, iptr->isn_arg.echo.echo_with_white,
539 &atstart, &needclr);
540 clear_tv(tv);
541 }
Bram Moolenaare0807ea2020-02-20 22:18:06 +0100542 if (needclr)
543 msg_clr_eos();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100544 ectx.ec_stack.ga_len -= count;
545 }
546 break;
547
Bram Moolenaarad39c092020-02-26 18:23:43 +0100548 // execute :execute {string} ...
549 case ISN_EXECUTE:
550 {
551 int count = iptr->isn_arg.number;
552 garray_T ga;
553 char_u buf[NUMBUFLEN];
554 char_u *p;
555 int len;
556 int failed = FALSE;
557
558 ga_init2(&ga, 1, 80);
559 for (idx = 0; idx < count; ++idx)
560 {
561 tv = STACK_TV_BOT(idx - count);
562 if (tv->v_type == VAR_CHANNEL || tv->v_type == VAR_JOB)
563 {
564 emsg(_(e_inval_string));
565 break;
566 }
567 else
568 p = tv_get_string_buf(tv, buf);
569
570 len = (int)STRLEN(p);
571 if (ga_grow(&ga, len + 2) == FAIL)
572 failed = TRUE;
573 else
574 {
575 if (ga.ga_len > 0)
576 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
577 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
578 ga.ga_len += len;
579 }
580 clear_tv(tv);
581 }
582 ectx.ec_stack.ga_len -= count;
583
584 if (!failed && ga.ga_data != NULL)
585 do_cmdline_cmd((char_u *)ga.ga_data);
586 ga_clear(&ga);
587 }
588 break;
589
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100590 // load local variable or argument
591 case ISN_LOAD:
592 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
593 goto failed;
594 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
595 ++ectx.ec_stack.ga_len;
596 break;
597
598 // load v: variable
599 case ISN_LOADV:
600 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
601 goto failed;
602 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
603 ++ectx.ec_stack.ga_len;
604 break;
605
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100606 // load s: variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100607 case ISN_LOADSCRIPT:
608 {
609 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +0100610 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100611 svar_T *sv;
612
613 sv = ((svar_T *)si->sn_var_vals.ga_data)
614 + iptr->isn_arg.script.script_idx;
615 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
616 goto failed;
617 copy_tv(sv->sv_tv, STACK_TV_BOT(0));
618 ++ectx.ec_stack.ga_len;
619 }
620 break;
621
622 // load s: variable in old script
623 case ISN_LOADS:
624 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100625 hashtab_T *ht = &SCRIPT_VARS(
626 iptr->isn_arg.loadstore.ls_sid);
627 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100628 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100629
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100630 if (di == NULL)
631 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100632 semsg(_(e_undefvar), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100633 goto failed;
634 }
635 else
636 {
637 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
638 goto failed;
639 copy_tv(&di->di_tv, STACK_TV_BOT(0));
640 ++ectx.ec_stack.ga_len;
641 }
642 }
643 break;
644
645 // load g: variable
646 case ISN_LOADG:
647 {
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100648 dictitem_T *di = find_var_in_ht(get_globvar_ht(), 0,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100649 iptr->isn_arg.string, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100650
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100651 if (di == NULL)
652 {
653 semsg(_("E121: Undefined variable: g:%s"),
654 iptr->isn_arg.string);
655 goto failed;
656 }
657 else
658 {
659 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
660 goto failed;
661 copy_tv(&di->di_tv, STACK_TV_BOT(0));
662 ++ectx.ec_stack.ga_len;
663 }
664 }
665 break;
666
667 // load &option
668 case ISN_LOADOPT:
669 {
670 typval_T optval;
671 char_u *name = iptr->isn_arg.string;
672
673 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
674 goto failed;
Bram Moolenaar58ceca52020-01-28 22:46:22 +0100675 if (get_option_tv(&name, &optval, TRUE) == FAIL)
676 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100677 *STACK_TV_BOT(0) = optval;
678 ++ectx.ec_stack.ga_len;
679 }
680 break;
681
682 // load $ENV
683 case ISN_LOADENV:
684 {
685 typval_T optval;
686 char_u *name = iptr->isn_arg.string;
687
688 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
689 goto failed;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100690 // name is always valid, checked when compiling
691 (void)get_env_tv(&name, &optval, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100692 *STACK_TV_BOT(0) = optval;
693 ++ectx.ec_stack.ga_len;
694 }
695 break;
696
697 // load @register
698 case ISN_LOADREG:
699 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
700 goto failed;
701 tv = STACK_TV_BOT(0);
702 tv->v_type = VAR_STRING;
703 tv->vval.v_string = get_reg_contents(
704 iptr->isn_arg.number, GREG_EXPR_SRC);
705 ++ectx.ec_stack.ga_len;
706 break;
707
708 // store local variable
709 case ISN_STORE:
710 --ectx.ec_stack.ga_len;
711 tv = STACK_TV_VAR(iptr->isn_arg.number);
712 clear_tv(tv);
713 *tv = *STACK_TV_BOT(0);
714 break;
715
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100716 // store s: variable in old script
717 case ISN_STORES:
718 {
719 hashtab_T *ht = &SCRIPT_VARS(
720 iptr->isn_arg.loadstore.ls_sid);
721 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100722 dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100723
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100724 --ectx.ec_stack.ga_len;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100725 if (di == NULL)
726 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
727 else
728 {
729 clear_tv(&di->di_tv);
730 di->di_tv = *STACK_TV_BOT(0);
731 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100732 }
733 break;
734
735 // store script-local variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100736 case ISN_STORESCRIPT:
737 {
Bram Moolenaar21b9e972020-01-26 19:26:46 +0100738 scriptitem_T *si = SCRIPT_ITEM(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100739 iptr->isn_arg.script.script_sid);
740 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
741 + iptr->isn_arg.script.script_idx;
742
743 --ectx.ec_stack.ga_len;
744 clear_tv(sv->sv_tv);
745 *sv->sv_tv = *STACK_TV_BOT(0);
746 }
747 break;
748
749 // store option
750 case ISN_STOREOPT:
751 {
752 long n = 0;
753 char_u *s = NULL;
754 char *msg;
755
756 --ectx.ec_stack.ga_len;
757 tv = STACK_TV_BOT(0);
758 if (tv->v_type == VAR_STRING)
Bram Moolenaar97a2af32020-01-28 22:52:48 +0100759 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100760 s = tv->vval.v_string;
Bram Moolenaar97a2af32020-01-28 22:52:48 +0100761 if (s == NULL)
762 s = (char_u *)"";
763 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100764 else if (tv->v_type == VAR_NUMBER)
765 n = tv->vval.v_number;
766 else
767 {
768 emsg(_("E1051: Expected string or number"));
769 goto failed;
770 }
771 msg = set_option_value(iptr->isn_arg.storeopt.so_name,
772 n, s, iptr->isn_arg.storeopt.so_flags);
773 if (msg != NULL)
774 {
775 emsg(_(msg));
776 goto failed;
777 }
778 clear_tv(tv);
779 }
780 break;
781
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100782 // store $ENV
783 case ISN_STOREENV:
784 --ectx.ec_stack.ga_len;
785 vim_setenv_ext(iptr->isn_arg.string,
786 tv_get_string(STACK_TV_BOT(0)));
787 break;
788
789 // store @r
790 case ISN_STOREREG:
791 {
792 int reg = iptr->isn_arg.number;
793
794 --ectx.ec_stack.ga_len;
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100795 tv = STACK_TV_BOT(0);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100796 write_reg_contents(reg == '@' ? '"' : reg,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100797 tv_get_string(tv), -1, FALSE);
798 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100799 }
800 break;
801
802 // store v: variable
803 case ISN_STOREV:
804 --ectx.ec_stack.ga_len;
805 if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
806 == FAIL)
807 goto failed;
808 break;
809
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100810 // store g: variable
811 case ISN_STOREG:
812 {
813 dictitem_T *di;
814
815 --ectx.ec_stack.ga_len;
816 di = find_var_in_ht(get_globvar_ht(), 0,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100817 iptr->isn_arg.string + 2, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100818 if (di == NULL)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100819 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100820 else
821 {
822 clear_tv(&di->di_tv);
823 di->di_tv = *STACK_TV_BOT(0);
824 }
825 }
826 break;
827
828 // store number in local variable
829 case ISN_STORENR:
830 tv = STACK_TV_VAR(iptr->isn_arg.storenr.str_idx);
831 clear_tv(tv);
832 tv->v_type = VAR_NUMBER;
833 tv->vval.v_number = iptr->isn_arg.storenr.str_val;
834 break;
835
836 // push constant
837 case ISN_PUSHNR:
838 case ISN_PUSHBOOL:
839 case ISN_PUSHSPEC:
840 case ISN_PUSHF:
841 case ISN_PUSHS:
842 case ISN_PUSHBLOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100843 case ISN_PUSHFUNC:
844 case ISN_PUSHPARTIAL:
845 case ISN_PUSHCHANNEL:
846 case ISN_PUSHJOB:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100847 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
848 goto failed;
849 tv = STACK_TV_BOT(0);
850 ++ectx.ec_stack.ga_len;
851 switch (iptr->isn_type)
852 {
853 case ISN_PUSHNR:
854 tv->v_type = VAR_NUMBER;
855 tv->vval.v_number = iptr->isn_arg.number;
856 break;
857 case ISN_PUSHBOOL:
858 tv->v_type = VAR_BOOL;
859 tv->vval.v_number = iptr->isn_arg.number;
860 break;
861 case ISN_PUSHSPEC:
862 tv->v_type = VAR_SPECIAL;
863 tv->vval.v_number = iptr->isn_arg.number;
864 break;
865#ifdef FEAT_FLOAT
866 case ISN_PUSHF:
867 tv->v_type = VAR_FLOAT;
868 tv->vval.v_float = iptr->isn_arg.fnumber;
869 break;
870#endif
871 case ISN_PUSHBLOB:
872 blob_copy(iptr->isn_arg.blob, tv);
873 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100874 case ISN_PUSHFUNC:
875 tv->v_type = VAR_FUNC;
876 tv->vval.v_string = vim_strsave(iptr->isn_arg.string);
877 break;
878 case ISN_PUSHPARTIAL:
879 tv->v_type = VAR_UNKNOWN;
880 break;
881 case ISN_PUSHCHANNEL:
882#ifdef FEAT_JOB_CHANNEL
883 tv->v_type = VAR_CHANNEL;
884 tv->vval.v_channel = iptr->isn_arg.channel;
885 if (tv->vval.v_channel != NULL)
886 ++tv->vval.v_channel->ch_refcount;
887#endif
888 break;
889 case ISN_PUSHJOB:
890#ifdef FEAT_JOB_CHANNEL
891 tv->v_type = VAR_JOB;
892 tv->vval.v_job = iptr->isn_arg.job;
893 if (tv->vval.v_job != NULL)
894 ++tv->vval.v_job->jv_refcount;
895#endif
896 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100897 default:
898 tv->v_type = VAR_STRING;
899 tv->vval.v_string = vim_strsave(iptr->isn_arg.string);
900 }
901 break;
902
903 // create a list from items on the stack; uses a single allocation
904 // for the list header and the items
905 case ISN_NEWLIST:
906 {
907 int count = iptr->isn_arg.number;
908 list_T *list = list_alloc_with_items(count);
909
910 if (list == NULL)
911 goto failed;
912 for (idx = 0; idx < count; ++idx)
913 list_set_item(list, idx, STACK_TV_BOT(idx - count));
914
915 if (count > 0)
916 ectx.ec_stack.ga_len -= count - 1;
917 else if (ga_grow(&ectx.ec_stack, 1) == FAIL)
918 goto failed;
919 else
920 ++ectx.ec_stack.ga_len;
921 tv = STACK_TV_BOT(-1);
922 tv->v_type = VAR_LIST;
923 tv->vval.v_list = list;
924 ++list->lv_refcount;
925 }
926 break;
927
928 // create a dict from items on the stack
929 case ISN_NEWDICT:
930 {
931 int count = iptr->isn_arg.number;
932 dict_T *dict = dict_alloc();
933 dictitem_T *item;
934
935 if (dict == NULL)
936 goto failed;
937 for (idx = 0; idx < count; ++idx)
938 {
939 // check key type is VAR_STRING
940 tv = STACK_TV_BOT(2 * (idx - count));
941 item = dictitem_alloc(tv->vval.v_string);
942 clear_tv(tv);
943 if (item == NULL)
944 goto failed;
945 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
946 item->di_tv.v_lock = 0;
947 if (dict_add(dict, item) == FAIL)
948 goto failed;
949 }
950
951 if (count > 0)
952 ectx.ec_stack.ga_len -= 2 * count - 1;
953 else if (ga_grow(&ectx.ec_stack, 1) == FAIL)
954 goto failed;
955 else
956 ++ectx.ec_stack.ga_len;
957 tv = STACK_TV_BOT(-1);
958 tv->v_type = VAR_DICT;
959 tv->vval.v_dict = dict;
960 ++dict->dv_refcount;
961 }
962 break;
963
964 // call a :def function
965 case ISN_DCALL:
966 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
967 iptr->isn_arg.dfunc.cdf_argcount,
968 &ectx) == FAIL)
969 goto failed;
970 break;
971
972 // call a builtin function
973 case ISN_BCALL:
974 SOURCING_LNUM = iptr->isn_lnum;
975 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
976 iptr->isn_arg.bfunc.cbf_argcount,
977 &ectx) == FAIL)
978 goto failed;
979 break;
980
981 // call a funcref or partial
982 case ISN_PCALL:
983 {
984 cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
985 int r;
986 typval_T partial;
987
988 SOURCING_LNUM = iptr->isn_lnum;
989 if (pfunc->cpf_top)
990 {
991 // funcref is above the arguments
992 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
993 }
994 else
995 {
996 // Get the funcref from the stack.
997 --ectx.ec_stack.ga_len;
998 partial = *STACK_TV_BOT(0);
999 tv = &partial;
1000 }
1001 r = call_partial(tv, pfunc->cpf_argcount, &ectx);
1002 if (tv == &partial)
1003 clear_tv(&partial);
1004 if (r == FAIL)
1005 goto failed;
1006
1007 if (pfunc->cpf_top)
1008 {
1009 // Get the funcref from the stack, overwrite with the
1010 // return value.
1011 clear_tv(tv);
1012 --ectx.ec_stack.ga_len;
1013 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
1014 }
1015 }
1016 break;
1017
1018 // call a user defined function or funcref/partial
1019 case ISN_UCALL:
1020 {
1021 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
1022
1023 SOURCING_LNUM = iptr->isn_lnum;
1024 if (call_eval_func(cufunc->cuf_name,
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001025 cufunc->cuf_argcount, &ectx, iptr) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001026 goto failed;
1027 }
1028 break;
1029
1030 // return from a :def function call
1031 case ISN_RETURN:
1032 {
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001033 garray_T *trystack = &ectx.ec_trystack;
1034
1035 if (trystack->ga_len > 0)
1036 trycmd = ((trycmd_T *)trystack->ga_data)
1037 + trystack->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001038 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame
1039 && trycmd->tcd_finally_idx != 0)
1040 {
1041 // jump to ":finally"
1042 ectx.ec_iidx = trycmd->tcd_finally_idx;
1043 trycmd->tcd_return = TRUE;
1044 }
1045 else
1046 {
1047 // Restore previous function. If the frame pointer
1048 // is zero then there is none and we are done.
1049 if (ectx.ec_frame == initial_frame_ptr)
1050 goto done;
1051
1052 func_return(&ectx);
1053 }
1054 }
1055 break;
1056
1057 // push a function reference to a compiled function
1058 case ISN_FUNCREF:
1059 {
1060 partial_T *pt = NULL;
1061
1062 pt = ALLOC_CLEAR_ONE(partial_T);
1063 if (pt == NULL)
1064 goto failed;
1065 dfunc = ((dfunc_T *)def_functions.ga_data)
1066 + iptr->isn_arg.number;
1067 pt->pt_func = dfunc->df_ufunc;
1068 pt->pt_refcount = 1;
1069 ++dfunc->df_ufunc->uf_refcount;
1070
1071 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1072 goto failed;
1073 tv = STACK_TV_BOT(0);
1074 ++ectx.ec_stack.ga_len;
1075 tv->vval.v_partial = pt;
1076 tv->v_type = VAR_PARTIAL;
1077 }
1078 break;
1079
1080 // jump if a condition is met
1081 case ISN_JUMP:
1082 {
1083 jumpwhen_T when = iptr->isn_arg.jump.jump_when;
1084 int jump = TRUE;
1085
1086 if (when != JUMP_ALWAYS)
1087 {
1088 tv = STACK_TV_BOT(-1);
1089 jump = tv2bool(tv);
1090 if (when == JUMP_IF_FALSE
1091 || when == JUMP_AND_KEEP_IF_FALSE)
1092 jump = !jump;
Bram Moolenaar777770f2020-02-06 21:27:08 +01001093 if (when == JUMP_IF_FALSE || !jump)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001094 {
1095 // drop the value from the stack
1096 clear_tv(tv);
1097 --ectx.ec_stack.ga_len;
1098 }
1099 }
1100 if (jump)
1101 ectx.ec_iidx = iptr->isn_arg.jump.jump_where;
1102 }
1103 break;
1104
1105 // top of a for loop
1106 case ISN_FOR:
1107 {
1108 list_T *list = STACK_TV_BOT(-1)->vval.v_list;
1109 typval_T *idxtv =
1110 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);
1111
1112 // push the next item from the list
1113 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1114 goto failed;
1115 if (++idxtv->vval.v_number >= list->lv_len)
1116 // past the end of the list, jump to "endfor"
1117 ectx.ec_iidx = iptr->isn_arg.forloop.for_end;
1118 else if (list->lv_first == &range_list_item)
1119 {
1120 // non-materialized range() list
1121 tv = STACK_TV_BOT(0);
1122 tv->v_type = VAR_NUMBER;
1123 tv->vval.v_number = list_find_nr(
1124 list, idxtv->vval.v_number, NULL);
1125 ++ectx.ec_stack.ga_len;
1126 }
1127 else
1128 {
1129 listitem_T *li = list_find(list, idxtv->vval.v_number);
1130
1131 if (li == NULL)
1132 goto failed;
1133 copy_tv(&li->li_tv, STACK_TV_BOT(0));
1134 ++ectx.ec_stack.ga_len;
1135 }
1136 }
1137 break;
1138
1139 // start of ":try" block
1140 case ISN_TRY:
1141 {
1142 if (ga_grow(&ectx.ec_trystack, 1) == FAIL)
1143 goto failed;
1144 trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data)
1145 + ectx.ec_trystack.ga_len;
1146 ++ectx.ec_trystack.ga_len;
1147 ++trylevel;
1148 trycmd->tcd_frame = ectx.ec_frame;
1149 trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch;
1150 trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001151 trycmd->tcd_caught = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001152 }
1153 break;
1154
1155 case ISN_PUSHEXC:
1156 if (current_exception == NULL)
1157 {
1158 iemsg("Evaluating catch while current_exception is NULL");
1159 goto failed;
1160 }
1161 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1162 goto failed;
1163 tv = STACK_TV_BOT(0);
1164 ++ectx.ec_stack.ga_len;
1165 tv->v_type = VAR_STRING;
1166 tv->vval.v_string = vim_strsave(
1167 (char_u *)current_exception->value);
1168 break;
1169
1170 case ISN_CATCH:
1171 {
1172 garray_T *trystack = &ectx.ec_trystack;
1173
1174 if (trystack->ga_len > 0)
1175 {
1176 trycmd = ((trycmd_T *)trystack->ga_data)
1177 + trystack->ga_len - 1;
1178 trycmd->tcd_caught = TRUE;
1179 }
1180 did_emsg = got_int = did_throw = FALSE;
1181 catch_exception(current_exception);
1182 }
1183 break;
1184
1185 // end of ":try" block
1186 case ISN_ENDTRY:
1187 {
1188 garray_T *trystack = &ectx.ec_trystack;
1189
1190 if (trystack->ga_len > 0)
1191 {
1192 --trystack->ga_len;
1193 --trylevel;
1194 trycmd = ((trycmd_T *)trystack->ga_data)
1195 + trystack->ga_len;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001196 if (trycmd->tcd_caught && current_exception != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001197 {
1198 // discard the exception
1199 if (caught_stack == current_exception)
1200 caught_stack = caught_stack->caught;
1201 discard_current_exception();
1202 }
1203
1204 if (trycmd->tcd_return)
1205 {
1206 // Restore previous function. If the frame pointer
1207 // is zero then there is none and we are done.
1208 if (ectx.ec_frame == initial_frame_ptr)
1209 goto done;
1210
1211 func_return(&ectx);
1212 }
1213 }
1214 }
1215 break;
1216
1217 case ISN_THROW:
1218 --ectx.ec_stack.ga_len;
1219 tv = STACK_TV_BOT(0);
1220 if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL)
1221 {
1222 vim_free(tv->vval.v_string);
1223 goto failed;
1224 }
1225 did_throw = TRUE;
1226 break;
1227
1228 // compare with special values
1229 case ISN_COMPAREBOOL:
1230 case ISN_COMPARESPECIAL:
1231 {
1232 typval_T *tv1 = STACK_TV_BOT(-2);
1233 typval_T *tv2 = STACK_TV_BOT(-1);
1234 varnumber_T arg1 = tv1->vval.v_number;
1235 varnumber_T arg2 = tv2->vval.v_number;
1236 int res;
1237
1238 switch (iptr->isn_arg.op.op_type)
1239 {
1240 case EXPR_EQUAL: res = arg1 == arg2; break;
1241 case EXPR_NEQUAL: res = arg1 != arg2; break;
1242 default: res = 0; break;
1243 }
1244
1245 --ectx.ec_stack.ga_len;
1246 tv1->v_type = VAR_BOOL;
1247 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
1248 }
1249 break;
1250
1251 // Operation with two number arguments
1252 case ISN_OPNR:
1253 case ISN_COMPARENR:
1254 {
1255 typval_T *tv1 = STACK_TV_BOT(-2);
1256 typval_T *tv2 = STACK_TV_BOT(-1);
1257 varnumber_T arg1 = tv1->vval.v_number;
1258 varnumber_T arg2 = tv2->vval.v_number;
1259 varnumber_T res;
1260
1261 switch (iptr->isn_arg.op.op_type)
1262 {
1263 case EXPR_MULT: res = arg1 * arg2; break;
1264 case EXPR_DIV: res = arg1 / arg2; break;
1265 case EXPR_REM: res = arg1 % arg2; break;
1266 case EXPR_SUB: res = arg1 - arg2; break;
1267 case EXPR_ADD: res = arg1 + arg2; break;
1268
1269 case EXPR_EQUAL: res = arg1 == arg2; break;
1270 case EXPR_NEQUAL: res = arg1 != arg2; break;
1271 case EXPR_GREATER: res = arg1 > arg2; break;
1272 case EXPR_GEQUAL: res = arg1 >= arg2; break;
1273 case EXPR_SMALLER: res = arg1 < arg2; break;
1274 case EXPR_SEQUAL: res = arg1 <= arg2; break;
1275 default: res = 0; break;
1276 }
1277
1278 --ectx.ec_stack.ga_len;
1279 if (iptr->isn_type == ISN_COMPARENR)
1280 {
1281 tv1->v_type = VAR_BOOL;
1282 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
1283 }
1284 else
1285 tv1->vval.v_number = res;
1286 }
1287 break;
1288
1289 // Computation with two float arguments
1290 case ISN_OPFLOAT:
1291 case ISN_COMPAREFLOAT:
Bram Moolenaara5d59532020-01-26 21:42:03 +01001292#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001293 {
1294 typval_T *tv1 = STACK_TV_BOT(-2);
1295 typval_T *tv2 = STACK_TV_BOT(-1);
1296 float_T arg1 = tv1->vval.v_float;
1297 float_T arg2 = tv2->vval.v_float;
1298 float_T res = 0;
1299 int cmp = FALSE;
1300
1301 switch (iptr->isn_arg.op.op_type)
1302 {
1303 case EXPR_MULT: res = arg1 * arg2; break;
1304 case EXPR_DIV: res = arg1 / arg2; break;
1305 case EXPR_SUB: res = arg1 - arg2; break;
1306 case EXPR_ADD: res = arg1 + arg2; break;
1307
1308 case EXPR_EQUAL: cmp = arg1 == arg2; break;
1309 case EXPR_NEQUAL: cmp = arg1 != arg2; break;
1310 case EXPR_GREATER: cmp = arg1 > arg2; break;
1311 case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
1312 case EXPR_SMALLER: cmp = arg1 < arg2; break;
1313 case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
1314 default: cmp = 0; break;
1315 }
1316 --ectx.ec_stack.ga_len;
1317 if (iptr->isn_type == ISN_COMPAREFLOAT)
1318 {
1319 tv1->v_type = VAR_BOOL;
1320 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1321 }
1322 else
1323 tv1->vval.v_float = res;
1324 }
Bram Moolenaara5d59532020-01-26 21:42:03 +01001325#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001326 break;
1327
1328 case ISN_COMPARELIST:
1329 {
1330 typval_T *tv1 = STACK_TV_BOT(-2);
1331 typval_T *tv2 = STACK_TV_BOT(-1);
1332 list_T *arg1 = tv1->vval.v_list;
1333 list_T *arg2 = tv2->vval.v_list;
1334 int cmp = FALSE;
1335 int ic = iptr->isn_arg.op.op_ic;
1336
1337 switch (iptr->isn_arg.op.op_type)
1338 {
1339 case EXPR_EQUAL: cmp =
1340 list_equal(arg1, arg2, ic, FALSE); break;
1341 case EXPR_NEQUAL: cmp =
1342 !list_equal(arg1, arg2, ic, FALSE); break;
1343 case EXPR_IS: cmp = arg1 == arg2; break;
1344 case EXPR_ISNOT: cmp = arg1 != arg2; break;
1345 default: cmp = 0; break;
1346 }
1347 --ectx.ec_stack.ga_len;
1348 clear_tv(tv1);
1349 clear_tv(tv2);
1350 tv1->v_type = VAR_BOOL;
1351 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1352 }
1353 break;
1354
1355 case ISN_COMPAREBLOB:
1356 {
1357 typval_T *tv1 = STACK_TV_BOT(-2);
1358 typval_T *tv2 = STACK_TV_BOT(-1);
1359 blob_T *arg1 = tv1->vval.v_blob;
1360 blob_T *arg2 = tv2->vval.v_blob;
1361 int cmp = FALSE;
1362
1363 switch (iptr->isn_arg.op.op_type)
1364 {
1365 case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break;
1366 case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); 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 // TODO: handle separately
1380 case ISN_COMPARESTRING:
1381 case ISN_COMPAREDICT:
1382 case ISN_COMPAREFUNC:
1383 case ISN_COMPAREPARTIAL:
1384 case ISN_COMPAREANY:
1385 {
1386 typval_T *tv1 = STACK_TV_BOT(-2);
1387 typval_T *tv2 = STACK_TV_BOT(-1);
1388 exptype_T exptype = iptr->isn_arg.op.op_type;
1389 int ic = iptr->isn_arg.op.op_ic;
1390
1391 typval_compare(tv1, tv2, exptype, ic);
1392 clear_tv(tv2);
1393 tv1->v_type = VAR_BOOL;
1394 tv1->vval.v_number = tv1->vval.v_number
1395 ? VVAL_TRUE : VVAL_FALSE;
1396 --ectx.ec_stack.ga_len;
1397 }
1398 break;
1399
1400 case ISN_ADDLIST:
1401 case ISN_ADDBLOB:
1402 {
1403 typval_T *tv1 = STACK_TV_BOT(-2);
1404 typval_T *tv2 = STACK_TV_BOT(-1);
1405
1406 if (iptr->isn_type == ISN_ADDLIST)
1407 eval_addlist(tv1, tv2);
1408 else
1409 eval_addblob(tv1, tv2);
1410 clear_tv(tv2);
1411 --ectx.ec_stack.ga_len;
1412 }
1413 break;
1414
1415 // Computation with two arguments of unknown type
1416 case ISN_OPANY:
1417 {
1418 typval_T *tv1 = STACK_TV_BOT(-2);
1419 typval_T *tv2 = STACK_TV_BOT(-1);
1420 varnumber_T n1, n2;
1421#ifdef FEAT_FLOAT
1422 float_T f1 = 0, f2 = 0;
1423#endif
1424 int error = FALSE;
1425
1426 if (iptr->isn_arg.op.op_type == EXPR_ADD)
1427 {
1428 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
1429 {
1430 eval_addlist(tv1, tv2);
1431 clear_tv(tv2);
1432 --ectx.ec_stack.ga_len;
1433 break;
1434 }
1435 else if (tv1->v_type == VAR_BLOB
1436 && tv2->v_type == VAR_BLOB)
1437 {
1438 eval_addblob(tv1, tv2);
1439 clear_tv(tv2);
1440 --ectx.ec_stack.ga_len;
1441 break;
1442 }
1443 }
1444#ifdef FEAT_FLOAT
1445 if (tv1->v_type == VAR_FLOAT)
1446 {
1447 f1 = tv1->vval.v_float;
1448 n1 = 0;
1449 }
1450 else
1451#endif
1452 {
1453 n1 = tv_get_number_chk(tv1, &error);
1454 if (error)
1455 goto failed;
1456#ifdef FEAT_FLOAT
1457 if (tv2->v_type == VAR_FLOAT)
1458 f1 = n1;
1459#endif
1460 }
1461#ifdef FEAT_FLOAT
1462 if (tv2->v_type == VAR_FLOAT)
1463 {
1464 f2 = tv2->vval.v_float;
1465 n2 = 0;
1466 }
1467 else
1468#endif
1469 {
1470 n2 = tv_get_number_chk(tv2, &error);
1471 if (error)
1472 goto failed;
1473#ifdef FEAT_FLOAT
1474 if (tv1->v_type == VAR_FLOAT)
1475 f2 = n2;
1476#endif
1477 }
1478#ifdef FEAT_FLOAT
1479 // if there is a float on either side the result is a float
1480 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
1481 {
1482 switch (iptr->isn_arg.op.op_type)
1483 {
1484 case EXPR_MULT: f1 = f1 * f2; break;
1485 case EXPR_DIV: f1 = f1 / f2; break;
1486 case EXPR_SUB: f1 = f1 - f2; break;
1487 case EXPR_ADD: f1 = f1 + f2; break;
1488 default: emsg(_(e_modulus)); goto failed;
1489 }
1490 clear_tv(tv1);
1491 clear_tv(tv2);
1492 tv1->v_type = VAR_FLOAT;
1493 tv1->vval.v_float = f1;
1494 --ectx.ec_stack.ga_len;
1495 }
1496 else
1497#endif
1498 {
1499 switch (iptr->isn_arg.op.op_type)
1500 {
1501 case EXPR_MULT: n1 = n1 * n2; break;
1502 case EXPR_DIV: n1 = num_divide(n1, n2); break;
1503 case EXPR_SUB: n1 = n1 - n2; break;
1504 case EXPR_ADD: n1 = n1 + n2; break;
1505 default: n1 = num_modulus(n1, n2); break;
1506 }
1507 clear_tv(tv1);
1508 clear_tv(tv2);
1509 tv1->v_type = VAR_NUMBER;
1510 tv1->vval.v_number = n1;
1511 --ectx.ec_stack.ga_len;
1512 }
1513 }
1514 break;
1515
1516 case ISN_CONCAT:
1517 {
1518 char_u *str1 = STACK_TV_BOT(-2)->vval.v_string;
1519 char_u *str2 = STACK_TV_BOT(-1)->vval.v_string;
1520 char_u *res;
1521
1522 res = concat_str(str1, str2);
1523 clear_tv(STACK_TV_BOT(-2));
1524 clear_tv(STACK_TV_BOT(-1));
1525 --ectx.ec_stack.ga_len;
1526 STACK_TV_BOT(-1)->vval.v_string = res;
1527 }
1528 break;
1529
1530 case ISN_INDEX:
1531 {
1532 list_T *list;
1533 varnumber_T n;
1534 listitem_T *li;
1535
1536 // list index: list is at stack-2, index at stack-1
1537 tv = STACK_TV_BOT(-2);
1538 if (tv->v_type != VAR_LIST)
1539 {
1540 emsg(_(e_listreq));
1541 goto failed;
1542 }
1543 list = tv->vval.v_list;
1544
1545 tv = STACK_TV_BOT(-1);
1546 if (tv->v_type != VAR_NUMBER)
1547 {
1548 emsg(_(e_number_exp));
1549 goto failed;
1550 }
1551 n = tv->vval.v_number;
1552 clear_tv(tv);
1553 if ((li = list_find(list, n)) == NULL)
1554 {
1555 semsg(_(e_listidx), n);
1556 goto failed;
1557 }
1558 --ectx.ec_stack.ga_len;
1559 clear_tv(STACK_TV_BOT(-1));
1560 copy_tv(&li->li_tv, STACK_TV_BOT(-1));
1561 }
1562 break;
1563
1564 // dict member with string key
1565 case ISN_MEMBER:
1566 {
1567 dict_T *dict;
1568 dictitem_T *di;
1569
1570 tv = STACK_TV_BOT(-1);
1571 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
1572 {
1573 emsg(_(e_dictreq));
1574 goto failed;
1575 }
1576 dict = tv->vval.v_dict;
1577
1578 if ((di = dict_find(dict, iptr->isn_arg.string, -1))
1579 == NULL)
1580 {
1581 semsg(_(e_dictkey), iptr->isn_arg.string);
1582 goto failed;
1583 }
1584 clear_tv(tv);
1585 copy_tv(&di->di_tv, tv);
1586 }
1587 break;
1588
1589 case ISN_NEGATENR:
1590 tv = STACK_TV_BOT(-1);
1591 tv->vval.v_number = -tv->vval.v_number;
1592 break;
1593
1594 case ISN_CHECKNR:
1595 {
1596 int error = FALSE;
1597
1598 tv = STACK_TV_BOT(-1);
1599 if (check_not_string(tv) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001600 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001601 (void)tv_get_number_chk(tv, &error);
1602 if (error)
1603 goto failed;
1604 }
1605 break;
1606
1607 case ISN_CHECKTYPE:
1608 {
1609 checktype_T *ct = &iptr->isn_arg.type;
1610
1611 tv = STACK_TV_BOT(ct->ct_off);
1612 if (tv->v_type != ct->ct_type)
1613 {
1614 semsg(_("E1029: Expected %s but got %s"),
1615 vartype_name(ct->ct_type),
1616 vartype_name(tv->v_type));
1617 goto failed;
1618 }
1619 }
1620 break;
1621
1622 case ISN_2BOOL:
1623 {
1624 int n;
1625
1626 tv = STACK_TV_BOT(-1);
1627 n = tv2bool(tv);
1628 if (iptr->isn_arg.number) // invert
1629 n = !n;
1630 clear_tv(tv);
1631 tv->v_type = VAR_BOOL;
1632 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
1633 }
1634 break;
1635
1636 case ISN_2STRING:
1637 {
1638 char_u *str;
1639
1640 tv = STACK_TV_BOT(iptr->isn_arg.number);
1641 if (tv->v_type != VAR_STRING)
1642 {
1643 str = typval_tostring(tv);
1644 clear_tv(tv);
1645 tv->v_type = VAR_STRING;
1646 tv->vval.v_string = str;
1647 }
1648 }
1649 break;
1650
1651 case ISN_DROP:
1652 --ectx.ec_stack.ga_len;
1653 clear_tv(STACK_TV_BOT(0));
1654 break;
1655 }
1656 }
1657
1658done:
1659 // function finished, get result from the stack.
1660 tv = STACK_TV_BOT(-1);
1661 *rettv = *tv;
1662 tv->v_type = VAR_UNKNOWN;
1663 ret = OK;
1664
1665failed:
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001666 // When failed need to unwind the call stack.
1667 while (ectx.ec_frame != initial_frame_ptr)
1668 func_return(&ectx);
1669
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001670 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
1671 clear_tv(STACK_TV(idx));
1672 vim_free(ectx.ec_stack.ga_data);
1673 return ret;
1674}
1675
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001676/*
1677 * ":dissassemble".
Bram Moolenaar777770f2020-02-06 21:27:08 +01001678 * We don't really need this at runtime, but we do have tests that require it,
1679 * so always include this.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001680 */
1681 void
1682ex_disassemble(exarg_T *eap)
1683{
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001684 char_u *arg = eap->arg;
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001685 char_u *fname;
1686 ufunc_T *ufunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001687 dfunc_T *dfunc;
1688 isn_T *instr;
1689 int current;
1690 int line_idx = 0;
1691 int prev_current = 0;
1692
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001693 fname = trans_function_name(&arg, FALSE,
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001694 TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001695 if (fname == NULL)
1696 {
1697 semsg(_(e_invarg2), eap->arg);
1698 return;
1699 }
1700
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001701 ufunc = find_func(fname, NULL);
1702 vim_free(fname);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001703 if (ufunc == NULL)
1704 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01001705 semsg(_("E1061: Cannot find function %s"), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001706 return;
1707 }
1708 if (ufunc->uf_dfunc_idx < 0)
1709 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01001710 semsg(_("E1062: Function %s is not compiled"), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001711 return;
1712 }
1713 if (ufunc->uf_name_exp != NULL)
1714 msg((char *)ufunc->uf_name_exp);
1715 else
1716 msg((char *)ufunc->uf_name);
1717
1718 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
1719 instr = dfunc->df_instr;
1720 for (current = 0; current < dfunc->df_instr_count; ++current)
1721 {
1722 isn_T *iptr = &instr[current];
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001723 char *line;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001724
1725 while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len)
1726 {
1727 if (current > prev_current)
1728 {
1729 msg_puts("\n\n");
1730 prev_current = current;
1731 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001732 line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
1733 if (line != NULL)
1734 msg(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001735 }
1736
1737 switch (iptr->isn_type)
1738 {
1739 case ISN_EXEC:
1740 smsg("%4d EXEC %s", current, iptr->isn_arg.string);
1741 break;
1742 case ISN_ECHO:
1743 {
1744 echo_T *echo = &iptr->isn_arg.echo;
1745
1746 smsg("%4d %s %d", current,
1747 echo->echo_with_white ? "ECHO" : "ECHON",
1748 echo->echo_count);
1749 }
1750 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01001751 case ISN_EXECUTE:
1752 smsg("%4d EXECUTE %d", current, iptr->isn_arg.number);
1753 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001754 case ISN_LOAD:
1755 if (iptr->isn_arg.number < 0)
1756 smsg("%4d LOAD arg[%lld]", current,
1757 iptr->isn_arg.number + STACK_FRAME_SIZE);
1758 else
1759 smsg("%4d LOAD $%lld", current, iptr->isn_arg.number);
1760 break;
1761 case ISN_LOADV:
1762 smsg("%4d LOADV v:%s", current,
1763 get_vim_var_name(iptr->isn_arg.number));
1764 break;
1765 case ISN_LOADSCRIPT:
1766 {
1767 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001768 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001769 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1770 + iptr->isn_arg.script.script_idx;
1771
1772 smsg("%4d LOADSCRIPT %s from %s", current,
1773 sv->sv_name, si->sn_name);
1774 }
1775 break;
1776 case ISN_LOADS:
1777 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001778 scriptitem_T *si = SCRIPT_ITEM(
1779 iptr->isn_arg.loadstore.ls_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001780
1781 smsg("%4d LOADS s:%s from %s", current,
1782 iptr->isn_arg.string, si->sn_name);
1783 }
1784 break;
1785 case ISN_LOADG:
1786 smsg("%4d LOADG g:%s", current, iptr->isn_arg.string);
1787 break;
1788 case ISN_LOADOPT:
1789 smsg("%4d LOADOPT %s", current, iptr->isn_arg.string);
1790 break;
1791 case ISN_LOADENV:
1792 smsg("%4d LOADENV %s", current, iptr->isn_arg.string);
1793 break;
1794 case ISN_LOADREG:
1795 smsg("%4d LOADREG @%c", current, iptr->isn_arg.number);
1796 break;
1797
1798 case ISN_STORE:
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001799 if (iptr->isn_arg.number < 0)
1800 smsg("%4d STORE arg[%lld]", current,
1801 iptr->isn_arg.number + STACK_FRAME_SIZE);
1802 else
1803 smsg("%4d STORE $%lld", current, iptr->isn_arg.number);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001804 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001805 case ISN_STOREV:
1806 smsg("%4d STOREV v:%s", current,
1807 get_vim_var_name(iptr->isn_arg.number));
1808 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001809 case ISN_STOREG:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001810 smsg("%4d STOREG %s", current, iptr->isn_arg.string);
1811 break;
1812 case ISN_STORES:
1813 {
1814 scriptitem_T *si = SCRIPT_ITEM(
1815 iptr->isn_arg.loadstore.ls_sid);
1816
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001817 smsg("%4d STORES %s in %s", current,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001818 iptr->isn_arg.string, si->sn_name);
1819 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001820 break;
1821 case ISN_STORESCRIPT:
1822 {
1823 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001824 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001825 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1826 + iptr->isn_arg.script.script_idx;
1827
1828 smsg("%4d STORESCRIPT %s in %s", current,
1829 sv->sv_name, si->sn_name);
1830 }
1831 break;
1832 case ISN_STOREOPT:
1833 smsg("%4d STOREOPT &%s", current,
1834 iptr->isn_arg.storeopt.so_name);
1835 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001836 case ISN_STOREENV:
1837 smsg("%4d STOREENV $%s", current, iptr->isn_arg.string);
1838 break;
1839 case ISN_STOREREG:
1840 smsg("%4d STOREREG @%c", current, iptr->isn_arg.number);
1841 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001842 case ISN_STORENR:
1843 smsg("%4d STORE %lld in $%d", current,
1844 iptr->isn_arg.storenr.str_val,
1845 iptr->isn_arg.storenr.str_idx);
1846 break;
1847
1848 // constants
1849 case ISN_PUSHNR:
1850 smsg("%4d PUSHNR %lld", current, iptr->isn_arg.number);
1851 break;
1852 case ISN_PUSHBOOL:
1853 case ISN_PUSHSPEC:
1854 smsg("%4d PUSH %s", current,
1855 get_var_special_name(iptr->isn_arg.number));
1856 break;
1857 case ISN_PUSHF:
Bram Moolenaara5d59532020-01-26 21:42:03 +01001858#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001859 smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber);
Bram Moolenaara5d59532020-01-26 21:42:03 +01001860#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001861 break;
1862 case ISN_PUSHS:
1863 smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string);
1864 break;
1865 case ISN_PUSHBLOB:
1866 {
1867 char_u *r;
1868 char_u numbuf[NUMBUFLEN];
1869 char_u *tofree;
1870
1871 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01001872 smsg("%4d PUSHBLOB %s", current, r);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001873 vim_free(tofree);
1874 }
1875 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001876 case ISN_PUSHFUNC:
1877 smsg("%4d PUSHFUNC \"%s\"", current, iptr->isn_arg.string);
1878 break;
1879 case ISN_PUSHPARTIAL:
1880 // TODO
1881 smsg("%4d PUSHPARTIAL", current);
1882 break;
1883 case ISN_PUSHCHANNEL:
1884#ifdef FEAT_JOB_CHANNEL
1885 {
1886 channel_T *channel = iptr->isn_arg.channel;
1887
1888 smsg("%4d PUSHCHANNEL %d", current,
1889 channel == NULL ? 0 : channel->ch_id);
1890 }
1891#endif
1892 break;
1893 case ISN_PUSHJOB:
1894#ifdef FEAT_JOB_CHANNEL
1895 {
1896 typval_T tv;
1897 char_u *name;
1898
1899 tv.v_type = VAR_JOB;
1900 tv.vval.v_job = iptr->isn_arg.job;
1901 name = tv_get_string(&tv);
1902 smsg("%4d PUSHJOB %s", current, name);
1903 }
1904#endif
1905 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001906 case ISN_PUSHEXC:
1907 smsg("%4d PUSH v:exception", current);
1908 break;
1909 case ISN_NEWLIST:
1910 smsg("%4d NEWLIST size %lld", current, iptr->isn_arg.number);
1911 break;
1912 case ISN_NEWDICT:
1913 smsg("%4d NEWDICT size %lld", current, iptr->isn_arg.number);
1914 break;
1915
1916 // function call
1917 case ISN_BCALL:
1918 {
1919 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc;
1920
1921 smsg("%4d BCALL %s(argc %d)", current,
1922 internal_func_name(cbfunc->cbf_idx),
1923 cbfunc->cbf_argcount);
1924 }
1925 break;
1926 case ISN_DCALL:
1927 {
1928 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc;
1929 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
1930 + cdfunc->cdf_idx;
1931
1932 smsg("%4d DCALL %s(argc %d)", current,
1933 df->df_ufunc->uf_name_exp != NULL
1934 ? df->df_ufunc->uf_name_exp
1935 : df->df_ufunc->uf_name, cdfunc->cdf_argcount);
1936 }
1937 break;
1938 case ISN_UCALL:
1939 {
1940 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
1941
1942 smsg("%4d UCALL %s(argc %d)", current,
1943 cufunc->cuf_name, cufunc->cuf_argcount);
1944 }
1945 break;
1946 case ISN_PCALL:
1947 {
1948 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc;
1949
1950 smsg("%4d PCALL%s (argc %d)", current,
1951 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
1952 }
1953 break;
1954 case ISN_RETURN:
1955 smsg("%4d RETURN", current);
1956 break;
1957 case ISN_FUNCREF:
1958 {
1959 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
1960 + iptr->isn_arg.number;
1961
1962 smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name);
1963 }
1964 break;
1965
1966 case ISN_JUMP:
1967 {
1968 char *when = "?";
1969
1970 switch (iptr->isn_arg.jump.jump_when)
1971 {
1972 case JUMP_ALWAYS:
1973 when = "JUMP";
1974 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001975 case JUMP_AND_KEEP_IF_TRUE:
1976 when = "JUMP_AND_KEEP_IF_TRUE";
1977 break;
1978 case JUMP_IF_FALSE:
1979 when = "JUMP_IF_FALSE";
1980 break;
1981 case JUMP_AND_KEEP_IF_FALSE:
1982 when = "JUMP_AND_KEEP_IF_FALSE";
1983 break;
1984 }
1985 smsg("%4d %s -> %lld", current, when,
1986 iptr->isn_arg.jump.jump_where);
1987 }
1988 break;
1989
1990 case ISN_FOR:
1991 {
1992 forloop_T *forloop = &iptr->isn_arg.forloop;
1993
1994 smsg("%4d FOR $%d -> %d", current,
1995 forloop->for_idx, forloop->for_end);
1996 }
1997 break;
1998
1999 case ISN_TRY:
2000 {
2001 try_T *try = &iptr->isn_arg.try;
2002
2003 smsg("%4d TRY catch -> %d, finally -> %d", current,
2004 try->try_catch, try->try_finally);
2005 }
2006 break;
2007 case ISN_CATCH:
2008 // TODO
2009 smsg("%4d CATCH", current);
2010 break;
2011 case ISN_ENDTRY:
2012 smsg("%4d ENDTRY", current);
2013 break;
2014 case ISN_THROW:
2015 smsg("%4d THROW", current);
2016 break;
2017
2018 // expression operations on number
2019 case ISN_OPNR:
2020 case ISN_OPFLOAT:
2021 case ISN_OPANY:
2022 {
2023 char *what;
2024 char *ins;
2025
2026 switch (iptr->isn_arg.op.op_type)
2027 {
2028 case EXPR_MULT: what = "*"; break;
2029 case EXPR_DIV: what = "/"; break;
2030 case EXPR_REM: what = "%"; break;
2031 case EXPR_SUB: what = "-"; break;
2032 case EXPR_ADD: what = "+"; break;
2033 default: what = "???"; break;
2034 }
2035 switch (iptr->isn_type)
2036 {
2037 case ISN_OPNR: ins = "OPNR"; break;
2038 case ISN_OPFLOAT: ins = "OPFLOAT"; break;
2039 case ISN_OPANY: ins = "OPANY"; break;
2040 default: ins = "???"; break;
2041 }
2042 smsg("%4d %s %s", current, ins, what);
2043 }
2044 break;
2045
2046 case ISN_COMPAREBOOL:
2047 case ISN_COMPARESPECIAL:
2048 case ISN_COMPARENR:
2049 case ISN_COMPAREFLOAT:
2050 case ISN_COMPARESTRING:
2051 case ISN_COMPAREBLOB:
2052 case ISN_COMPARELIST:
2053 case ISN_COMPAREDICT:
2054 case ISN_COMPAREFUNC:
2055 case ISN_COMPAREPARTIAL:
2056 case ISN_COMPAREANY:
2057 {
2058 char *p;
2059 char buf[10];
2060 char *type;
2061
2062 switch (iptr->isn_arg.op.op_type)
2063 {
2064 case EXPR_EQUAL: p = "=="; break;
2065 case EXPR_NEQUAL: p = "!="; break;
2066 case EXPR_GREATER: p = ">"; break;
2067 case EXPR_GEQUAL: p = ">="; break;
2068 case EXPR_SMALLER: p = "<"; break;
2069 case EXPR_SEQUAL: p = "<="; break;
2070 case EXPR_MATCH: p = "=~"; break;
2071 case EXPR_IS: p = "is"; break;
2072 case EXPR_ISNOT: p = "isnot"; break;
2073 case EXPR_NOMATCH: p = "!~"; break;
2074 default: p = "???"; break;
2075 }
2076 STRCPY(buf, p);
2077 if (iptr->isn_arg.op.op_ic == TRUE)
2078 strcat(buf, "?");
2079 switch(iptr->isn_type)
2080 {
2081 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
2082 case ISN_COMPARESPECIAL:
2083 type = "COMPARESPECIAL"; break;
2084 case ISN_COMPARENR: type = "COMPARENR"; break;
2085 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
2086 case ISN_COMPARESTRING:
2087 type = "COMPARESTRING"; break;
2088 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
2089 case ISN_COMPARELIST: type = "COMPARELIST"; break;
2090 case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
2091 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
2092 case ISN_COMPAREPARTIAL:
2093 type = "COMPAREPARTIAL"; break;
2094 case ISN_COMPAREANY: type = "COMPAREANY"; break;
2095 default: type = "???"; break;
2096 }
2097
2098 smsg("%4d %s %s", current, type, buf);
2099 }
2100 break;
2101
2102 case ISN_ADDLIST: smsg("%4d ADDLIST", current); break;
2103 case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break;
2104
2105 // expression operations
2106 case ISN_CONCAT: smsg("%4d CONCAT", current); break;
2107 case ISN_INDEX: smsg("%4d INDEX", current); break;
2108 case ISN_MEMBER: smsg("%4d MEMBER %s", current,
2109 iptr->isn_arg.string); break;
2110 case ISN_NEGATENR: smsg("%4d NEGATENR", current); break;
2111
2112 case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
2113 case ISN_CHECKTYPE: smsg("%4d CHECKTYPE %s stack[%d]", current,
2114 vartype_name(iptr->isn_arg.type.ct_type),
2115 iptr->isn_arg.type.ct_off);
2116 break;
2117 case ISN_2BOOL: if (iptr->isn_arg.number)
2118 smsg("%4d INVERT (!val)", current);
2119 else
2120 smsg("%4d 2BOOL (!!val)", current);
2121 break;
2122 case ISN_2STRING: smsg("%4d 2STRING stack[%d]", current,
2123 iptr->isn_arg.number);
2124 break;
2125
2126 case ISN_DROP: smsg("%4d DROP", current); break;
2127 }
2128 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002129}
2130
2131/*
2132 * Return TRUE when "tv" is not falsey: non-zero, non-empty string, non-empty
2133 * list, etc. Mostly like what JavaScript does, except that empty list and
2134 * empty dictionary are FALSE.
2135 */
2136 int
2137tv2bool(typval_T *tv)
2138{
2139 switch (tv->v_type)
2140 {
2141 case VAR_NUMBER:
2142 return tv->vval.v_number != 0;
2143 case VAR_FLOAT:
2144#ifdef FEAT_FLOAT
2145 return tv->vval.v_float != 0.0;
2146#else
2147 break;
2148#endif
2149 case VAR_PARTIAL:
2150 return tv->vval.v_partial != NULL;
2151 case VAR_FUNC:
2152 case VAR_STRING:
2153 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
2154 case VAR_LIST:
2155 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
2156 case VAR_DICT:
2157 return tv->vval.v_dict != NULL
2158 && tv->vval.v_dict->dv_hashtab.ht_used > 0;
2159 case VAR_BOOL:
2160 case VAR_SPECIAL:
2161 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
2162 case VAR_JOB:
2163#ifdef FEAT_JOB_CHANNEL
2164 return tv->vval.v_job != NULL;
2165#else
2166 break;
2167#endif
2168 case VAR_CHANNEL:
2169#ifdef FEAT_JOB_CHANNEL
2170 return tv->vval.v_channel != NULL;
2171#else
2172 break;
2173#endif
2174 case VAR_BLOB:
2175 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
2176 case VAR_UNKNOWN:
2177 case VAR_VOID:
2178 break;
2179 }
2180 return FALSE;
2181}
2182
2183/*
2184 * If "tv" is a string give an error and return FAIL.
2185 */
2186 int
2187check_not_string(typval_T *tv)
2188{
2189 if (tv->v_type == VAR_STRING)
2190 {
2191 emsg(_("E1030: Using a String as a Number"));
2192 clear_tv(tv);
2193 return FAIL;
2194 }
2195 return OK;
2196}
2197
2198
2199#endif // FEAT_EVAL