blob: a7850d125a3e0c54ea326f033c577744547ad703 [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 Moolenaarfe270812020-04-11 22:31:27 +0200111 * Create a new list from "count" items at the bottom of the stack.
112 * When "count" is zero an empty list is added to the stack.
113 */
114 static int
115exe_newlist(int count, ectx_T *ectx)
116{
117 list_T *list = list_alloc_with_items(count);
118 int idx;
119 typval_T *tv;
120
121 if (list == NULL)
122 return FAIL;
123 for (idx = 0; idx < count; ++idx)
124 list_set_item(list, idx, STACK_TV_BOT(idx - count));
125
126 if (count > 0)
127 ectx->ec_stack.ga_len -= count - 1;
128 else if (ga_grow(&ectx->ec_stack, 1) == FAIL)
129 return FAIL;
130 else
131 ++ectx->ec_stack.ga_len;
132 tv = STACK_TV_BOT(-1);
133 tv->v_type = VAR_LIST;
134 tv->vval.v_list = list;
135 ++list->lv_refcount;
136 return OK;
137}
138
139/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100140 * Call compiled function "cdf_idx" from compiled code.
141 *
142 * Stack has:
143 * - current arguments (already there)
144 * - omitted optional argument (default values) added here
145 * - stack frame:
146 * - pointer to calling function
147 * - Index of next instruction in calling function
148 * - previous frame pointer
149 * - reserved space for local variables
150 */
151 static int
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200152call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100153{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200154 int argcount = argcount_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100155 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
156 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200157 int arg_to_add;
158 int vararg_count = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100159 int idx;
160
161 if (dfunc->df_deleted)
162 {
163 emsg_funcname(e_func_deleted, ufunc->uf_name);
164 return FAIL;
165 }
166
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200167 if (ufunc->uf_va_name != NULL)
168 {
Bram Moolenaarfe270812020-04-11 22:31:27 +0200169 // Need to make a list out of the vararg arguments.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200170 // Stack at time of call with 2 varargs:
171 // normal_arg
172 // optional_arg
173 // vararg_1
174 // vararg_2
Bram Moolenaarfe270812020-04-11 22:31:27 +0200175 // After creating the list:
176 // normal_arg
177 // optional_arg
178 // vararg-list
179 // With missing optional arguments we get:
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200180 // normal_arg
Bram Moolenaarfe270812020-04-11 22:31:27 +0200181 // After creating the list
182 // normal_arg
183 // (space for optional_arg)
184 // vararg-list
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200185 vararg_count = argcount - ufunc->uf_args.ga_len;
186 if (vararg_count < 0)
187 vararg_count = 0;
188 else
189 argcount -= vararg_count;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200190 if (exe_newlist(vararg_count, ectx) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200191 return FAIL;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200192
193 vararg_count = 1;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200194 }
195
Bram Moolenaarfe270812020-04-11 22:31:27 +0200196 arg_to_add = ufunc->uf_args.ga_len - argcount;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200197 if (arg_to_add < 0)
198 {
199 iemsg("Argument count wrong?");
200 return FAIL;
201 }
202 if (ga_grow(&ectx->ec_stack, arg_to_add + 3 + dfunc->df_varcount) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100203 return FAIL;
204
Bram Moolenaarfe270812020-04-11 22:31:27 +0200205 // Move the vararg-list to below the missing optional arguments.
206 if (vararg_count > 0 && arg_to_add > 0)
207 *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100208
209 // Reserve space for omitted optional arguments, filled in soon.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200210 for (idx = 0; idx < arg_to_add; ++idx)
Bram Moolenaarfe270812020-04-11 22:31:27 +0200211 STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200212 ectx->ec_stack.ga_len += arg_to_add;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100213
214 // Store current execution state in stack frame for ISN_RETURN.
215 // TODO: If the actual number of arguments doesn't match what the called
216 // function expects things go bad.
217 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx;
218 STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx;
219 STACK_TV_BOT(2)->vval.v_number = ectx->ec_frame;
220 ectx->ec_frame = ectx->ec_stack.ga_len;
221
222 // Initialize local variables
223 for (idx = 0; idx < dfunc->df_varcount; ++idx)
224 STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN;
Bram Moolenaarfe270812020-04-11 22:31:27 +0200225 ectx->ec_stack.ga_len += STACK_FRAME_SIZE + dfunc->df_varcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100226
227 // Set execution state to the start of the called function.
228 ectx->ec_dfunc_idx = cdf_idx;
229 ectx->ec_instr = dfunc->df_instr;
230 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100231
232 // Decide where to start execution, handles optional arguments.
233 init_instr_idx(ufunc, argcount, ectx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100234
235 return OK;
236}
237
238// Get pointer to item in the stack.
239#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
240
241/*
242 * Return from the current function.
243 */
244 static void
245func_return(ectx_T *ectx)
246{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100247 int idx;
248 dfunc_T *dfunc;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100249 int top;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100250
251 // execution context goes one level up
252 estack_pop();
253
254 // Clear the local variables and temporary values, but not
255 // the return value.
256 for (idx = ectx->ec_frame + STACK_FRAME_SIZE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100257 idx < ectx->ec_stack.ga_len - 1; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100258 clear_tv(STACK_TV(idx));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100259
260 // Clear the arguments.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100261 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100262 top = ectx->ec_frame - ufunc_argcount(dfunc->df_ufunc);
263 for (idx = top; idx < ectx->ec_frame; ++idx)
264 clear_tv(STACK_TV(idx));
265
266 // Restore the previous frame.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100267 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame)->vval.v_number;
268 ectx->ec_iidx = STACK_TV(ectx->ec_frame + 1)->vval.v_number;
269 ectx->ec_frame = STACK_TV(ectx->ec_frame + 2)->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100270 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
271 ectx->ec_instr = dfunc->df_instr;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100272
273 // Reset the stack to the position before the call, move the return value
274 // to the top of the stack.
275 idx = ectx->ec_stack.ga_len - 1;
276 ectx->ec_stack.ga_len = top + 1;
277 *STACK_TV_BOT(-1) = *STACK_TV(idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100278}
279
280#undef STACK_TV
281
282/*
283 * Prepare arguments and rettv for calling a builtin or user function.
284 */
285 static int
286call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
287{
288 int idx;
289 typval_T *tv;
290
291 // Move arguments from bottom of the stack to argvars[] and add terminator.
292 for (idx = 0; idx < argcount; ++idx)
293 argvars[idx] = *STACK_TV_BOT(idx - argcount);
294 argvars[argcount].v_type = VAR_UNKNOWN;
295
296 // Result replaces the arguments on the stack.
297 if (argcount > 0)
298 ectx->ec_stack.ga_len -= argcount - 1;
299 else if (ga_grow(&ectx->ec_stack, 1) == FAIL)
300 return FAIL;
301 else
302 ++ectx->ec_stack.ga_len;
303
304 // Default return value is zero.
305 tv = STACK_TV_BOT(-1);
306 tv->v_type = VAR_NUMBER;
307 tv->vval.v_number = 0;
308
309 return OK;
310}
311
312/*
313 * Call a builtin function by index.
314 */
315 static int
316call_bfunc(int func_idx, int argcount, ectx_T *ectx)
317{
318 typval_T argvars[MAX_FUNC_ARGS];
319 int idx;
320
321 if (call_prepare(argcount, argvars, ectx) == FAIL)
322 return FAIL;
323
324 // Call the builtin function.
325 call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1));
326
327 // Clear the arguments.
328 for (idx = 0; idx < argcount; ++idx)
329 clear_tv(&argvars[idx]);
330 return OK;
331}
332
333/*
334 * Execute a user defined function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100335 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100336 */
337 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100338call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100339{
340 typval_T argvars[MAX_FUNC_ARGS];
341 funcexe_T funcexe;
342 int error;
343 int idx;
344
345 if (ufunc->uf_dfunc_idx >= 0)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100346 {
347 // The function has been compiled, can call it quickly. For a function
348 // that was defined later: we can call it directly next time.
349 if (iptr != NULL)
350 {
Bram Moolenaar20431c92020-03-20 18:39:46 +0100351 delete_instr(iptr);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100352 iptr->isn_type = ISN_DCALL;
353 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
354 iptr->isn_arg.dfunc.cdf_argcount = argcount;
355 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100356 return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100357 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100358
359 if (call_prepare(argcount, argvars, ectx) == FAIL)
360 return FAIL;
361 vim_memset(&funcexe, 0, sizeof(funcexe));
362 funcexe.evaluate = TRUE;
363
364 // Call the user function. Result goes in last position on the stack.
365 // TODO: add selfdict if there is one
366 error = call_user_func_check(ufunc, argcount, argvars,
367 STACK_TV_BOT(-1), &funcexe, NULL);
368
369 // Clear the arguments.
370 for (idx = 0; idx < argcount; ++idx)
371 clear_tv(&argvars[idx]);
372
373 if (error != FCERR_NONE)
374 {
375 user_func_error(error, ufunc->uf_name);
376 return FAIL;
377 }
378 return OK;
379}
380
381/*
382 * Execute a function by "name".
383 * This can be a builtin function or a user function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100384 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100385 * Returns FAIL if not found without an error message.
386 */
387 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100388call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100389{
390 ufunc_T *ufunc;
391
392 if (builtin_function(name, -1))
393 {
394 int func_idx = find_internal_func(name);
395
396 if (func_idx < 0)
397 return FAIL;
398 if (check_internal_func(func_idx, argcount) == FAIL)
399 return FAIL;
400 return call_bfunc(func_idx, argcount, ectx);
401 }
402
403 ufunc = find_func(name, NULL);
404 if (ufunc != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100405 return call_ufunc(ufunc, argcount, ectx, iptr);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100406
407 return FAIL;
408}
409
410 static int
411call_partial(typval_T *tv, int argcount, ectx_T *ectx)
412{
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200413 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100414 int called_emsg_before = called_emsg;
415
416 if (tv->v_type == VAR_PARTIAL)
417 {
418 partial_T *pt = tv->vval.v_partial;
419
420 if (pt->pt_func != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100421 return call_ufunc(pt->pt_func, argcount, ectx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100422 name = pt->pt_name;
423 }
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200424 else if (tv->v_type == VAR_FUNC)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100425 name = tv->vval.v_string;
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200426 if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100427 {
428 if (called_emsg == called_emsg_before)
429 semsg(_(e_unknownfunc), name);
430 return FAIL;
431 }
432 return OK;
433}
434
435/*
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100436 * Store "tv" in variable "name".
437 * This is for s: and g: variables.
438 */
439 static void
440store_var(char_u *name, typval_T *tv)
441{
442 funccal_entry_T entry;
443
444 save_funccal(&entry);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200445 set_var_const(name, NULL, tv, FALSE, LET_NO_COMMAND);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100446 restore_funccal();
447}
448
449/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100450 * Execute a function by "name".
451 * This can be a builtin function, user function or a funcref.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100452 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100453 */
454 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100455call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100456{
457 int called_emsg_before = called_emsg;
458
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100459 if (call_by_name(name, argcount, ectx, iptr) == FAIL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100460 && called_emsg == called_emsg_before)
461 {
462 // "name" may be a variable that is a funcref or partial
463 // if find variable
464 // call_partial()
465 // else
466 // semsg(_(e_unknownfunc), name);
467 emsg("call_eval_func(partial) not implemented yet");
468 return FAIL;
469 }
470 return OK;
471}
472
473/*
474 * Call a "def" function from old Vim script.
475 * Return OK or FAIL.
476 */
477 int
478call_def_function(
479 ufunc_T *ufunc,
480 int argc, // nr of arguments
481 typval_T *argv, // arguments
482 typval_T *rettv) // return value
483{
484 ectx_T ectx; // execution context
485 int initial_frame_ptr;
486 typval_T *tv;
487 int idx;
488 int ret = FAIL;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100489 int defcount = ufunc->uf_args.ga_len - argc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100490
491// Get pointer to item in the stack.
492#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
493
494// Get pointer to item at the bottom of the stack, -1 is the bottom.
495#undef STACK_TV_BOT
496#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
497
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200498// Get pointer to a local variable on the stack. Negative for arguments.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100499#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame + STACK_FRAME_SIZE + idx)
500
501 vim_memset(&ectx, 0, sizeof(ectx));
502 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
503 if (ga_grow(&ectx.ec_stack, 20) == FAIL)
Bram Moolenaard5aec0c2020-02-27 21:48:51 +0100504 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100505 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
506
507 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
508
509 // Put arguments on the stack.
510 for (idx = 0; idx < argc; ++idx)
511 {
512 copy_tv(&argv[idx], STACK_TV_BOT(0));
513 ++ectx.ec_stack.ga_len;
514 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100515 // Make space for omitted arguments, will store default value below.
516 if (defcount > 0)
517 for (idx = 0; idx < defcount; ++idx)
518 {
519 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
520 ++ectx.ec_stack.ga_len;
521 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100522
523 // Frame pointer points to just after arguments.
524 ectx.ec_frame = ectx.ec_stack.ga_len;
525 initial_frame_ptr = ectx.ec_frame;
526
527 // dummy frame entries
528 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
529 {
530 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
531 ++ectx.ec_stack.ga_len;
532 }
533
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200534 {
535 // Reserve space for local variables.
536 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
537 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100538
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200539 for (idx = 0; idx < dfunc->df_varcount; ++idx)
540 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
541 ectx.ec_stack.ga_len += dfunc->df_varcount;
542
543 ectx.ec_instr = dfunc->df_instr;
544 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100545
546 // Decide where to start execution, handles optional arguments.
547 init_instr_idx(ufunc, argc, &ectx);
548
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100549 for (;;)
550 {
551 isn_T *iptr;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100552
553 veryfast_breakcheck();
554 if (got_int)
555 {
556 // Turn CTRL-C into an exception.
557 got_int = FALSE;
Bram Moolenaar97acfc72020-03-22 13:44:28 +0100558 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
Bram Moolenaar20431c92020-03-20 18:39:46 +0100559 goto failed;
560 did_throw = TRUE;
561 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100562
563 if (did_throw && !ectx.ec_in_catch)
564 {
565 garray_T *trystack = &ectx.ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100566 trycmd_T *trycmd = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100567
568 // An exception jumps to the first catch, finally, or returns from
569 // the current function.
570 if (trystack->ga_len > 0)
571 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1;
572 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame)
573 {
574 // jump to ":catch" or ":finally"
575 ectx.ec_in_catch = TRUE;
576 ectx.ec_iidx = trycmd->tcd_catch_idx;
577 }
578 else
579 {
580 // not inside try or need to return from current functions.
581 if (ectx.ec_frame == initial_frame_ptr)
582 {
583 // At the toplevel we are done. Push a dummy return value.
584 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
585 goto failed;
586 tv = STACK_TV_BOT(0);
587 tv->v_type = VAR_NUMBER;
588 tv->vval.v_number = 0;
589 ++ectx.ec_stack.ga_len;
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100590 need_rethrow = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100591 goto done;
592 }
593
594 func_return(&ectx);
595 }
596 continue;
597 }
598
599 iptr = &ectx.ec_instr[ectx.ec_iidx++];
600 switch (iptr->isn_type)
601 {
602 // execute Ex command line
603 case ISN_EXEC:
604 do_cmdline_cmd(iptr->isn_arg.string);
605 break;
606
607 // execute :echo {string} ...
608 case ISN_ECHO:
609 {
610 int count = iptr->isn_arg.echo.echo_count;
611 int atstart = TRUE;
612 int needclr = TRUE;
613
614 for (idx = 0; idx < count; ++idx)
615 {
616 tv = STACK_TV_BOT(idx - count);
617 echo_one(tv, iptr->isn_arg.echo.echo_with_white,
618 &atstart, &needclr);
619 clear_tv(tv);
620 }
Bram Moolenaare0807ea2020-02-20 22:18:06 +0100621 if (needclr)
622 msg_clr_eos();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100623 ectx.ec_stack.ga_len -= count;
624 }
625 break;
626
Bram Moolenaarad39c092020-02-26 18:23:43 +0100627 // execute :execute {string} ...
628 case ISN_EXECUTE:
629 {
630 int count = iptr->isn_arg.number;
631 garray_T ga;
632 char_u buf[NUMBUFLEN];
633 char_u *p;
634 int len;
635 int failed = FALSE;
636
637 ga_init2(&ga, 1, 80);
638 for (idx = 0; idx < count; ++idx)
639 {
640 tv = STACK_TV_BOT(idx - count);
641 if (tv->v_type == VAR_CHANNEL || tv->v_type == VAR_JOB)
642 {
643 emsg(_(e_inval_string));
644 break;
645 }
646 else
647 p = tv_get_string_buf(tv, buf);
648
649 len = (int)STRLEN(p);
650 if (ga_grow(&ga, len + 2) == FAIL)
651 failed = TRUE;
652 else
653 {
654 if (ga.ga_len > 0)
655 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
656 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
657 ga.ga_len += len;
658 }
659 clear_tv(tv);
660 }
661 ectx.ec_stack.ga_len -= count;
662
663 if (!failed && ga.ga_data != NULL)
664 do_cmdline_cmd((char_u *)ga.ga_data);
665 ga_clear(&ga);
666 }
667 break;
668
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100669 // load local variable or argument
670 case ISN_LOAD:
671 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
672 goto failed;
673 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
674 ++ectx.ec_stack.ga_len;
675 break;
676
677 // load v: variable
678 case ISN_LOADV:
679 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
680 goto failed;
681 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
682 ++ectx.ec_stack.ga_len;
683 break;
684
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100685 // load s: variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100686 case ISN_LOADSCRIPT:
687 {
688 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +0100689 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100690 svar_T *sv;
691
692 sv = ((svar_T *)si->sn_var_vals.ga_data)
693 + iptr->isn_arg.script.script_idx;
694 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
695 goto failed;
696 copy_tv(sv->sv_tv, STACK_TV_BOT(0));
697 ++ectx.ec_stack.ga_len;
698 }
699 break;
700
701 // load s: variable in old script
702 case ISN_LOADS:
703 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100704 hashtab_T *ht = &SCRIPT_VARS(
705 iptr->isn_arg.loadstore.ls_sid);
706 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100707 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100708
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100709 if (di == NULL)
710 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100711 semsg(_(e_undefvar), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100712 goto failed;
713 }
714 else
715 {
716 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
717 goto failed;
718 copy_tv(&di->di_tv, STACK_TV_BOT(0));
719 ++ectx.ec_stack.ga_len;
720 }
721 }
722 break;
723
724 // load g: variable
725 case ISN_LOADG:
726 {
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100727 dictitem_T *di = find_var_in_ht(get_globvar_ht(), 0,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100728 iptr->isn_arg.string, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100729
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100730 if (di == NULL)
731 {
732 semsg(_("E121: Undefined variable: g:%s"),
733 iptr->isn_arg.string);
734 goto failed;
735 }
736 else
737 {
738 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
739 goto failed;
740 copy_tv(&di->di_tv, STACK_TV_BOT(0));
741 ++ectx.ec_stack.ga_len;
742 }
743 }
744 break;
745
746 // load &option
747 case ISN_LOADOPT:
748 {
749 typval_T optval;
750 char_u *name = iptr->isn_arg.string;
751
Bram Moolenaara8c17702020-04-01 21:17:24 +0200752 // This is not expected to fail, name is checked during
753 // compilation: don't set SOURCING_LNUM.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100754 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
755 goto failed;
Bram Moolenaar58ceca52020-01-28 22:46:22 +0100756 if (get_option_tv(&name, &optval, TRUE) == FAIL)
757 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100758 *STACK_TV_BOT(0) = optval;
759 ++ectx.ec_stack.ga_len;
760 }
761 break;
762
763 // load $ENV
764 case ISN_LOADENV:
765 {
766 typval_T optval;
767 char_u *name = iptr->isn_arg.string;
768
769 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
770 goto failed;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100771 // name is always valid, checked when compiling
772 (void)get_env_tv(&name, &optval, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100773 *STACK_TV_BOT(0) = optval;
774 ++ectx.ec_stack.ga_len;
775 }
776 break;
777
778 // load @register
779 case ISN_LOADREG:
780 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
781 goto failed;
782 tv = STACK_TV_BOT(0);
783 tv->v_type = VAR_STRING;
784 tv->vval.v_string = get_reg_contents(
785 iptr->isn_arg.number, GREG_EXPR_SRC);
786 ++ectx.ec_stack.ga_len;
787 break;
788
789 // store local variable
790 case ISN_STORE:
791 --ectx.ec_stack.ga_len;
792 tv = STACK_TV_VAR(iptr->isn_arg.number);
793 clear_tv(tv);
794 *tv = *STACK_TV_BOT(0);
795 break;
796
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100797 // store s: variable in old script
798 case ISN_STORES:
799 {
800 hashtab_T *ht = &SCRIPT_VARS(
801 iptr->isn_arg.loadstore.ls_sid);
802 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100803 dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100804
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100805 --ectx.ec_stack.ga_len;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100806 if (di == NULL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200807 store_var(name, STACK_TV_BOT(0));
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100808 else
809 {
810 clear_tv(&di->di_tv);
811 di->di_tv = *STACK_TV_BOT(0);
812 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100813 }
814 break;
815
816 // store script-local variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100817 case ISN_STORESCRIPT:
818 {
Bram Moolenaar21b9e972020-01-26 19:26:46 +0100819 scriptitem_T *si = SCRIPT_ITEM(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100820 iptr->isn_arg.script.script_sid);
821 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
822 + iptr->isn_arg.script.script_idx;
823
824 --ectx.ec_stack.ga_len;
825 clear_tv(sv->sv_tv);
826 *sv->sv_tv = *STACK_TV_BOT(0);
827 }
828 break;
829
830 // store option
831 case ISN_STOREOPT:
832 {
833 long n = 0;
834 char_u *s = NULL;
835 char *msg;
836
837 --ectx.ec_stack.ga_len;
838 tv = STACK_TV_BOT(0);
839 if (tv->v_type == VAR_STRING)
Bram Moolenaar97a2af32020-01-28 22:52:48 +0100840 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100841 s = tv->vval.v_string;
Bram Moolenaar97a2af32020-01-28 22:52:48 +0100842 if (s == NULL)
843 s = (char_u *)"";
844 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100845 else if (tv->v_type == VAR_NUMBER)
846 n = tv->vval.v_number;
847 else
848 {
849 emsg(_("E1051: Expected string or number"));
850 goto failed;
851 }
852 msg = set_option_value(iptr->isn_arg.storeopt.so_name,
853 n, s, iptr->isn_arg.storeopt.so_flags);
854 if (msg != NULL)
855 {
856 emsg(_(msg));
857 goto failed;
858 }
859 clear_tv(tv);
860 }
861 break;
862
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100863 // store $ENV
864 case ISN_STOREENV:
865 --ectx.ec_stack.ga_len;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100866 tv = STACK_TV_BOT(0);
867 vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
868 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100869 break;
870
871 // store @r
872 case ISN_STOREREG:
873 {
874 int reg = iptr->isn_arg.number;
875
876 --ectx.ec_stack.ga_len;
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100877 tv = STACK_TV_BOT(0);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100878 write_reg_contents(reg == '@' ? '"' : reg,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100879 tv_get_string(tv), -1, FALSE);
880 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100881 }
882 break;
883
884 // store v: variable
885 case ISN_STOREV:
886 --ectx.ec_stack.ga_len;
887 if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
888 == FAIL)
889 goto failed;
890 break;
891
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100892 // store g: variable
893 case ISN_STOREG:
894 {
895 dictitem_T *di;
896
897 --ectx.ec_stack.ga_len;
898 di = find_var_in_ht(get_globvar_ht(), 0,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100899 iptr->isn_arg.string + 2, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100900 if (di == NULL)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100901 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100902 else
903 {
904 clear_tv(&di->di_tv);
905 di->di_tv = *STACK_TV_BOT(0);
906 }
907 }
908 break;
909
910 // store number in local variable
911 case ISN_STORENR:
Bram Moolenaara471eea2020-03-04 22:20:26 +0100912 tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100913 clear_tv(tv);
914 tv->v_type = VAR_NUMBER;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100915 tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100916 break;
917
918 // push constant
919 case ISN_PUSHNR:
920 case ISN_PUSHBOOL:
921 case ISN_PUSHSPEC:
922 case ISN_PUSHF:
923 case ISN_PUSHS:
924 case ISN_PUSHBLOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100925 case ISN_PUSHFUNC:
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100926 case ISN_PUSHCHANNEL:
927 case ISN_PUSHJOB:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100928 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
929 goto failed;
930 tv = STACK_TV_BOT(0);
931 ++ectx.ec_stack.ga_len;
932 switch (iptr->isn_type)
933 {
934 case ISN_PUSHNR:
935 tv->v_type = VAR_NUMBER;
936 tv->vval.v_number = iptr->isn_arg.number;
937 break;
938 case ISN_PUSHBOOL:
939 tv->v_type = VAR_BOOL;
940 tv->vval.v_number = iptr->isn_arg.number;
941 break;
942 case ISN_PUSHSPEC:
943 tv->v_type = VAR_SPECIAL;
944 tv->vval.v_number = iptr->isn_arg.number;
945 break;
946#ifdef FEAT_FLOAT
947 case ISN_PUSHF:
948 tv->v_type = VAR_FLOAT;
949 tv->vval.v_float = iptr->isn_arg.fnumber;
950 break;
951#endif
952 case ISN_PUSHBLOB:
953 blob_copy(iptr->isn_arg.blob, tv);
954 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100955 case ISN_PUSHFUNC:
956 tv->v_type = VAR_FUNC;
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100957 if (iptr->isn_arg.string == NULL)
958 tv->vval.v_string = NULL;
959 else
960 tv->vval.v_string =
961 vim_strsave(iptr->isn_arg.string);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100962 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100963 case ISN_PUSHCHANNEL:
964#ifdef FEAT_JOB_CHANNEL
965 tv->v_type = VAR_CHANNEL;
966 tv->vval.v_channel = iptr->isn_arg.channel;
967 if (tv->vval.v_channel != NULL)
968 ++tv->vval.v_channel->ch_refcount;
969#endif
970 break;
971 case ISN_PUSHJOB:
972#ifdef FEAT_JOB_CHANNEL
973 tv->v_type = VAR_JOB;
974 tv->vval.v_job = iptr->isn_arg.job;
975 if (tv->vval.v_job != NULL)
976 ++tv->vval.v_job->jv_refcount;
977#endif
978 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100979 default:
980 tv->v_type = VAR_STRING;
Bram Moolenaare69f6d02020-04-01 22:11:01 +0200981 tv->vval.v_string = vim_strsave(
982 iptr->isn_arg.string == NULL
983 ? (char_u *)"" : iptr->isn_arg.string);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100984 }
985 break;
986
987 // create a list from items on the stack; uses a single allocation
988 // for the list header and the items
989 case ISN_NEWLIST:
Bram Moolenaarfe270812020-04-11 22:31:27 +0200990 if (exe_newlist(iptr->isn_arg.number, &ectx) == FAIL)
991 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100992 break;
993
994 // create a dict from items on the stack
995 case ISN_NEWDICT:
996 {
997 int count = iptr->isn_arg.number;
998 dict_T *dict = dict_alloc();
999 dictitem_T *item;
1000
1001 if (dict == NULL)
1002 goto failed;
1003 for (idx = 0; idx < count; ++idx)
1004 {
1005 // check key type is VAR_STRING
1006 tv = STACK_TV_BOT(2 * (idx - count));
1007 item = dictitem_alloc(tv->vval.v_string);
1008 clear_tv(tv);
1009 if (item == NULL)
1010 goto failed;
1011 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
1012 item->di_tv.v_lock = 0;
1013 if (dict_add(dict, item) == FAIL)
1014 goto failed;
1015 }
1016
1017 if (count > 0)
1018 ectx.ec_stack.ga_len -= 2 * count - 1;
1019 else if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1020 goto failed;
1021 else
1022 ++ectx.ec_stack.ga_len;
1023 tv = STACK_TV_BOT(-1);
1024 tv->v_type = VAR_DICT;
1025 tv->vval.v_dict = dict;
1026 ++dict->dv_refcount;
1027 }
1028 break;
1029
1030 // call a :def function
1031 case ISN_DCALL:
1032 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
1033 iptr->isn_arg.dfunc.cdf_argcount,
1034 &ectx) == FAIL)
1035 goto failed;
1036 break;
1037
1038 // call a builtin function
1039 case ISN_BCALL:
1040 SOURCING_LNUM = iptr->isn_lnum;
1041 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
1042 iptr->isn_arg.bfunc.cbf_argcount,
1043 &ectx) == FAIL)
1044 goto failed;
1045 break;
1046
1047 // call a funcref or partial
1048 case ISN_PCALL:
1049 {
1050 cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
1051 int r;
1052 typval_T partial;
1053
1054 SOURCING_LNUM = iptr->isn_lnum;
1055 if (pfunc->cpf_top)
1056 {
1057 // funcref is above the arguments
1058 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
1059 }
1060 else
1061 {
1062 // Get the funcref from the stack.
1063 --ectx.ec_stack.ga_len;
1064 partial = *STACK_TV_BOT(0);
1065 tv = &partial;
1066 }
1067 r = call_partial(tv, pfunc->cpf_argcount, &ectx);
1068 if (tv == &partial)
1069 clear_tv(&partial);
1070 if (r == FAIL)
1071 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001072 }
1073 break;
1074
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001075 case ISN_PCALL_END:
1076 // PCALL finished, arguments have been consumed and replaced by
1077 // the return value. Now clear the funcref from the stack,
1078 // and move the return value in its place.
1079 --ectx.ec_stack.ga_len;
1080 clear_tv(STACK_TV_BOT(-1));
1081 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
1082 break;
1083
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001084 // call a user defined function or funcref/partial
1085 case ISN_UCALL:
1086 {
1087 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
1088
1089 SOURCING_LNUM = iptr->isn_lnum;
1090 if (call_eval_func(cufunc->cuf_name,
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001091 cufunc->cuf_argcount, &ectx, iptr) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001092 goto failed;
1093 }
1094 break;
1095
1096 // return from a :def function call
1097 case ISN_RETURN:
1098 {
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001099 garray_T *trystack = &ectx.ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01001100 trycmd_T *trycmd = NULL;
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001101
1102 if (trystack->ga_len > 0)
1103 trycmd = ((trycmd_T *)trystack->ga_data)
1104 + trystack->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001105 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame
1106 && trycmd->tcd_finally_idx != 0)
1107 {
1108 // jump to ":finally"
1109 ectx.ec_iidx = trycmd->tcd_finally_idx;
1110 trycmd->tcd_return = TRUE;
1111 }
1112 else
1113 {
1114 // Restore previous function. If the frame pointer
1115 // is zero then there is none and we are done.
1116 if (ectx.ec_frame == initial_frame_ptr)
1117 goto done;
1118
1119 func_return(&ectx);
1120 }
1121 }
1122 break;
1123
1124 // push a function reference to a compiled function
1125 case ISN_FUNCREF:
1126 {
1127 partial_T *pt = NULL;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001128 dfunc_T *dfunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001129
1130 pt = ALLOC_CLEAR_ONE(partial_T);
1131 if (pt == NULL)
1132 goto failed;
1133 dfunc = ((dfunc_T *)def_functions.ga_data)
1134 + iptr->isn_arg.number;
1135 pt->pt_func = dfunc->df_ufunc;
1136 pt->pt_refcount = 1;
1137 ++dfunc->df_ufunc->uf_refcount;
1138
1139 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1140 goto failed;
1141 tv = STACK_TV_BOT(0);
1142 ++ectx.ec_stack.ga_len;
1143 tv->vval.v_partial = pt;
1144 tv->v_type = VAR_PARTIAL;
1145 }
1146 break;
1147
1148 // jump if a condition is met
1149 case ISN_JUMP:
1150 {
1151 jumpwhen_T when = iptr->isn_arg.jump.jump_when;
1152 int jump = TRUE;
1153
1154 if (when != JUMP_ALWAYS)
1155 {
1156 tv = STACK_TV_BOT(-1);
1157 jump = tv2bool(tv);
1158 if (when == JUMP_IF_FALSE
1159 || when == JUMP_AND_KEEP_IF_FALSE)
1160 jump = !jump;
Bram Moolenaar777770f2020-02-06 21:27:08 +01001161 if (when == JUMP_IF_FALSE || !jump)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001162 {
1163 // drop the value from the stack
1164 clear_tv(tv);
1165 --ectx.ec_stack.ga_len;
1166 }
1167 }
1168 if (jump)
1169 ectx.ec_iidx = iptr->isn_arg.jump.jump_where;
1170 }
1171 break;
1172
1173 // top of a for loop
1174 case ISN_FOR:
1175 {
1176 list_T *list = STACK_TV_BOT(-1)->vval.v_list;
1177 typval_T *idxtv =
1178 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);
1179
1180 // push the next item from the list
1181 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1182 goto failed;
1183 if (++idxtv->vval.v_number >= list->lv_len)
1184 // past the end of the list, jump to "endfor"
1185 ectx.ec_iidx = iptr->isn_arg.forloop.for_end;
1186 else if (list->lv_first == &range_list_item)
1187 {
1188 // non-materialized range() list
1189 tv = STACK_TV_BOT(0);
1190 tv->v_type = VAR_NUMBER;
1191 tv->vval.v_number = list_find_nr(
1192 list, idxtv->vval.v_number, NULL);
1193 ++ectx.ec_stack.ga_len;
1194 }
1195 else
1196 {
1197 listitem_T *li = list_find(list, idxtv->vval.v_number);
1198
1199 if (li == NULL)
1200 goto failed;
1201 copy_tv(&li->li_tv, STACK_TV_BOT(0));
1202 ++ectx.ec_stack.ga_len;
1203 }
1204 }
1205 break;
1206
1207 // start of ":try" block
1208 case ISN_TRY:
1209 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001210 trycmd_T *trycmd = NULL;
1211
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001212 if (ga_grow(&ectx.ec_trystack, 1) == FAIL)
1213 goto failed;
1214 trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data)
1215 + ectx.ec_trystack.ga_len;
1216 ++ectx.ec_trystack.ga_len;
1217 ++trylevel;
1218 trycmd->tcd_frame = ectx.ec_frame;
1219 trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch;
1220 trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001221 trycmd->tcd_caught = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001222 }
1223 break;
1224
1225 case ISN_PUSHEXC:
1226 if (current_exception == NULL)
1227 {
1228 iemsg("Evaluating catch while current_exception is NULL");
1229 goto failed;
1230 }
1231 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1232 goto failed;
1233 tv = STACK_TV_BOT(0);
1234 ++ectx.ec_stack.ga_len;
1235 tv->v_type = VAR_STRING;
1236 tv->vval.v_string = vim_strsave(
1237 (char_u *)current_exception->value);
1238 break;
1239
1240 case ISN_CATCH:
1241 {
1242 garray_T *trystack = &ectx.ec_trystack;
1243
1244 if (trystack->ga_len > 0)
1245 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001246 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001247 + trystack->ga_len - 1;
1248 trycmd->tcd_caught = TRUE;
1249 }
1250 did_emsg = got_int = did_throw = FALSE;
1251 catch_exception(current_exception);
1252 }
1253 break;
1254
1255 // end of ":try" block
1256 case ISN_ENDTRY:
1257 {
1258 garray_T *trystack = &ectx.ec_trystack;
1259
1260 if (trystack->ga_len > 0)
1261 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001262 trycmd_T *trycmd = NULL;
1263
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001264 --trystack->ga_len;
1265 --trylevel;
1266 trycmd = ((trycmd_T *)trystack->ga_data)
1267 + trystack->ga_len;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001268 if (trycmd->tcd_caught && current_exception != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001269 {
1270 // discard the exception
1271 if (caught_stack == current_exception)
1272 caught_stack = caught_stack->caught;
1273 discard_current_exception();
1274 }
1275
1276 if (trycmd->tcd_return)
1277 {
1278 // Restore previous function. If the frame pointer
1279 // is zero then there is none and we are done.
1280 if (ectx.ec_frame == initial_frame_ptr)
1281 goto done;
1282
1283 func_return(&ectx);
1284 }
1285 }
1286 }
1287 break;
1288
1289 case ISN_THROW:
1290 --ectx.ec_stack.ga_len;
1291 tv = STACK_TV_BOT(0);
1292 if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL)
1293 {
1294 vim_free(tv->vval.v_string);
1295 goto failed;
1296 }
1297 did_throw = TRUE;
1298 break;
1299
1300 // compare with special values
1301 case ISN_COMPAREBOOL:
1302 case ISN_COMPARESPECIAL:
1303 {
1304 typval_T *tv1 = STACK_TV_BOT(-2);
1305 typval_T *tv2 = STACK_TV_BOT(-1);
1306 varnumber_T arg1 = tv1->vval.v_number;
1307 varnumber_T arg2 = tv2->vval.v_number;
1308 int res;
1309
1310 switch (iptr->isn_arg.op.op_type)
1311 {
1312 case EXPR_EQUAL: res = arg1 == arg2; break;
1313 case EXPR_NEQUAL: res = arg1 != arg2; break;
1314 default: res = 0; break;
1315 }
1316
1317 --ectx.ec_stack.ga_len;
1318 tv1->v_type = VAR_BOOL;
1319 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
1320 }
1321 break;
1322
1323 // Operation with two number arguments
1324 case ISN_OPNR:
1325 case ISN_COMPARENR:
1326 {
1327 typval_T *tv1 = STACK_TV_BOT(-2);
1328 typval_T *tv2 = STACK_TV_BOT(-1);
1329 varnumber_T arg1 = tv1->vval.v_number;
1330 varnumber_T arg2 = tv2->vval.v_number;
1331 varnumber_T res;
1332
1333 switch (iptr->isn_arg.op.op_type)
1334 {
1335 case EXPR_MULT: res = arg1 * arg2; break;
1336 case EXPR_DIV: res = arg1 / arg2; break;
1337 case EXPR_REM: res = arg1 % arg2; break;
1338 case EXPR_SUB: res = arg1 - arg2; break;
1339 case EXPR_ADD: res = arg1 + arg2; break;
1340
1341 case EXPR_EQUAL: res = arg1 == arg2; break;
1342 case EXPR_NEQUAL: res = arg1 != arg2; break;
1343 case EXPR_GREATER: res = arg1 > arg2; break;
1344 case EXPR_GEQUAL: res = arg1 >= arg2; break;
1345 case EXPR_SMALLER: res = arg1 < arg2; break;
1346 case EXPR_SEQUAL: res = arg1 <= arg2; break;
1347 default: res = 0; break;
1348 }
1349
1350 --ectx.ec_stack.ga_len;
1351 if (iptr->isn_type == ISN_COMPARENR)
1352 {
1353 tv1->v_type = VAR_BOOL;
1354 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
1355 }
1356 else
1357 tv1->vval.v_number = res;
1358 }
1359 break;
1360
1361 // Computation with two float arguments
1362 case ISN_OPFLOAT:
1363 case ISN_COMPAREFLOAT:
Bram Moolenaara5d59532020-01-26 21:42:03 +01001364#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001365 {
1366 typval_T *tv1 = STACK_TV_BOT(-2);
1367 typval_T *tv2 = STACK_TV_BOT(-1);
1368 float_T arg1 = tv1->vval.v_float;
1369 float_T arg2 = tv2->vval.v_float;
1370 float_T res = 0;
1371 int cmp = FALSE;
1372
1373 switch (iptr->isn_arg.op.op_type)
1374 {
1375 case EXPR_MULT: res = arg1 * arg2; break;
1376 case EXPR_DIV: res = arg1 / arg2; break;
1377 case EXPR_SUB: res = arg1 - arg2; break;
1378 case EXPR_ADD: res = arg1 + arg2; break;
1379
1380 case EXPR_EQUAL: cmp = arg1 == arg2; break;
1381 case EXPR_NEQUAL: cmp = arg1 != arg2; break;
1382 case EXPR_GREATER: cmp = arg1 > arg2; break;
1383 case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
1384 case EXPR_SMALLER: cmp = arg1 < arg2; break;
1385 case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
1386 default: cmp = 0; break;
1387 }
1388 --ectx.ec_stack.ga_len;
1389 if (iptr->isn_type == ISN_COMPAREFLOAT)
1390 {
1391 tv1->v_type = VAR_BOOL;
1392 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1393 }
1394 else
1395 tv1->vval.v_float = res;
1396 }
Bram Moolenaara5d59532020-01-26 21:42:03 +01001397#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001398 break;
1399
1400 case ISN_COMPARELIST:
1401 {
1402 typval_T *tv1 = STACK_TV_BOT(-2);
1403 typval_T *tv2 = STACK_TV_BOT(-1);
1404 list_T *arg1 = tv1->vval.v_list;
1405 list_T *arg2 = tv2->vval.v_list;
1406 int cmp = FALSE;
1407 int ic = iptr->isn_arg.op.op_ic;
1408
1409 switch (iptr->isn_arg.op.op_type)
1410 {
1411 case EXPR_EQUAL: cmp =
1412 list_equal(arg1, arg2, ic, FALSE); break;
1413 case EXPR_NEQUAL: cmp =
1414 !list_equal(arg1, arg2, ic, FALSE); break;
1415 case EXPR_IS: cmp = arg1 == arg2; break;
1416 case EXPR_ISNOT: cmp = arg1 != arg2; break;
1417 default: cmp = 0; break;
1418 }
1419 --ectx.ec_stack.ga_len;
1420 clear_tv(tv1);
1421 clear_tv(tv2);
1422 tv1->v_type = VAR_BOOL;
1423 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1424 }
1425 break;
1426
1427 case ISN_COMPAREBLOB:
1428 {
1429 typval_T *tv1 = STACK_TV_BOT(-2);
1430 typval_T *tv2 = STACK_TV_BOT(-1);
1431 blob_T *arg1 = tv1->vval.v_blob;
1432 blob_T *arg2 = tv2->vval.v_blob;
1433 int cmp = FALSE;
1434
1435 switch (iptr->isn_arg.op.op_type)
1436 {
1437 case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break;
1438 case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break;
1439 case EXPR_IS: cmp = arg1 == arg2; break;
1440 case EXPR_ISNOT: cmp = arg1 != arg2; break;
1441 default: cmp = 0; break;
1442 }
1443 --ectx.ec_stack.ga_len;
1444 clear_tv(tv1);
1445 clear_tv(tv2);
1446 tv1->v_type = VAR_BOOL;
1447 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1448 }
1449 break;
1450
1451 // TODO: handle separately
1452 case ISN_COMPARESTRING:
1453 case ISN_COMPAREDICT:
1454 case ISN_COMPAREFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001455 case ISN_COMPAREANY:
1456 {
1457 typval_T *tv1 = STACK_TV_BOT(-2);
1458 typval_T *tv2 = STACK_TV_BOT(-1);
1459 exptype_T exptype = iptr->isn_arg.op.op_type;
1460 int ic = iptr->isn_arg.op.op_ic;
1461
1462 typval_compare(tv1, tv2, exptype, ic);
1463 clear_tv(tv2);
1464 tv1->v_type = VAR_BOOL;
1465 tv1->vval.v_number = tv1->vval.v_number
1466 ? VVAL_TRUE : VVAL_FALSE;
1467 --ectx.ec_stack.ga_len;
1468 }
1469 break;
1470
1471 case ISN_ADDLIST:
1472 case ISN_ADDBLOB:
1473 {
1474 typval_T *tv1 = STACK_TV_BOT(-2);
1475 typval_T *tv2 = STACK_TV_BOT(-1);
1476
1477 if (iptr->isn_type == ISN_ADDLIST)
1478 eval_addlist(tv1, tv2);
1479 else
1480 eval_addblob(tv1, tv2);
1481 clear_tv(tv2);
1482 --ectx.ec_stack.ga_len;
1483 }
1484 break;
1485
1486 // Computation with two arguments of unknown type
1487 case ISN_OPANY:
1488 {
1489 typval_T *tv1 = STACK_TV_BOT(-2);
1490 typval_T *tv2 = STACK_TV_BOT(-1);
1491 varnumber_T n1, n2;
1492#ifdef FEAT_FLOAT
1493 float_T f1 = 0, f2 = 0;
1494#endif
1495 int error = FALSE;
1496
1497 if (iptr->isn_arg.op.op_type == EXPR_ADD)
1498 {
1499 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
1500 {
1501 eval_addlist(tv1, tv2);
1502 clear_tv(tv2);
1503 --ectx.ec_stack.ga_len;
1504 break;
1505 }
1506 else if (tv1->v_type == VAR_BLOB
1507 && tv2->v_type == VAR_BLOB)
1508 {
1509 eval_addblob(tv1, tv2);
1510 clear_tv(tv2);
1511 --ectx.ec_stack.ga_len;
1512 break;
1513 }
1514 }
1515#ifdef FEAT_FLOAT
1516 if (tv1->v_type == VAR_FLOAT)
1517 {
1518 f1 = tv1->vval.v_float;
1519 n1 = 0;
1520 }
1521 else
1522#endif
1523 {
1524 n1 = tv_get_number_chk(tv1, &error);
1525 if (error)
1526 goto failed;
1527#ifdef FEAT_FLOAT
1528 if (tv2->v_type == VAR_FLOAT)
1529 f1 = n1;
1530#endif
1531 }
1532#ifdef FEAT_FLOAT
1533 if (tv2->v_type == VAR_FLOAT)
1534 {
1535 f2 = tv2->vval.v_float;
1536 n2 = 0;
1537 }
1538 else
1539#endif
1540 {
1541 n2 = tv_get_number_chk(tv2, &error);
1542 if (error)
1543 goto failed;
1544#ifdef FEAT_FLOAT
1545 if (tv1->v_type == VAR_FLOAT)
1546 f2 = n2;
1547#endif
1548 }
1549#ifdef FEAT_FLOAT
1550 // if there is a float on either side the result is a float
1551 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
1552 {
1553 switch (iptr->isn_arg.op.op_type)
1554 {
1555 case EXPR_MULT: f1 = f1 * f2; break;
1556 case EXPR_DIV: f1 = f1 / f2; break;
1557 case EXPR_SUB: f1 = f1 - f2; break;
1558 case EXPR_ADD: f1 = f1 + f2; break;
1559 default: emsg(_(e_modulus)); goto failed;
1560 }
1561 clear_tv(tv1);
1562 clear_tv(tv2);
1563 tv1->v_type = VAR_FLOAT;
1564 tv1->vval.v_float = f1;
1565 --ectx.ec_stack.ga_len;
1566 }
1567 else
1568#endif
1569 {
1570 switch (iptr->isn_arg.op.op_type)
1571 {
1572 case EXPR_MULT: n1 = n1 * n2; break;
1573 case EXPR_DIV: n1 = num_divide(n1, n2); break;
1574 case EXPR_SUB: n1 = n1 - n2; break;
1575 case EXPR_ADD: n1 = n1 + n2; break;
1576 default: n1 = num_modulus(n1, n2); break;
1577 }
1578 clear_tv(tv1);
1579 clear_tv(tv2);
1580 tv1->v_type = VAR_NUMBER;
1581 tv1->vval.v_number = n1;
1582 --ectx.ec_stack.ga_len;
1583 }
1584 }
1585 break;
1586
1587 case ISN_CONCAT:
1588 {
1589 char_u *str1 = STACK_TV_BOT(-2)->vval.v_string;
1590 char_u *str2 = STACK_TV_BOT(-1)->vval.v_string;
1591 char_u *res;
1592
1593 res = concat_str(str1, str2);
1594 clear_tv(STACK_TV_BOT(-2));
1595 clear_tv(STACK_TV_BOT(-1));
1596 --ectx.ec_stack.ga_len;
1597 STACK_TV_BOT(-1)->vval.v_string = res;
1598 }
1599 break;
1600
1601 case ISN_INDEX:
1602 {
1603 list_T *list;
1604 varnumber_T n;
1605 listitem_T *li;
1606
1607 // list index: list is at stack-2, index at stack-1
1608 tv = STACK_TV_BOT(-2);
1609 if (tv->v_type != VAR_LIST)
1610 {
1611 emsg(_(e_listreq));
1612 goto failed;
1613 }
1614 list = tv->vval.v_list;
1615
1616 tv = STACK_TV_BOT(-1);
1617 if (tv->v_type != VAR_NUMBER)
1618 {
1619 emsg(_(e_number_exp));
1620 goto failed;
1621 }
1622 n = tv->vval.v_number;
1623 clear_tv(tv);
1624 if ((li = list_find(list, n)) == NULL)
1625 {
1626 semsg(_(e_listidx), n);
1627 goto failed;
1628 }
1629 --ectx.ec_stack.ga_len;
1630 clear_tv(STACK_TV_BOT(-1));
1631 copy_tv(&li->li_tv, STACK_TV_BOT(-1));
1632 }
1633 break;
1634
1635 // dict member with string key
1636 case ISN_MEMBER:
1637 {
1638 dict_T *dict;
1639 dictitem_T *di;
1640
1641 tv = STACK_TV_BOT(-1);
1642 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
1643 {
1644 emsg(_(e_dictreq));
1645 goto failed;
1646 }
1647 dict = tv->vval.v_dict;
1648
1649 if ((di = dict_find(dict, iptr->isn_arg.string, -1))
1650 == NULL)
1651 {
1652 semsg(_(e_dictkey), iptr->isn_arg.string);
1653 goto failed;
1654 }
1655 clear_tv(tv);
1656 copy_tv(&di->di_tv, tv);
1657 }
1658 break;
1659
1660 case ISN_NEGATENR:
1661 tv = STACK_TV_BOT(-1);
Bram Moolenaarc58164c2020-03-29 18:40:30 +02001662 if (tv->v_type != VAR_NUMBER
1663#ifdef FEAT_FLOAT
1664 && tv->v_type != VAR_FLOAT
1665#endif
1666 )
1667 {
1668 emsg(_(e_number_exp));
1669 goto failed;
1670 }
1671#ifdef FEAT_FLOAT
1672 if (tv->v_type == VAR_FLOAT)
1673 tv->vval.v_float = -tv->vval.v_float;
1674 else
1675#endif
1676 tv->vval.v_number = -tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001677 break;
1678
1679 case ISN_CHECKNR:
1680 {
1681 int error = FALSE;
1682
1683 tv = STACK_TV_BOT(-1);
1684 if (check_not_string(tv) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001685 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001686 (void)tv_get_number_chk(tv, &error);
1687 if (error)
1688 goto failed;
1689 }
1690 break;
1691
1692 case ISN_CHECKTYPE:
1693 {
1694 checktype_T *ct = &iptr->isn_arg.type;
1695
1696 tv = STACK_TV_BOT(ct->ct_off);
1697 if (tv->v_type != ct->ct_type)
1698 {
1699 semsg(_("E1029: Expected %s but got %s"),
1700 vartype_name(ct->ct_type),
1701 vartype_name(tv->v_type));
1702 goto failed;
1703 }
1704 }
1705 break;
1706
1707 case ISN_2BOOL:
1708 {
1709 int n;
1710
1711 tv = STACK_TV_BOT(-1);
1712 n = tv2bool(tv);
1713 if (iptr->isn_arg.number) // invert
1714 n = !n;
1715 clear_tv(tv);
1716 tv->v_type = VAR_BOOL;
1717 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
1718 }
1719 break;
1720
1721 case ISN_2STRING:
1722 {
1723 char_u *str;
1724
1725 tv = STACK_TV_BOT(iptr->isn_arg.number);
1726 if (tv->v_type != VAR_STRING)
1727 {
1728 str = typval_tostring(tv);
1729 clear_tv(tv);
1730 tv->v_type = VAR_STRING;
1731 tv->vval.v_string = str;
1732 }
1733 }
1734 break;
1735
1736 case ISN_DROP:
1737 --ectx.ec_stack.ga_len;
1738 clear_tv(STACK_TV_BOT(0));
1739 break;
1740 }
1741 }
1742
1743done:
1744 // function finished, get result from the stack.
1745 tv = STACK_TV_BOT(-1);
1746 *rettv = *tv;
1747 tv->v_type = VAR_UNKNOWN;
1748 ret = OK;
1749
1750failed:
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001751 // When failed need to unwind the call stack.
1752 while (ectx.ec_frame != initial_frame_ptr)
1753 func_return(&ectx);
1754
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001755 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
1756 clear_tv(STACK_TV(idx));
1757 vim_free(ectx.ec_stack.ga_data);
Bram Moolenaar20431c92020-03-20 18:39:46 +01001758 vim_free(ectx.ec_trystack.ga_data);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001759 return ret;
1760}
1761
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001762/*
1763 * ":dissassemble".
Bram Moolenaar777770f2020-02-06 21:27:08 +01001764 * We don't really need this at runtime, but we do have tests that require it,
1765 * so always include this.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001766 */
1767 void
1768ex_disassemble(exarg_T *eap)
1769{
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001770 char_u *arg = eap->arg;
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001771 char_u *fname;
1772 ufunc_T *ufunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001773 dfunc_T *dfunc;
1774 isn_T *instr;
1775 int current;
1776 int line_idx = 0;
1777 int prev_current = 0;
1778
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001779 fname = trans_function_name(&arg, FALSE,
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001780 TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001781 if (fname == NULL)
1782 {
1783 semsg(_(e_invarg2), eap->arg);
1784 return;
1785 }
1786
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001787 ufunc = find_func(fname, NULL);
1788 vim_free(fname);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001789 if (ufunc == NULL)
1790 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01001791 semsg(_("E1061: Cannot find function %s"), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001792 return;
1793 }
1794 if (ufunc->uf_dfunc_idx < 0)
1795 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01001796 semsg(_("E1062: Function %s is not compiled"), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001797 return;
1798 }
1799 if (ufunc->uf_name_exp != NULL)
1800 msg((char *)ufunc->uf_name_exp);
1801 else
1802 msg((char *)ufunc->uf_name);
1803
1804 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
1805 instr = dfunc->df_instr;
1806 for (current = 0; current < dfunc->df_instr_count; ++current)
1807 {
1808 isn_T *iptr = &instr[current];
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001809 char *line;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001810
1811 while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len)
1812 {
1813 if (current > prev_current)
1814 {
1815 msg_puts("\n\n");
1816 prev_current = current;
1817 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001818 line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
1819 if (line != NULL)
1820 msg(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001821 }
1822
1823 switch (iptr->isn_type)
1824 {
1825 case ISN_EXEC:
1826 smsg("%4d EXEC %s", current, iptr->isn_arg.string);
1827 break;
1828 case ISN_ECHO:
1829 {
1830 echo_T *echo = &iptr->isn_arg.echo;
1831
1832 smsg("%4d %s %d", current,
1833 echo->echo_with_white ? "ECHO" : "ECHON",
1834 echo->echo_count);
1835 }
1836 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01001837 case ISN_EXECUTE:
Bram Moolenaar10827722020-03-23 22:53:22 +01001838 smsg("%4d EXECUTE %lld", current,
1839 (long long)(iptr->isn_arg.number));
Bram Moolenaarad39c092020-02-26 18:23:43 +01001840 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001841 case ISN_LOAD:
1842 if (iptr->isn_arg.number < 0)
1843 smsg("%4d LOAD arg[%lld]", current,
Bram Moolenaar10827722020-03-23 22:53:22 +01001844 (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001845 else
Bram Moolenaar10827722020-03-23 22:53:22 +01001846 smsg("%4d LOAD $%lld", current,
1847 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001848 break;
1849 case ISN_LOADV:
1850 smsg("%4d LOADV v:%s", current,
1851 get_vim_var_name(iptr->isn_arg.number));
1852 break;
1853 case ISN_LOADSCRIPT:
1854 {
1855 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001856 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001857 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1858 + iptr->isn_arg.script.script_idx;
1859
1860 smsg("%4d LOADSCRIPT %s from %s", current,
1861 sv->sv_name, si->sn_name);
1862 }
1863 break;
1864 case ISN_LOADS:
1865 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001866 scriptitem_T *si = SCRIPT_ITEM(
1867 iptr->isn_arg.loadstore.ls_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001868
1869 smsg("%4d LOADS s:%s from %s", current,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001870 iptr->isn_arg.loadstore.ls_name, si->sn_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001871 }
1872 break;
1873 case ISN_LOADG:
1874 smsg("%4d LOADG g:%s", current, iptr->isn_arg.string);
1875 break;
1876 case ISN_LOADOPT:
1877 smsg("%4d LOADOPT %s", current, iptr->isn_arg.string);
1878 break;
1879 case ISN_LOADENV:
1880 smsg("%4d LOADENV %s", current, iptr->isn_arg.string);
1881 break;
1882 case ISN_LOADREG:
Bram Moolenaar10827722020-03-23 22:53:22 +01001883 smsg("%4d LOADREG @%c", current, (int)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001884 break;
1885
1886 case ISN_STORE:
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001887 if (iptr->isn_arg.number < 0)
1888 smsg("%4d STORE arg[%lld]", current,
Bram Moolenaar10827722020-03-23 22:53:22 +01001889 (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001890 else
Bram Moolenaar10827722020-03-23 22:53:22 +01001891 smsg("%4d STORE $%lld", current,
1892 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001893 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001894 case ISN_STOREV:
1895 smsg("%4d STOREV v:%s", current,
1896 get_vim_var_name(iptr->isn_arg.number));
1897 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001898 case ISN_STOREG:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001899 smsg("%4d STOREG %s", current, iptr->isn_arg.string);
1900 break;
1901 case ISN_STORES:
1902 {
1903 scriptitem_T *si = SCRIPT_ITEM(
1904 iptr->isn_arg.loadstore.ls_sid);
1905
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001906 smsg("%4d STORES %s in %s", current,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001907 iptr->isn_arg.loadstore.ls_name, si->sn_name);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001908 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001909 break;
1910 case ISN_STORESCRIPT:
1911 {
1912 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001913 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001914 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1915 + iptr->isn_arg.script.script_idx;
1916
1917 smsg("%4d STORESCRIPT %s in %s", current,
1918 sv->sv_name, si->sn_name);
1919 }
1920 break;
1921 case ISN_STOREOPT:
1922 smsg("%4d STOREOPT &%s", current,
1923 iptr->isn_arg.storeopt.so_name);
1924 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001925 case ISN_STOREENV:
1926 smsg("%4d STOREENV $%s", current, iptr->isn_arg.string);
1927 break;
1928 case ISN_STOREREG:
Bram Moolenaar10827722020-03-23 22:53:22 +01001929 smsg("%4d STOREREG @%c", current, (int)iptr->isn_arg.number);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001930 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001931 case ISN_STORENR:
1932 smsg("%4d STORE %lld in $%d", current,
Bram Moolenaara471eea2020-03-04 22:20:26 +01001933 iptr->isn_arg.storenr.stnr_val,
1934 iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001935 break;
1936
1937 // constants
1938 case ISN_PUSHNR:
Bram Moolenaar10827722020-03-23 22:53:22 +01001939 smsg("%4d PUSHNR %lld", current,
1940 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001941 break;
1942 case ISN_PUSHBOOL:
1943 case ISN_PUSHSPEC:
1944 smsg("%4d PUSH %s", current,
1945 get_var_special_name(iptr->isn_arg.number));
1946 break;
1947 case ISN_PUSHF:
Bram Moolenaara5d59532020-01-26 21:42:03 +01001948#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001949 smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber);
Bram Moolenaara5d59532020-01-26 21:42:03 +01001950#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001951 break;
1952 case ISN_PUSHS:
1953 smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string);
1954 break;
1955 case ISN_PUSHBLOB:
1956 {
1957 char_u *r;
1958 char_u numbuf[NUMBUFLEN];
1959 char_u *tofree;
1960
1961 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01001962 smsg("%4d PUSHBLOB %s", current, r);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001963 vim_free(tofree);
1964 }
1965 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001966 case ISN_PUSHFUNC:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01001967 {
1968 char *name = (char *)iptr->isn_arg.string;
1969
1970 smsg("%4d PUSHFUNC \"%s\"", current,
1971 name == NULL ? "[none]" : name);
1972 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001973 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001974 case ISN_PUSHCHANNEL:
1975#ifdef FEAT_JOB_CHANNEL
1976 {
1977 channel_T *channel = iptr->isn_arg.channel;
1978
1979 smsg("%4d PUSHCHANNEL %d", current,
1980 channel == NULL ? 0 : channel->ch_id);
1981 }
1982#endif
1983 break;
1984 case ISN_PUSHJOB:
1985#ifdef FEAT_JOB_CHANNEL
1986 {
1987 typval_T tv;
1988 char_u *name;
1989
1990 tv.v_type = VAR_JOB;
1991 tv.vval.v_job = iptr->isn_arg.job;
1992 name = tv_get_string(&tv);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001993 smsg("%4d PUSHJOB \"%s\"", current, name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001994 }
1995#endif
1996 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001997 case ISN_PUSHEXC:
1998 smsg("%4d PUSH v:exception", current);
1999 break;
2000 case ISN_NEWLIST:
Bram Moolenaar10827722020-03-23 22:53:22 +01002001 smsg("%4d NEWLIST size %lld", current,
2002 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002003 break;
2004 case ISN_NEWDICT:
Bram Moolenaar10827722020-03-23 22:53:22 +01002005 smsg("%4d NEWDICT size %lld", current,
2006 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002007 break;
2008
2009 // function call
2010 case ISN_BCALL:
2011 {
2012 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc;
2013
2014 smsg("%4d BCALL %s(argc %d)", current,
2015 internal_func_name(cbfunc->cbf_idx),
2016 cbfunc->cbf_argcount);
2017 }
2018 break;
2019 case ISN_DCALL:
2020 {
2021 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc;
2022 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
2023 + cdfunc->cdf_idx;
2024
2025 smsg("%4d DCALL %s(argc %d)", current,
2026 df->df_ufunc->uf_name_exp != NULL
2027 ? df->df_ufunc->uf_name_exp
2028 : df->df_ufunc->uf_name, cdfunc->cdf_argcount);
2029 }
2030 break;
2031 case ISN_UCALL:
2032 {
2033 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
2034
2035 smsg("%4d UCALL %s(argc %d)", current,
2036 cufunc->cuf_name, cufunc->cuf_argcount);
2037 }
2038 break;
2039 case ISN_PCALL:
2040 {
2041 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc;
2042
2043 smsg("%4d PCALL%s (argc %d)", current,
2044 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
2045 }
2046 break;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02002047 case ISN_PCALL_END:
2048 smsg("%4d PCALL end", current);
2049 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002050 case ISN_RETURN:
2051 smsg("%4d RETURN", current);
2052 break;
2053 case ISN_FUNCREF:
2054 {
2055 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
2056 + iptr->isn_arg.number;
2057
2058 smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name);
2059 }
2060 break;
2061
2062 case ISN_JUMP:
2063 {
2064 char *when = "?";
2065
2066 switch (iptr->isn_arg.jump.jump_when)
2067 {
2068 case JUMP_ALWAYS:
2069 when = "JUMP";
2070 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002071 case JUMP_AND_KEEP_IF_TRUE:
2072 when = "JUMP_AND_KEEP_IF_TRUE";
2073 break;
2074 case JUMP_IF_FALSE:
2075 when = "JUMP_IF_FALSE";
2076 break;
2077 case JUMP_AND_KEEP_IF_FALSE:
2078 when = "JUMP_AND_KEEP_IF_FALSE";
2079 break;
2080 }
Bram Moolenaar8a677a32020-03-12 19:15:45 +01002081 smsg("%4d %s -> %d", current, when,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002082 iptr->isn_arg.jump.jump_where);
2083 }
2084 break;
2085
2086 case ISN_FOR:
2087 {
2088 forloop_T *forloop = &iptr->isn_arg.forloop;
2089
2090 smsg("%4d FOR $%d -> %d", current,
2091 forloop->for_idx, forloop->for_end);
2092 }
2093 break;
2094
2095 case ISN_TRY:
2096 {
2097 try_T *try = &iptr->isn_arg.try;
2098
2099 smsg("%4d TRY catch -> %d, finally -> %d", current,
2100 try->try_catch, try->try_finally);
2101 }
2102 break;
2103 case ISN_CATCH:
2104 // TODO
2105 smsg("%4d CATCH", current);
2106 break;
2107 case ISN_ENDTRY:
2108 smsg("%4d ENDTRY", current);
2109 break;
2110 case ISN_THROW:
2111 smsg("%4d THROW", current);
2112 break;
2113
2114 // expression operations on number
2115 case ISN_OPNR:
2116 case ISN_OPFLOAT:
2117 case ISN_OPANY:
2118 {
2119 char *what;
2120 char *ins;
2121
2122 switch (iptr->isn_arg.op.op_type)
2123 {
2124 case EXPR_MULT: what = "*"; break;
2125 case EXPR_DIV: what = "/"; break;
2126 case EXPR_REM: what = "%"; break;
2127 case EXPR_SUB: what = "-"; break;
2128 case EXPR_ADD: what = "+"; break;
2129 default: what = "???"; break;
2130 }
2131 switch (iptr->isn_type)
2132 {
2133 case ISN_OPNR: ins = "OPNR"; break;
2134 case ISN_OPFLOAT: ins = "OPFLOAT"; break;
2135 case ISN_OPANY: ins = "OPANY"; break;
2136 default: ins = "???"; break;
2137 }
2138 smsg("%4d %s %s", current, ins, what);
2139 }
2140 break;
2141
2142 case ISN_COMPAREBOOL:
2143 case ISN_COMPARESPECIAL:
2144 case ISN_COMPARENR:
2145 case ISN_COMPAREFLOAT:
2146 case ISN_COMPARESTRING:
2147 case ISN_COMPAREBLOB:
2148 case ISN_COMPARELIST:
2149 case ISN_COMPAREDICT:
2150 case ISN_COMPAREFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002151 case ISN_COMPAREANY:
2152 {
2153 char *p;
2154 char buf[10];
2155 char *type;
2156
2157 switch (iptr->isn_arg.op.op_type)
2158 {
2159 case EXPR_EQUAL: p = "=="; break;
2160 case EXPR_NEQUAL: p = "!="; break;
2161 case EXPR_GREATER: p = ">"; break;
2162 case EXPR_GEQUAL: p = ">="; break;
2163 case EXPR_SMALLER: p = "<"; break;
2164 case EXPR_SEQUAL: p = "<="; break;
2165 case EXPR_MATCH: p = "=~"; break;
2166 case EXPR_IS: p = "is"; break;
2167 case EXPR_ISNOT: p = "isnot"; break;
2168 case EXPR_NOMATCH: p = "!~"; break;
2169 default: p = "???"; break;
2170 }
2171 STRCPY(buf, p);
2172 if (iptr->isn_arg.op.op_ic == TRUE)
2173 strcat(buf, "?");
2174 switch(iptr->isn_type)
2175 {
2176 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
2177 case ISN_COMPARESPECIAL:
2178 type = "COMPARESPECIAL"; break;
2179 case ISN_COMPARENR: type = "COMPARENR"; break;
2180 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
2181 case ISN_COMPARESTRING:
2182 type = "COMPARESTRING"; break;
2183 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
2184 case ISN_COMPARELIST: type = "COMPARELIST"; break;
2185 case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
2186 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002187 case ISN_COMPAREANY: type = "COMPAREANY"; break;
2188 default: type = "???"; break;
2189 }
2190
2191 smsg("%4d %s %s", current, type, buf);
2192 }
2193 break;
2194
2195 case ISN_ADDLIST: smsg("%4d ADDLIST", current); break;
2196 case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break;
2197
2198 // expression operations
2199 case ISN_CONCAT: smsg("%4d CONCAT", current); break;
2200 case ISN_INDEX: smsg("%4d INDEX", current); break;
2201 case ISN_MEMBER: smsg("%4d MEMBER %s", current,
2202 iptr->isn_arg.string); break;
2203 case ISN_NEGATENR: smsg("%4d NEGATENR", current); break;
2204
2205 case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
2206 case ISN_CHECKTYPE: smsg("%4d CHECKTYPE %s stack[%d]", current,
2207 vartype_name(iptr->isn_arg.type.ct_type),
2208 iptr->isn_arg.type.ct_off);
2209 break;
2210 case ISN_2BOOL: if (iptr->isn_arg.number)
2211 smsg("%4d INVERT (!val)", current);
2212 else
2213 smsg("%4d 2BOOL (!!val)", current);
2214 break;
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002215 case ISN_2STRING: smsg("%4d 2STRING stack[%lld]", current,
2216 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002217 break;
2218
2219 case ISN_DROP: smsg("%4d DROP", current); break;
2220 }
2221 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002222}
2223
2224/*
2225 * Return TRUE when "tv" is not falsey: non-zero, non-empty string, non-empty
2226 * list, etc. Mostly like what JavaScript does, except that empty list and
2227 * empty dictionary are FALSE.
2228 */
2229 int
2230tv2bool(typval_T *tv)
2231{
2232 switch (tv->v_type)
2233 {
2234 case VAR_NUMBER:
2235 return tv->vval.v_number != 0;
2236 case VAR_FLOAT:
2237#ifdef FEAT_FLOAT
2238 return tv->vval.v_float != 0.0;
2239#else
2240 break;
2241#endif
2242 case VAR_PARTIAL:
2243 return tv->vval.v_partial != NULL;
2244 case VAR_FUNC:
2245 case VAR_STRING:
2246 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
2247 case VAR_LIST:
2248 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
2249 case VAR_DICT:
2250 return tv->vval.v_dict != NULL
2251 && tv->vval.v_dict->dv_hashtab.ht_used > 0;
2252 case VAR_BOOL:
2253 case VAR_SPECIAL:
2254 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
2255 case VAR_JOB:
2256#ifdef FEAT_JOB_CHANNEL
2257 return tv->vval.v_job != NULL;
2258#else
2259 break;
2260#endif
2261 case VAR_CHANNEL:
2262#ifdef FEAT_JOB_CHANNEL
2263 return tv->vval.v_channel != NULL;
2264#else
2265 break;
2266#endif
2267 case VAR_BLOB:
2268 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
2269 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02002270 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002271 case VAR_VOID:
2272 break;
2273 }
2274 return FALSE;
2275}
2276
2277/*
2278 * If "tv" is a string give an error and return FAIL.
2279 */
2280 int
2281check_not_string(typval_T *tv)
2282{
2283 if (tv->v_type == VAR_STRING)
2284 {
2285 emsg(_("E1030: Using a String as a Number"));
2286 clear_tv(tv);
2287 return FAIL;
2288 }
2289 return OK;
2290}
2291
2292
2293#endif // FEAT_EVAL