blob: 310be87f7e8dcb7c375e32bb34eb6bfd3c0d3e1b [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
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200123call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100124{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200125 int argcount = argcount_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100126 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx;
127 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200128 int arg_to_add;
129 int vararg_count = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100130 int idx;
131
132 if (dfunc->df_deleted)
133 {
134 emsg_funcname(e_func_deleted, ufunc->uf_name);
135 return FAIL;
136 }
137
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200138 if (ufunc->uf_va_name != NULL)
139 {
140 int iidx;
141 isn_T *iptr;
142
143 // Need to make a list out of the vararg arguments. There is a
144 // ISN_NEWLIST instruction at the start of the function body, we need
145 // to move the arguments below the stack frame and pass the count.
146 // Stack at time of call with 2 varargs:
147 // normal_arg
148 // optional_arg
149 // vararg_1
150 // vararg_2
151 // When starting execution:
152 // normal_arg
153 // optional_arg
154 // space list of varargs
155 // STACK_FRAME
156 // [local variables]
157 // vararg_1
158 // vararg_2
159 // TODO: This doesn't work if the same function is used for a default
160 // argument value. Forbid that somehow?
161 vararg_count = argcount - ufunc->uf_args.ga_len;
162 if (vararg_count < 0)
163 vararg_count = 0;
164 else
165 argcount -= vararg_count;
166 if (ufunc->uf_def_arg_idx == NULL)
167 iidx = 0;
168 else
169 iidx = ufunc->uf_def_arg_idx[ufunc->uf_def_args.ga_len];
170 iptr = &dfunc->df_instr[iidx];
171 if (iptr->isn_type != ISN_NEWLIST)
172 {
173 iemsg("Not a ISN_NEWLIST instruction");
174 return FAIL;
175 }
176 iptr->isn_arg.number = vararg_count;
177 }
178
179 arg_to_add = ufunc_argcount(ufunc) - argcount;
180 if (arg_to_add < 0)
181 {
182 iemsg("Argument count wrong?");
183 return FAIL;
184 }
185 if (ga_grow(&ectx->ec_stack, arg_to_add + 3 + dfunc->df_varcount) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100186 return FAIL;
187
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200188 if (vararg_count > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100189 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200190 int stack_added = arg_to_add + STACK_FRAME_SIZE + dfunc->df_varcount;
191
192 // Move the varargs to below the stack frame.
193 // TODO: use mch_memmove()
194 for (idx = 1; idx <= vararg_count; ++idx)
195 *STACK_TV_BOT(stack_added - idx) = *STACK_TV_BOT(-idx);
196 ectx->ec_stack.ga_len -= vararg_count;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100197 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100198
199 // Reserve space for omitted optional arguments, filled in soon.
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200200 // Also room for a list of varargs, if there is one.
201 for (idx = 0; idx < arg_to_add; ++idx)
202 STACK_TV_BOT(idx)->v_type = VAR_UNKNOWN;
203 ectx->ec_stack.ga_len += arg_to_add;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100204
205 // Store current execution state in stack frame for ISN_RETURN.
206 // TODO: If the actual number of arguments doesn't match what the called
207 // function expects things go bad.
208 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx;
209 STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx;
210 STACK_TV_BOT(2)->vval.v_number = ectx->ec_frame;
211 ectx->ec_frame = ectx->ec_stack.ga_len;
212
213 // Initialize local variables
214 for (idx = 0; idx < dfunc->df_varcount; ++idx)
215 STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200216 ectx->ec_stack.ga_len += STACK_FRAME_SIZE + dfunc->df_varcount
217 + vararg_count;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100218
219 // Set execution state to the start of the called function.
220 ectx->ec_dfunc_idx = cdf_idx;
221 ectx->ec_instr = dfunc->df_instr;
222 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100223
224 // Decide where to start execution, handles optional arguments.
225 init_instr_idx(ufunc, argcount, ectx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100226
227 return OK;
228}
229
230// Get pointer to item in the stack.
231#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
232
233/*
234 * Return from the current function.
235 */
236 static void
237func_return(ectx_T *ectx)
238{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100239 int idx;
240 dfunc_T *dfunc;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100241 int top;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100242
243 // execution context goes one level up
244 estack_pop();
245
246 // Clear the local variables and temporary values, but not
247 // the return value.
248 for (idx = ectx->ec_frame + STACK_FRAME_SIZE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100249 idx < ectx->ec_stack.ga_len - 1; ++idx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100250 clear_tv(STACK_TV(idx));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100251
252 // Clear the arguments.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100253 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100254 top = ectx->ec_frame - ufunc_argcount(dfunc->df_ufunc);
255 for (idx = top; idx < ectx->ec_frame; ++idx)
256 clear_tv(STACK_TV(idx));
257
258 // Restore the previous frame.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100259 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame)->vval.v_number;
260 ectx->ec_iidx = STACK_TV(ectx->ec_frame + 1)->vval.v_number;
261 ectx->ec_frame = STACK_TV(ectx->ec_frame + 2)->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100262 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
263 ectx->ec_instr = dfunc->df_instr;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100264
265 // Reset the stack to the position before the call, move the return value
266 // to the top of the stack.
267 idx = ectx->ec_stack.ga_len - 1;
268 ectx->ec_stack.ga_len = top + 1;
269 *STACK_TV_BOT(-1) = *STACK_TV(idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100270}
271
272#undef STACK_TV
273
274/*
275 * Prepare arguments and rettv for calling a builtin or user function.
276 */
277 static int
278call_prepare(int argcount, typval_T *argvars, ectx_T *ectx)
279{
280 int idx;
281 typval_T *tv;
282
283 // Move arguments from bottom of the stack to argvars[] and add terminator.
284 for (idx = 0; idx < argcount; ++idx)
285 argvars[idx] = *STACK_TV_BOT(idx - argcount);
286 argvars[argcount].v_type = VAR_UNKNOWN;
287
288 // Result replaces the arguments on the stack.
289 if (argcount > 0)
290 ectx->ec_stack.ga_len -= argcount - 1;
291 else if (ga_grow(&ectx->ec_stack, 1) == FAIL)
292 return FAIL;
293 else
294 ++ectx->ec_stack.ga_len;
295
296 // Default return value is zero.
297 tv = STACK_TV_BOT(-1);
298 tv->v_type = VAR_NUMBER;
299 tv->vval.v_number = 0;
300
301 return OK;
302}
303
304/*
305 * Call a builtin function by index.
306 */
307 static int
308call_bfunc(int func_idx, int argcount, ectx_T *ectx)
309{
310 typval_T argvars[MAX_FUNC_ARGS];
311 int idx;
312
313 if (call_prepare(argcount, argvars, ectx) == FAIL)
314 return FAIL;
315
316 // Call the builtin function.
317 call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1));
318
319 // Clear the arguments.
320 for (idx = 0; idx < argcount; ++idx)
321 clear_tv(&argvars[idx]);
322 return OK;
323}
324
325/*
326 * Execute a user defined function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100327 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100328 */
329 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100330call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100331{
332 typval_T argvars[MAX_FUNC_ARGS];
333 funcexe_T funcexe;
334 int error;
335 int idx;
336
337 if (ufunc->uf_dfunc_idx >= 0)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100338 {
339 // The function has been compiled, can call it quickly. For a function
340 // that was defined later: we can call it directly next time.
341 if (iptr != NULL)
342 {
Bram Moolenaar20431c92020-03-20 18:39:46 +0100343 delete_instr(iptr);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100344 iptr->isn_type = ISN_DCALL;
345 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
346 iptr->isn_arg.dfunc.cdf_argcount = argcount;
347 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100348 return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx);
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100349 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100350
351 if (call_prepare(argcount, argvars, ectx) == FAIL)
352 return FAIL;
353 vim_memset(&funcexe, 0, sizeof(funcexe));
354 funcexe.evaluate = TRUE;
355
356 // Call the user function. Result goes in last position on the stack.
357 // TODO: add selfdict if there is one
358 error = call_user_func_check(ufunc, argcount, argvars,
359 STACK_TV_BOT(-1), &funcexe, NULL);
360
361 // Clear the arguments.
362 for (idx = 0; idx < argcount; ++idx)
363 clear_tv(&argvars[idx]);
364
365 if (error != FCERR_NONE)
366 {
367 user_func_error(error, ufunc->uf_name);
368 return FAIL;
369 }
370 return OK;
371}
372
373/*
374 * Execute a function by "name".
375 * This can be a builtin function or a user function.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100376 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100377 * Returns FAIL if not found without an error message.
378 */
379 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100380call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100381{
382 ufunc_T *ufunc;
383
384 if (builtin_function(name, -1))
385 {
386 int func_idx = find_internal_func(name);
387
388 if (func_idx < 0)
389 return FAIL;
390 if (check_internal_func(func_idx, argcount) == FAIL)
391 return FAIL;
392 return call_bfunc(func_idx, argcount, ectx);
393 }
394
395 ufunc = find_func(name, NULL);
396 if (ufunc != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100397 return call_ufunc(ufunc, argcount, ectx, iptr);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100398
399 return FAIL;
400}
401
402 static int
403call_partial(typval_T *tv, int argcount, ectx_T *ectx)
404{
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200405 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100406 int called_emsg_before = called_emsg;
407
408 if (tv->v_type == VAR_PARTIAL)
409 {
410 partial_T *pt = tv->vval.v_partial;
411
412 if (pt->pt_func != NULL)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100413 return call_ufunc(pt->pt_func, argcount, ectx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100414 name = pt->pt_name;
415 }
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200416 else if (tv->v_type == VAR_FUNC)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100417 name = tv->vval.v_string;
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200418 if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100419 {
420 if (called_emsg == called_emsg_before)
421 semsg(_(e_unknownfunc), name);
422 return FAIL;
423 }
424 return OK;
425}
426
427/*
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100428 * Store "tv" in variable "name".
429 * This is for s: and g: variables.
430 */
431 static void
432store_var(char_u *name, typval_T *tv)
433{
434 funccal_entry_T entry;
435
436 save_funccal(&entry);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200437 set_var_const(name, NULL, tv, FALSE, LET_NO_COMMAND);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100438 restore_funccal();
439}
440
441/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100442 * Execute a function by "name".
443 * This can be a builtin function, user function or a funcref.
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100444 * "iptr" can be used to replace the instruction with a more efficient one.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100445 */
446 static int
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100447call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100448{
449 int called_emsg_before = called_emsg;
450
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100451 if (call_by_name(name, argcount, ectx, iptr) == FAIL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100452 && called_emsg == called_emsg_before)
453 {
454 // "name" may be a variable that is a funcref or partial
455 // if find variable
456 // call_partial()
457 // else
458 // semsg(_(e_unknownfunc), name);
459 emsg("call_eval_func(partial) not implemented yet");
460 return FAIL;
461 }
462 return OK;
463}
464
465/*
466 * Call a "def" function from old Vim script.
467 * Return OK or FAIL.
468 */
469 int
470call_def_function(
471 ufunc_T *ufunc,
472 int argc, // nr of arguments
473 typval_T *argv, // arguments
474 typval_T *rettv) // return value
475{
476 ectx_T ectx; // execution context
477 int initial_frame_ptr;
478 typval_T *tv;
479 int idx;
480 int ret = FAIL;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100481 int defcount = ufunc->uf_args.ga_len - argc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100482
483// Get pointer to item in the stack.
484#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
485
486// Get pointer to item at the bottom of the stack, -1 is the bottom.
487#undef STACK_TV_BOT
488#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
489
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200490// Get pointer to a local variable on the stack. Negative for arguments.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100491#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame + STACK_FRAME_SIZE + idx)
492
493 vim_memset(&ectx, 0, sizeof(ectx));
494 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
495 if (ga_grow(&ectx.ec_stack, 20) == FAIL)
Bram Moolenaard5aec0c2020-02-27 21:48:51 +0100496 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100497 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
498
499 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
500
501 // Put arguments on the stack.
502 for (idx = 0; idx < argc; ++idx)
503 {
504 copy_tv(&argv[idx], STACK_TV_BOT(0));
505 ++ectx.ec_stack.ga_len;
506 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100507 // Make space for omitted arguments, will store default value below.
508 if (defcount > 0)
509 for (idx = 0; idx < defcount; ++idx)
510 {
511 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
512 ++ectx.ec_stack.ga_len;
513 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100514
515 // Frame pointer points to just after arguments.
516 ectx.ec_frame = ectx.ec_stack.ga_len;
517 initial_frame_ptr = ectx.ec_frame;
518
519 // dummy frame entries
520 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
521 {
522 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
523 ++ectx.ec_stack.ga_len;
524 }
525
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200526 {
527 // Reserve space for local variables.
528 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
529 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100530
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200531 for (idx = 0; idx < dfunc->df_varcount; ++idx)
532 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
533 ectx.ec_stack.ga_len += dfunc->df_varcount;
534
535 ectx.ec_instr = dfunc->df_instr;
536 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100537
538 // Decide where to start execution, handles optional arguments.
539 init_instr_idx(ufunc, argc, &ectx);
540
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100541 for (;;)
542 {
543 isn_T *iptr;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100544
545 veryfast_breakcheck();
546 if (got_int)
547 {
548 // Turn CTRL-C into an exception.
549 got_int = FALSE;
Bram Moolenaar97acfc72020-03-22 13:44:28 +0100550 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL)
Bram Moolenaar20431c92020-03-20 18:39:46 +0100551 goto failed;
552 did_throw = TRUE;
553 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100554
555 if (did_throw && !ectx.ec_in_catch)
556 {
557 garray_T *trystack = &ectx.ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100558 trycmd_T *trycmd = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100559
560 // An exception jumps to the first catch, finally, or returns from
561 // the current function.
562 if (trystack->ga_len > 0)
563 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1;
564 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame)
565 {
566 // jump to ":catch" or ":finally"
567 ectx.ec_in_catch = TRUE;
568 ectx.ec_iidx = trycmd->tcd_catch_idx;
569 }
570 else
571 {
572 // not inside try or need to return from current functions.
573 if (ectx.ec_frame == initial_frame_ptr)
574 {
575 // At the toplevel we are done. Push a dummy return value.
576 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
577 goto failed;
578 tv = STACK_TV_BOT(0);
579 tv->v_type = VAR_NUMBER;
580 tv->vval.v_number = 0;
581 ++ectx.ec_stack.ga_len;
Bram Moolenaar257cc5e2020-02-19 17:06:11 +0100582 need_rethrow = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100583 goto done;
584 }
585
586 func_return(&ectx);
587 }
588 continue;
589 }
590
591 iptr = &ectx.ec_instr[ectx.ec_iidx++];
592 switch (iptr->isn_type)
593 {
594 // execute Ex command line
595 case ISN_EXEC:
596 do_cmdline_cmd(iptr->isn_arg.string);
597 break;
598
599 // execute :echo {string} ...
600 case ISN_ECHO:
601 {
602 int count = iptr->isn_arg.echo.echo_count;
603 int atstart = TRUE;
604 int needclr = TRUE;
605
606 for (idx = 0; idx < count; ++idx)
607 {
608 tv = STACK_TV_BOT(idx - count);
609 echo_one(tv, iptr->isn_arg.echo.echo_with_white,
610 &atstart, &needclr);
611 clear_tv(tv);
612 }
Bram Moolenaare0807ea2020-02-20 22:18:06 +0100613 if (needclr)
614 msg_clr_eos();
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100615 ectx.ec_stack.ga_len -= count;
616 }
617 break;
618
Bram Moolenaarad39c092020-02-26 18:23:43 +0100619 // execute :execute {string} ...
620 case ISN_EXECUTE:
621 {
622 int count = iptr->isn_arg.number;
623 garray_T ga;
624 char_u buf[NUMBUFLEN];
625 char_u *p;
626 int len;
627 int failed = FALSE;
628
629 ga_init2(&ga, 1, 80);
630 for (idx = 0; idx < count; ++idx)
631 {
632 tv = STACK_TV_BOT(idx - count);
633 if (tv->v_type == VAR_CHANNEL || tv->v_type == VAR_JOB)
634 {
635 emsg(_(e_inval_string));
636 break;
637 }
638 else
639 p = tv_get_string_buf(tv, buf);
640
641 len = (int)STRLEN(p);
642 if (ga_grow(&ga, len + 2) == FAIL)
643 failed = TRUE;
644 else
645 {
646 if (ga.ga_len > 0)
647 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
648 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
649 ga.ga_len += len;
650 }
651 clear_tv(tv);
652 }
653 ectx.ec_stack.ga_len -= count;
654
655 if (!failed && ga.ga_data != NULL)
656 do_cmdline_cmd((char_u *)ga.ga_data);
657 ga_clear(&ga);
658 }
659 break;
660
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100661 // load local variable or argument
662 case ISN_LOAD:
663 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
664 goto failed;
665 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
666 ++ectx.ec_stack.ga_len;
667 break;
668
669 // load v: variable
670 case ISN_LOADV:
671 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
672 goto failed;
673 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
674 ++ectx.ec_stack.ga_len;
675 break;
676
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100677 // load s: variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100678 case ISN_LOADSCRIPT:
679 {
680 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +0100681 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100682 svar_T *sv;
683
684 sv = ((svar_T *)si->sn_var_vals.ga_data)
685 + iptr->isn_arg.script.script_idx;
686 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
687 goto failed;
688 copy_tv(sv->sv_tv, STACK_TV_BOT(0));
689 ++ectx.ec_stack.ga_len;
690 }
691 break;
692
693 // load s: variable in old script
694 case ISN_LOADS:
695 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100696 hashtab_T *ht = &SCRIPT_VARS(
697 iptr->isn_arg.loadstore.ls_sid);
698 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100699 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100700
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100701 if (di == NULL)
702 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100703 semsg(_(e_undefvar), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100704 goto failed;
705 }
706 else
707 {
708 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
709 goto failed;
710 copy_tv(&di->di_tv, STACK_TV_BOT(0));
711 ++ectx.ec_stack.ga_len;
712 }
713 }
714 break;
715
716 // load g: variable
717 case ISN_LOADG:
718 {
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100719 dictitem_T *di = find_var_in_ht(get_globvar_ht(), 0,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100720 iptr->isn_arg.string, TRUE);
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100721
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100722 if (di == NULL)
723 {
724 semsg(_("E121: Undefined variable: g:%s"),
725 iptr->isn_arg.string);
726 goto failed;
727 }
728 else
729 {
730 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
731 goto failed;
732 copy_tv(&di->di_tv, STACK_TV_BOT(0));
733 ++ectx.ec_stack.ga_len;
734 }
735 }
736 break;
737
738 // load &option
739 case ISN_LOADOPT:
740 {
741 typval_T optval;
742 char_u *name = iptr->isn_arg.string;
743
Bram Moolenaara8c17702020-04-01 21:17:24 +0200744 // This is not expected to fail, name is checked during
745 // compilation: don't set SOURCING_LNUM.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100746 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
747 goto failed;
Bram Moolenaar58ceca52020-01-28 22:46:22 +0100748 if (get_option_tv(&name, &optval, TRUE) == FAIL)
749 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100750 *STACK_TV_BOT(0) = optval;
751 ++ectx.ec_stack.ga_len;
752 }
753 break;
754
755 // load $ENV
756 case ISN_LOADENV:
757 {
758 typval_T optval;
759 char_u *name = iptr->isn_arg.string;
760
761 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
762 goto failed;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100763 // name is always valid, checked when compiling
764 (void)get_env_tv(&name, &optval, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100765 *STACK_TV_BOT(0) = optval;
766 ++ectx.ec_stack.ga_len;
767 }
768 break;
769
770 // load @register
771 case ISN_LOADREG:
772 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
773 goto failed;
774 tv = STACK_TV_BOT(0);
775 tv->v_type = VAR_STRING;
776 tv->vval.v_string = get_reg_contents(
777 iptr->isn_arg.number, GREG_EXPR_SRC);
778 ++ectx.ec_stack.ga_len;
779 break;
780
781 // store local variable
782 case ISN_STORE:
783 --ectx.ec_stack.ga_len;
784 tv = STACK_TV_VAR(iptr->isn_arg.number);
785 clear_tv(tv);
786 *tv = *STACK_TV_BOT(0);
787 break;
788
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100789 // store s: variable in old script
790 case ISN_STORES:
791 {
792 hashtab_T *ht = &SCRIPT_VARS(
793 iptr->isn_arg.loadstore.ls_sid);
794 char_u *name = iptr->isn_arg.loadstore.ls_name;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100795 dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100796
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100797 --ectx.ec_stack.ga_len;
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100798 if (di == NULL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200799 store_var(name, STACK_TV_BOT(0));
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100800 else
801 {
802 clear_tv(&di->di_tv);
803 di->di_tv = *STACK_TV_BOT(0);
804 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100805 }
806 break;
807
808 // store script-local variable in Vim9 script
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100809 case ISN_STORESCRIPT:
810 {
Bram Moolenaar21b9e972020-01-26 19:26:46 +0100811 scriptitem_T *si = SCRIPT_ITEM(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100812 iptr->isn_arg.script.script_sid);
813 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
814 + iptr->isn_arg.script.script_idx;
815
816 --ectx.ec_stack.ga_len;
817 clear_tv(sv->sv_tv);
818 *sv->sv_tv = *STACK_TV_BOT(0);
819 }
820 break;
821
822 // store option
823 case ISN_STOREOPT:
824 {
825 long n = 0;
826 char_u *s = NULL;
827 char *msg;
828
829 --ectx.ec_stack.ga_len;
830 tv = STACK_TV_BOT(0);
831 if (tv->v_type == VAR_STRING)
Bram Moolenaar97a2af32020-01-28 22:52:48 +0100832 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100833 s = tv->vval.v_string;
Bram Moolenaar97a2af32020-01-28 22:52:48 +0100834 if (s == NULL)
835 s = (char_u *)"";
836 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100837 else if (tv->v_type == VAR_NUMBER)
838 n = tv->vval.v_number;
839 else
840 {
841 emsg(_("E1051: Expected string or number"));
842 goto failed;
843 }
844 msg = set_option_value(iptr->isn_arg.storeopt.so_name,
845 n, s, iptr->isn_arg.storeopt.so_flags);
846 if (msg != NULL)
847 {
848 emsg(_(msg));
849 goto failed;
850 }
851 clear_tv(tv);
852 }
853 break;
854
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100855 // store $ENV
856 case ISN_STOREENV:
857 --ectx.ec_stack.ga_len;
Bram Moolenaar20431c92020-03-20 18:39:46 +0100858 tv = STACK_TV_BOT(0);
859 vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
860 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100861 break;
862
863 // store @r
864 case ISN_STOREREG:
865 {
866 int reg = iptr->isn_arg.number;
867
868 --ectx.ec_stack.ga_len;
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100869 tv = STACK_TV_BOT(0);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100870 write_reg_contents(reg == '@' ? '"' : reg,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100871 tv_get_string(tv), -1, FALSE);
872 clear_tv(tv);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100873 }
874 break;
875
876 // store v: variable
877 case ISN_STOREV:
878 --ectx.ec_stack.ga_len;
879 if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
880 == FAIL)
881 goto failed;
882 break;
883
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100884 // store g: variable
885 case ISN_STOREG:
886 {
887 dictitem_T *di;
888
889 --ectx.ec_stack.ga_len;
890 di = find_var_in_ht(get_globvar_ht(), 0,
Bram Moolenaar401d9ff2020-02-19 18:14:44 +0100891 iptr->isn_arg.string + 2, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100892 if (di == NULL)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +0100893 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100894 else
895 {
896 clear_tv(&di->di_tv);
897 di->di_tv = *STACK_TV_BOT(0);
898 }
899 }
900 break;
901
902 // store number in local variable
903 case ISN_STORENR:
Bram Moolenaara471eea2020-03-04 22:20:26 +0100904 tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100905 clear_tv(tv);
906 tv->v_type = VAR_NUMBER;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100907 tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100908 break;
909
910 // push constant
911 case ISN_PUSHNR:
912 case ISN_PUSHBOOL:
913 case ISN_PUSHSPEC:
914 case ISN_PUSHF:
915 case ISN_PUSHS:
916 case ISN_PUSHBLOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100917 case ISN_PUSHFUNC:
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100918 case ISN_PUSHCHANNEL:
919 case ISN_PUSHJOB:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100920 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
921 goto failed;
922 tv = STACK_TV_BOT(0);
923 ++ectx.ec_stack.ga_len;
924 switch (iptr->isn_type)
925 {
926 case ISN_PUSHNR:
927 tv->v_type = VAR_NUMBER;
928 tv->vval.v_number = iptr->isn_arg.number;
929 break;
930 case ISN_PUSHBOOL:
931 tv->v_type = VAR_BOOL;
932 tv->vval.v_number = iptr->isn_arg.number;
933 break;
934 case ISN_PUSHSPEC:
935 tv->v_type = VAR_SPECIAL;
936 tv->vval.v_number = iptr->isn_arg.number;
937 break;
938#ifdef FEAT_FLOAT
939 case ISN_PUSHF:
940 tv->v_type = VAR_FLOAT;
941 tv->vval.v_float = iptr->isn_arg.fnumber;
942 break;
943#endif
944 case ISN_PUSHBLOB:
945 blob_copy(iptr->isn_arg.blob, tv);
946 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100947 case ISN_PUSHFUNC:
948 tv->v_type = VAR_FUNC;
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100949 if (iptr->isn_arg.string == NULL)
950 tv->vval.v_string = NULL;
951 else
952 tv->vval.v_string =
953 vim_strsave(iptr->isn_arg.string);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100954 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100955 case ISN_PUSHCHANNEL:
956#ifdef FEAT_JOB_CHANNEL
957 tv->v_type = VAR_CHANNEL;
958 tv->vval.v_channel = iptr->isn_arg.channel;
959 if (tv->vval.v_channel != NULL)
960 ++tv->vval.v_channel->ch_refcount;
961#endif
962 break;
963 case ISN_PUSHJOB:
964#ifdef FEAT_JOB_CHANNEL
965 tv->v_type = VAR_JOB;
966 tv->vval.v_job = iptr->isn_arg.job;
967 if (tv->vval.v_job != NULL)
968 ++tv->vval.v_job->jv_refcount;
969#endif
970 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100971 default:
972 tv->v_type = VAR_STRING;
Bram Moolenaare69f6d02020-04-01 22:11:01 +0200973 tv->vval.v_string = vim_strsave(
974 iptr->isn_arg.string == NULL
975 ? (char_u *)"" : iptr->isn_arg.string);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100976 }
977 break;
978
979 // create a list from items on the stack; uses a single allocation
980 // for the list header and the items
981 case ISN_NEWLIST:
982 {
983 int count = iptr->isn_arg.number;
984 list_T *list = list_alloc_with_items(count);
985
986 if (list == NULL)
987 goto failed;
988 for (idx = 0; idx < count; ++idx)
989 list_set_item(list, idx, STACK_TV_BOT(idx - count));
990
991 if (count > 0)
992 ectx.ec_stack.ga_len -= count - 1;
993 else if (ga_grow(&ectx.ec_stack, 1) == FAIL)
994 goto failed;
995 else
996 ++ectx.ec_stack.ga_len;
997 tv = STACK_TV_BOT(-1);
998 tv->v_type = VAR_LIST;
999 tv->vval.v_list = list;
1000 ++list->lv_refcount;
1001 }
1002 break;
1003
1004 // create a dict from items on the stack
1005 case ISN_NEWDICT:
1006 {
1007 int count = iptr->isn_arg.number;
1008 dict_T *dict = dict_alloc();
1009 dictitem_T *item;
1010
1011 if (dict == NULL)
1012 goto failed;
1013 for (idx = 0; idx < count; ++idx)
1014 {
1015 // check key type is VAR_STRING
1016 tv = STACK_TV_BOT(2 * (idx - count));
1017 item = dictitem_alloc(tv->vval.v_string);
1018 clear_tv(tv);
1019 if (item == NULL)
1020 goto failed;
1021 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
1022 item->di_tv.v_lock = 0;
1023 if (dict_add(dict, item) == FAIL)
1024 goto failed;
1025 }
1026
1027 if (count > 0)
1028 ectx.ec_stack.ga_len -= 2 * count - 1;
1029 else if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1030 goto failed;
1031 else
1032 ++ectx.ec_stack.ga_len;
1033 tv = STACK_TV_BOT(-1);
1034 tv->v_type = VAR_DICT;
1035 tv->vval.v_dict = dict;
1036 ++dict->dv_refcount;
1037 }
1038 break;
1039
1040 // call a :def function
1041 case ISN_DCALL:
1042 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
1043 iptr->isn_arg.dfunc.cdf_argcount,
1044 &ectx) == FAIL)
1045 goto failed;
1046 break;
1047
1048 // call a builtin function
1049 case ISN_BCALL:
1050 SOURCING_LNUM = iptr->isn_lnum;
1051 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
1052 iptr->isn_arg.bfunc.cbf_argcount,
1053 &ectx) == FAIL)
1054 goto failed;
1055 break;
1056
1057 // call a funcref or partial
1058 case ISN_PCALL:
1059 {
1060 cpfunc_T *pfunc = &iptr->isn_arg.pfunc;
1061 int r;
1062 typval_T partial;
1063
1064 SOURCING_LNUM = iptr->isn_lnum;
1065 if (pfunc->cpf_top)
1066 {
1067 // funcref is above the arguments
1068 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1);
1069 }
1070 else
1071 {
1072 // Get the funcref from the stack.
1073 --ectx.ec_stack.ga_len;
1074 partial = *STACK_TV_BOT(0);
1075 tv = &partial;
1076 }
1077 r = call_partial(tv, pfunc->cpf_argcount, &ectx);
1078 if (tv == &partial)
1079 clear_tv(&partial);
1080 if (r == FAIL)
1081 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001082 }
1083 break;
1084
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001085 case ISN_PCALL_END:
1086 // PCALL finished, arguments have been consumed and replaced by
1087 // the return value. Now clear the funcref from the stack,
1088 // and move the return value in its place.
1089 --ectx.ec_stack.ga_len;
1090 clear_tv(STACK_TV_BOT(-1));
1091 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
1092 break;
1093
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001094 // call a user defined function or funcref/partial
1095 case ISN_UCALL:
1096 {
1097 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
1098
1099 SOURCING_LNUM = iptr->isn_lnum;
1100 if (call_eval_func(cufunc->cuf_name,
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001101 cufunc->cuf_argcount, &ectx, iptr) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001102 goto failed;
1103 }
1104 break;
1105
1106 // return from a :def function call
1107 case ISN_RETURN:
1108 {
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001109 garray_T *trystack = &ectx.ec_trystack;
Bram Moolenaar20431c92020-03-20 18:39:46 +01001110 trycmd_T *trycmd = NULL;
Bram Moolenaar8cbd6df2020-01-28 22:59:45 +01001111
1112 if (trystack->ga_len > 0)
1113 trycmd = ((trycmd_T *)trystack->ga_data)
1114 + trystack->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001115 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame
1116 && trycmd->tcd_finally_idx != 0)
1117 {
1118 // jump to ":finally"
1119 ectx.ec_iidx = trycmd->tcd_finally_idx;
1120 trycmd->tcd_return = TRUE;
1121 }
1122 else
1123 {
1124 // Restore previous function. If the frame pointer
1125 // is zero then there is none and we are done.
1126 if (ectx.ec_frame == initial_frame_ptr)
1127 goto done;
1128
1129 func_return(&ectx);
1130 }
1131 }
1132 break;
1133
1134 // push a function reference to a compiled function
1135 case ISN_FUNCREF:
1136 {
1137 partial_T *pt = NULL;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001138 dfunc_T *dfunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001139
1140 pt = ALLOC_CLEAR_ONE(partial_T);
1141 if (pt == NULL)
1142 goto failed;
1143 dfunc = ((dfunc_T *)def_functions.ga_data)
1144 + iptr->isn_arg.number;
1145 pt->pt_func = dfunc->df_ufunc;
1146 pt->pt_refcount = 1;
1147 ++dfunc->df_ufunc->uf_refcount;
1148
1149 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1150 goto failed;
1151 tv = STACK_TV_BOT(0);
1152 ++ectx.ec_stack.ga_len;
1153 tv->vval.v_partial = pt;
1154 tv->v_type = VAR_PARTIAL;
1155 }
1156 break;
1157
1158 // jump if a condition is met
1159 case ISN_JUMP:
1160 {
1161 jumpwhen_T when = iptr->isn_arg.jump.jump_when;
1162 int jump = TRUE;
1163
1164 if (when != JUMP_ALWAYS)
1165 {
1166 tv = STACK_TV_BOT(-1);
1167 jump = tv2bool(tv);
1168 if (when == JUMP_IF_FALSE
1169 || when == JUMP_AND_KEEP_IF_FALSE)
1170 jump = !jump;
Bram Moolenaar777770f2020-02-06 21:27:08 +01001171 if (when == JUMP_IF_FALSE || !jump)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001172 {
1173 // drop the value from the stack
1174 clear_tv(tv);
1175 --ectx.ec_stack.ga_len;
1176 }
1177 }
1178 if (jump)
1179 ectx.ec_iidx = iptr->isn_arg.jump.jump_where;
1180 }
1181 break;
1182
1183 // top of a for loop
1184 case ISN_FOR:
1185 {
1186 list_T *list = STACK_TV_BOT(-1)->vval.v_list;
1187 typval_T *idxtv =
1188 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);
1189
1190 // push the next item from the list
1191 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1192 goto failed;
1193 if (++idxtv->vval.v_number >= list->lv_len)
1194 // past the end of the list, jump to "endfor"
1195 ectx.ec_iidx = iptr->isn_arg.forloop.for_end;
1196 else if (list->lv_first == &range_list_item)
1197 {
1198 // non-materialized range() list
1199 tv = STACK_TV_BOT(0);
1200 tv->v_type = VAR_NUMBER;
1201 tv->vval.v_number = list_find_nr(
1202 list, idxtv->vval.v_number, NULL);
1203 ++ectx.ec_stack.ga_len;
1204 }
1205 else
1206 {
1207 listitem_T *li = list_find(list, idxtv->vval.v_number);
1208
1209 if (li == NULL)
1210 goto failed;
1211 copy_tv(&li->li_tv, STACK_TV_BOT(0));
1212 ++ectx.ec_stack.ga_len;
1213 }
1214 }
1215 break;
1216
1217 // start of ":try" block
1218 case ISN_TRY:
1219 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001220 trycmd_T *trycmd = NULL;
1221
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001222 if (ga_grow(&ectx.ec_trystack, 1) == FAIL)
1223 goto failed;
1224 trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data)
1225 + ectx.ec_trystack.ga_len;
1226 ++ectx.ec_trystack.ga_len;
1227 ++trylevel;
1228 trycmd->tcd_frame = ectx.ec_frame;
1229 trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch;
1230 trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001231 trycmd->tcd_caught = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001232 }
1233 break;
1234
1235 case ISN_PUSHEXC:
1236 if (current_exception == NULL)
1237 {
1238 iemsg("Evaluating catch while current_exception is NULL");
1239 goto failed;
1240 }
1241 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1242 goto failed;
1243 tv = STACK_TV_BOT(0);
1244 ++ectx.ec_stack.ga_len;
1245 tv->v_type = VAR_STRING;
1246 tv->vval.v_string = vim_strsave(
1247 (char_u *)current_exception->value);
1248 break;
1249
1250 case ISN_CATCH:
1251 {
1252 garray_T *trystack = &ectx.ec_trystack;
1253
1254 if (trystack->ga_len > 0)
1255 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001256 trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001257 + trystack->ga_len - 1;
1258 trycmd->tcd_caught = TRUE;
1259 }
1260 did_emsg = got_int = did_throw = FALSE;
1261 catch_exception(current_exception);
1262 }
1263 break;
1264
1265 // end of ":try" block
1266 case ISN_ENDTRY:
1267 {
1268 garray_T *trystack = &ectx.ec_trystack;
1269
1270 if (trystack->ga_len > 0)
1271 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01001272 trycmd_T *trycmd = NULL;
1273
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001274 --trystack->ga_len;
1275 --trylevel;
1276 trycmd = ((trycmd_T *)trystack->ga_data)
1277 + trystack->ga_len;
Bram Moolenaarf575adf2020-02-20 20:41:06 +01001278 if (trycmd->tcd_caught && current_exception != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001279 {
1280 // discard the exception
1281 if (caught_stack == current_exception)
1282 caught_stack = caught_stack->caught;
1283 discard_current_exception();
1284 }
1285
1286 if (trycmd->tcd_return)
1287 {
1288 // Restore previous function. If the frame pointer
1289 // is zero then there is none and we are done.
1290 if (ectx.ec_frame == initial_frame_ptr)
1291 goto done;
1292
1293 func_return(&ectx);
1294 }
1295 }
1296 }
1297 break;
1298
1299 case ISN_THROW:
1300 --ectx.ec_stack.ga_len;
1301 tv = STACK_TV_BOT(0);
1302 if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL)
1303 {
1304 vim_free(tv->vval.v_string);
1305 goto failed;
1306 }
1307 did_throw = TRUE;
1308 break;
1309
1310 // compare with special values
1311 case ISN_COMPAREBOOL:
1312 case ISN_COMPARESPECIAL:
1313 {
1314 typval_T *tv1 = STACK_TV_BOT(-2);
1315 typval_T *tv2 = STACK_TV_BOT(-1);
1316 varnumber_T arg1 = tv1->vval.v_number;
1317 varnumber_T arg2 = tv2->vval.v_number;
1318 int res;
1319
1320 switch (iptr->isn_arg.op.op_type)
1321 {
1322 case EXPR_EQUAL: res = arg1 == arg2; break;
1323 case EXPR_NEQUAL: res = arg1 != arg2; break;
1324 default: res = 0; break;
1325 }
1326
1327 --ectx.ec_stack.ga_len;
1328 tv1->v_type = VAR_BOOL;
1329 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
1330 }
1331 break;
1332
1333 // Operation with two number arguments
1334 case ISN_OPNR:
1335 case ISN_COMPARENR:
1336 {
1337 typval_T *tv1 = STACK_TV_BOT(-2);
1338 typval_T *tv2 = STACK_TV_BOT(-1);
1339 varnumber_T arg1 = tv1->vval.v_number;
1340 varnumber_T arg2 = tv2->vval.v_number;
1341 varnumber_T res;
1342
1343 switch (iptr->isn_arg.op.op_type)
1344 {
1345 case EXPR_MULT: res = arg1 * arg2; break;
1346 case EXPR_DIV: res = arg1 / arg2; break;
1347 case EXPR_REM: res = arg1 % arg2; break;
1348 case EXPR_SUB: res = arg1 - arg2; break;
1349 case EXPR_ADD: res = arg1 + arg2; break;
1350
1351 case EXPR_EQUAL: res = arg1 == arg2; break;
1352 case EXPR_NEQUAL: res = arg1 != arg2; break;
1353 case EXPR_GREATER: res = arg1 > arg2; break;
1354 case EXPR_GEQUAL: res = arg1 >= arg2; break;
1355 case EXPR_SMALLER: res = arg1 < arg2; break;
1356 case EXPR_SEQUAL: res = arg1 <= arg2; break;
1357 default: res = 0; break;
1358 }
1359
1360 --ectx.ec_stack.ga_len;
1361 if (iptr->isn_type == ISN_COMPARENR)
1362 {
1363 tv1->v_type = VAR_BOOL;
1364 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE;
1365 }
1366 else
1367 tv1->vval.v_number = res;
1368 }
1369 break;
1370
1371 // Computation with two float arguments
1372 case ISN_OPFLOAT:
1373 case ISN_COMPAREFLOAT:
Bram Moolenaara5d59532020-01-26 21:42:03 +01001374#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001375 {
1376 typval_T *tv1 = STACK_TV_BOT(-2);
1377 typval_T *tv2 = STACK_TV_BOT(-1);
1378 float_T arg1 = tv1->vval.v_float;
1379 float_T arg2 = tv2->vval.v_float;
1380 float_T res = 0;
1381 int cmp = FALSE;
1382
1383 switch (iptr->isn_arg.op.op_type)
1384 {
1385 case EXPR_MULT: res = arg1 * arg2; break;
1386 case EXPR_DIV: res = arg1 / arg2; break;
1387 case EXPR_SUB: res = arg1 - arg2; break;
1388 case EXPR_ADD: res = arg1 + arg2; break;
1389
1390 case EXPR_EQUAL: cmp = arg1 == arg2; break;
1391 case EXPR_NEQUAL: cmp = arg1 != arg2; break;
1392 case EXPR_GREATER: cmp = arg1 > arg2; break;
1393 case EXPR_GEQUAL: cmp = arg1 >= arg2; break;
1394 case EXPR_SMALLER: cmp = arg1 < arg2; break;
1395 case EXPR_SEQUAL: cmp = arg1 <= arg2; break;
1396 default: cmp = 0; break;
1397 }
1398 --ectx.ec_stack.ga_len;
1399 if (iptr->isn_type == ISN_COMPAREFLOAT)
1400 {
1401 tv1->v_type = VAR_BOOL;
1402 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1403 }
1404 else
1405 tv1->vval.v_float = res;
1406 }
Bram Moolenaara5d59532020-01-26 21:42:03 +01001407#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001408 break;
1409
1410 case ISN_COMPARELIST:
1411 {
1412 typval_T *tv1 = STACK_TV_BOT(-2);
1413 typval_T *tv2 = STACK_TV_BOT(-1);
1414 list_T *arg1 = tv1->vval.v_list;
1415 list_T *arg2 = tv2->vval.v_list;
1416 int cmp = FALSE;
1417 int ic = iptr->isn_arg.op.op_ic;
1418
1419 switch (iptr->isn_arg.op.op_type)
1420 {
1421 case EXPR_EQUAL: cmp =
1422 list_equal(arg1, arg2, ic, FALSE); break;
1423 case EXPR_NEQUAL: cmp =
1424 !list_equal(arg1, arg2, ic, FALSE); break;
1425 case EXPR_IS: cmp = arg1 == arg2; break;
1426 case EXPR_ISNOT: cmp = arg1 != arg2; break;
1427 default: cmp = 0; break;
1428 }
1429 --ectx.ec_stack.ga_len;
1430 clear_tv(tv1);
1431 clear_tv(tv2);
1432 tv1->v_type = VAR_BOOL;
1433 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1434 }
1435 break;
1436
1437 case ISN_COMPAREBLOB:
1438 {
1439 typval_T *tv1 = STACK_TV_BOT(-2);
1440 typval_T *tv2 = STACK_TV_BOT(-1);
1441 blob_T *arg1 = tv1->vval.v_blob;
1442 blob_T *arg2 = tv2->vval.v_blob;
1443 int cmp = FALSE;
1444
1445 switch (iptr->isn_arg.op.op_type)
1446 {
1447 case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break;
1448 case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break;
1449 case EXPR_IS: cmp = arg1 == arg2; break;
1450 case EXPR_ISNOT: cmp = arg1 != arg2; break;
1451 default: cmp = 0; break;
1452 }
1453 --ectx.ec_stack.ga_len;
1454 clear_tv(tv1);
1455 clear_tv(tv2);
1456 tv1->v_type = VAR_BOOL;
1457 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE;
1458 }
1459 break;
1460
1461 // TODO: handle separately
1462 case ISN_COMPARESTRING:
1463 case ISN_COMPAREDICT:
1464 case ISN_COMPAREFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001465 case ISN_COMPAREANY:
1466 {
1467 typval_T *tv1 = STACK_TV_BOT(-2);
1468 typval_T *tv2 = STACK_TV_BOT(-1);
1469 exptype_T exptype = iptr->isn_arg.op.op_type;
1470 int ic = iptr->isn_arg.op.op_ic;
1471
1472 typval_compare(tv1, tv2, exptype, ic);
1473 clear_tv(tv2);
1474 tv1->v_type = VAR_BOOL;
1475 tv1->vval.v_number = tv1->vval.v_number
1476 ? VVAL_TRUE : VVAL_FALSE;
1477 --ectx.ec_stack.ga_len;
1478 }
1479 break;
1480
1481 case ISN_ADDLIST:
1482 case ISN_ADDBLOB:
1483 {
1484 typval_T *tv1 = STACK_TV_BOT(-2);
1485 typval_T *tv2 = STACK_TV_BOT(-1);
1486
1487 if (iptr->isn_type == ISN_ADDLIST)
1488 eval_addlist(tv1, tv2);
1489 else
1490 eval_addblob(tv1, tv2);
1491 clear_tv(tv2);
1492 --ectx.ec_stack.ga_len;
1493 }
1494 break;
1495
1496 // Computation with two arguments of unknown type
1497 case ISN_OPANY:
1498 {
1499 typval_T *tv1 = STACK_TV_BOT(-2);
1500 typval_T *tv2 = STACK_TV_BOT(-1);
1501 varnumber_T n1, n2;
1502#ifdef FEAT_FLOAT
1503 float_T f1 = 0, f2 = 0;
1504#endif
1505 int error = FALSE;
1506
1507 if (iptr->isn_arg.op.op_type == EXPR_ADD)
1508 {
1509 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST)
1510 {
1511 eval_addlist(tv1, tv2);
1512 clear_tv(tv2);
1513 --ectx.ec_stack.ga_len;
1514 break;
1515 }
1516 else if (tv1->v_type == VAR_BLOB
1517 && tv2->v_type == VAR_BLOB)
1518 {
1519 eval_addblob(tv1, tv2);
1520 clear_tv(tv2);
1521 --ectx.ec_stack.ga_len;
1522 break;
1523 }
1524 }
1525#ifdef FEAT_FLOAT
1526 if (tv1->v_type == VAR_FLOAT)
1527 {
1528 f1 = tv1->vval.v_float;
1529 n1 = 0;
1530 }
1531 else
1532#endif
1533 {
1534 n1 = tv_get_number_chk(tv1, &error);
1535 if (error)
1536 goto failed;
1537#ifdef FEAT_FLOAT
1538 if (tv2->v_type == VAR_FLOAT)
1539 f1 = n1;
1540#endif
1541 }
1542#ifdef FEAT_FLOAT
1543 if (tv2->v_type == VAR_FLOAT)
1544 {
1545 f2 = tv2->vval.v_float;
1546 n2 = 0;
1547 }
1548 else
1549#endif
1550 {
1551 n2 = tv_get_number_chk(tv2, &error);
1552 if (error)
1553 goto failed;
1554#ifdef FEAT_FLOAT
1555 if (tv1->v_type == VAR_FLOAT)
1556 f2 = n2;
1557#endif
1558 }
1559#ifdef FEAT_FLOAT
1560 // if there is a float on either side the result is a float
1561 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT)
1562 {
1563 switch (iptr->isn_arg.op.op_type)
1564 {
1565 case EXPR_MULT: f1 = f1 * f2; break;
1566 case EXPR_DIV: f1 = f1 / f2; break;
1567 case EXPR_SUB: f1 = f1 - f2; break;
1568 case EXPR_ADD: f1 = f1 + f2; break;
1569 default: emsg(_(e_modulus)); goto failed;
1570 }
1571 clear_tv(tv1);
1572 clear_tv(tv2);
1573 tv1->v_type = VAR_FLOAT;
1574 tv1->vval.v_float = f1;
1575 --ectx.ec_stack.ga_len;
1576 }
1577 else
1578#endif
1579 {
1580 switch (iptr->isn_arg.op.op_type)
1581 {
1582 case EXPR_MULT: n1 = n1 * n2; break;
1583 case EXPR_DIV: n1 = num_divide(n1, n2); break;
1584 case EXPR_SUB: n1 = n1 - n2; break;
1585 case EXPR_ADD: n1 = n1 + n2; break;
1586 default: n1 = num_modulus(n1, n2); break;
1587 }
1588 clear_tv(tv1);
1589 clear_tv(tv2);
1590 tv1->v_type = VAR_NUMBER;
1591 tv1->vval.v_number = n1;
1592 --ectx.ec_stack.ga_len;
1593 }
1594 }
1595 break;
1596
1597 case ISN_CONCAT:
1598 {
1599 char_u *str1 = STACK_TV_BOT(-2)->vval.v_string;
1600 char_u *str2 = STACK_TV_BOT(-1)->vval.v_string;
1601 char_u *res;
1602
1603 res = concat_str(str1, str2);
1604 clear_tv(STACK_TV_BOT(-2));
1605 clear_tv(STACK_TV_BOT(-1));
1606 --ectx.ec_stack.ga_len;
1607 STACK_TV_BOT(-1)->vval.v_string = res;
1608 }
1609 break;
1610
1611 case ISN_INDEX:
1612 {
1613 list_T *list;
1614 varnumber_T n;
1615 listitem_T *li;
1616
1617 // list index: list is at stack-2, index at stack-1
1618 tv = STACK_TV_BOT(-2);
1619 if (tv->v_type != VAR_LIST)
1620 {
1621 emsg(_(e_listreq));
1622 goto failed;
1623 }
1624 list = tv->vval.v_list;
1625
1626 tv = STACK_TV_BOT(-1);
1627 if (tv->v_type != VAR_NUMBER)
1628 {
1629 emsg(_(e_number_exp));
1630 goto failed;
1631 }
1632 n = tv->vval.v_number;
1633 clear_tv(tv);
1634 if ((li = list_find(list, n)) == NULL)
1635 {
1636 semsg(_(e_listidx), n);
1637 goto failed;
1638 }
1639 --ectx.ec_stack.ga_len;
1640 clear_tv(STACK_TV_BOT(-1));
1641 copy_tv(&li->li_tv, STACK_TV_BOT(-1));
1642 }
1643 break;
1644
1645 // dict member with string key
1646 case ISN_MEMBER:
1647 {
1648 dict_T *dict;
1649 dictitem_T *di;
1650
1651 tv = STACK_TV_BOT(-1);
1652 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL)
1653 {
1654 emsg(_(e_dictreq));
1655 goto failed;
1656 }
1657 dict = tv->vval.v_dict;
1658
1659 if ((di = dict_find(dict, iptr->isn_arg.string, -1))
1660 == NULL)
1661 {
1662 semsg(_(e_dictkey), iptr->isn_arg.string);
1663 goto failed;
1664 }
1665 clear_tv(tv);
1666 copy_tv(&di->di_tv, tv);
1667 }
1668 break;
1669
1670 case ISN_NEGATENR:
1671 tv = STACK_TV_BOT(-1);
Bram Moolenaarc58164c2020-03-29 18:40:30 +02001672 if (tv->v_type != VAR_NUMBER
1673#ifdef FEAT_FLOAT
1674 && tv->v_type != VAR_FLOAT
1675#endif
1676 )
1677 {
1678 emsg(_(e_number_exp));
1679 goto failed;
1680 }
1681#ifdef FEAT_FLOAT
1682 if (tv->v_type == VAR_FLOAT)
1683 tv->vval.v_float = -tv->vval.v_float;
1684 else
1685#endif
1686 tv->vval.v_number = -tv->vval.v_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001687 break;
1688
1689 case ISN_CHECKNR:
1690 {
1691 int error = FALSE;
1692
1693 tv = STACK_TV_BOT(-1);
1694 if (check_not_string(tv) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001695 goto failed;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001696 (void)tv_get_number_chk(tv, &error);
1697 if (error)
1698 goto failed;
1699 }
1700 break;
1701
1702 case ISN_CHECKTYPE:
1703 {
1704 checktype_T *ct = &iptr->isn_arg.type;
1705
1706 tv = STACK_TV_BOT(ct->ct_off);
1707 if (tv->v_type != ct->ct_type)
1708 {
1709 semsg(_("E1029: Expected %s but got %s"),
1710 vartype_name(ct->ct_type),
1711 vartype_name(tv->v_type));
1712 goto failed;
1713 }
1714 }
1715 break;
1716
1717 case ISN_2BOOL:
1718 {
1719 int n;
1720
1721 tv = STACK_TV_BOT(-1);
1722 n = tv2bool(tv);
1723 if (iptr->isn_arg.number) // invert
1724 n = !n;
1725 clear_tv(tv);
1726 tv->v_type = VAR_BOOL;
1727 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE;
1728 }
1729 break;
1730
1731 case ISN_2STRING:
1732 {
1733 char_u *str;
1734
1735 tv = STACK_TV_BOT(iptr->isn_arg.number);
1736 if (tv->v_type != VAR_STRING)
1737 {
1738 str = typval_tostring(tv);
1739 clear_tv(tv);
1740 tv->v_type = VAR_STRING;
1741 tv->vval.v_string = str;
1742 }
1743 }
1744 break;
1745
1746 case ISN_DROP:
1747 --ectx.ec_stack.ga_len;
1748 clear_tv(STACK_TV_BOT(0));
1749 break;
1750 }
1751 }
1752
1753done:
1754 // function finished, get result from the stack.
1755 tv = STACK_TV_BOT(-1);
1756 *rettv = *tv;
1757 tv->v_type = VAR_UNKNOWN;
1758 ret = OK;
1759
1760failed:
Bram Moolenaar7eeefd42020-02-26 21:24:23 +01001761 // When failed need to unwind the call stack.
1762 while (ectx.ec_frame != initial_frame_ptr)
1763 func_return(&ectx);
1764
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001765 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
1766 clear_tv(STACK_TV(idx));
1767 vim_free(ectx.ec_stack.ga_data);
Bram Moolenaar20431c92020-03-20 18:39:46 +01001768 vim_free(ectx.ec_trystack.ga_data);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001769 return ret;
1770}
1771
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001772/*
1773 * ":dissassemble".
Bram Moolenaar777770f2020-02-06 21:27:08 +01001774 * We don't really need this at runtime, but we do have tests that require it,
1775 * so always include this.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001776 */
1777 void
1778ex_disassemble(exarg_T *eap)
1779{
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001780 char_u *arg = eap->arg;
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001781 char_u *fname;
1782 ufunc_T *ufunc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001783 dfunc_T *dfunc;
1784 isn_T *instr;
1785 int current;
1786 int line_idx = 0;
1787 int prev_current = 0;
1788
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001789 fname = trans_function_name(&arg, FALSE,
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001790 TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
Bram Moolenaar21456cd2020-02-13 21:29:32 +01001791 if (fname == NULL)
1792 {
1793 semsg(_(e_invarg2), eap->arg);
1794 return;
1795 }
1796
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +01001797 ufunc = find_func(fname, NULL);
1798 vim_free(fname);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001799 if (ufunc == NULL)
1800 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01001801 semsg(_("E1061: Cannot find function %s"), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001802 return;
1803 }
1804 if (ufunc->uf_dfunc_idx < 0)
1805 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01001806 semsg(_("E1062: Function %s is not compiled"), eap->arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001807 return;
1808 }
1809 if (ufunc->uf_name_exp != NULL)
1810 msg((char *)ufunc->uf_name_exp);
1811 else
1812 msg((char *)ufunc->uf_name);
1813
1814 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
1815 instr = dfunc->df_instr;
1816 for (current = 0; current < dfunc->df_instr_count; ++current)
1817 {
1818 isn_T *iptr = &instr[current];
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001819 char *line;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001820
1821 while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len)
1822 {
1823 if (current > prev_current)
1824 {
1825 msg_puts("\n\n");
1826 prev_current = current;
1827 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001828 line = ((char **)ufunc->uf_lines.ga_data)[line_idx++];
1829 if (line != NULL)
1830 msg(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001831 }
1832
1833 switch (iptr->isn_type)
1834 {
1835 case ISN_EXEC:
1836 smsg("%4d EXEC %s", current, iptr->isn_arg.string);
1837 break;
1838 case ISN_ECHO:
1839 {
1840 echo_T *echo = &iptr->isn_arg.echo;
1841
1842 smsg("%4d %s %d", current,
1843 echo->echo_with_white ? "ECHO" : "ECHON",
1844 echo->echo_count);
1845 }
1846 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01001847 case ISN_EXECUTE:
Bram Moolenaar10827722020-03-23 22:53:22 +01001848 smsg("%4d EXECUTE %lld", current,
1849 (long long)(iptr->isn_arg.number));
Bram Moolenaarad39c092020-02-26 18:23:43 +01001850 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001851 case ISN_LOAD:
1852 if (iptr->isn_arg.number < 0)
1853 smsg("%4d LOAD arg[%lld]", current,
Bram Moolenaar10827722020-03-23 22:53:22 +01001854 (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001855 else
Bram Moolenaar10827722020-03-23 22:53:22 +01001856 smsg("%4d LOAD $%lld", current,
1857 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001858 break;
1859 case ISN_LOADV:
1860 smsg("%4d LOADV v:%s", current,
1861 get_vim_var_name(iptr->isn_arg.number));
1862 break;
1863 case ISN_LOADSCRIPT:
1864 {
1865 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001866 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001867 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1868 + iptr->isn_arg.script.script_idx;
1869
1870 smsg("%4d LOADSCRIPT %s from %s", current,
1871 sv->sv_name, si->sn_name);
1872 }
1873 break;
1874 case ISN_LOADS:
1875 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001876 scriptitem_T *si = SCRIPT_ITEM(
1877 iptr->isn_arg.loadstore.ls_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001878
1879 smsg("%4d LOADS s:%s from %s", current,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001880 iptr->isn_arg.loadstore.ls_name, si->sn_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001881 }
1882 break;
1883 case ISN_LOADG:
1884 smsg("%4d LOADG g:%s", current, iptr->isn_arg.string);
1885 break;
1886 case ISN_LOADOPT:
1887 smsg("%4d LOADOPT %s", current, iptr->isn_arg.string);
1888 break;
1889 case ISN_LOADENV:
1890 smsg("%4d LOADENV %s", current, iptr->isn_arg.string);
1891 break;
1892 case ISN_LOADREG:
Bram Moolenaar10827722020-03-23 22:53:22 +01001893 smsg("%4d LOADREG @%c", current, (int)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001894 break;
1895
1896 case ISN_STORE:
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001897 if (iptr->isn_arg.number < 0)
1898 smsg("%4d STORE arg[%lld]", current,
Bram Moolenaar10827722020-03-23 22:53:22 +01001899 (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE));
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001900 else
Bram Moolenaar10827722020-03-23 22:53:22 +01001901 smsg("%4d STORE $%lld", current,
1902 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001903 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001904 case ISN_STOREV:
1905 smsg("%4d STOREV v:%s", current,
1906 get_vim_var_name(iptr->isn_arg.number));
1907 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001908 case ISN_STOREG:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001909 smsg("%4d STOREG %s", current, iptr->isn_arg.string);
1910 break;
1911 case ISN_STORES:
1912 {
1913 scriptitem_T *si = SCRIPT_ITEM(
1914 iptr->isn_arg.loadstore.ls_sid);
1915
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01001916 smsg("%4d STORES %s in %s", current,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001917 iptr->isn_arg.loadstore.ls_name, si->sn_name);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001918 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001919 break;
1920 case ISN_STORESCRIPT:
1921 {
1922 scriptitem_T *si =
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001923 SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001924 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
1925 + iptr->isn_arg.script.script_idx;
1926
1927 smsg("%4d STORESCRIPT %s in %s", current,
1928 sv->sv_name, si->sn_name);
1929 }
1930 break;
1931 case ISN_STOREOPT:
1932 smsg("%4d STOREOPT &%s", current,
1933 iptr->isn_arg.storeopt.so_name);
1934 break;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001935 case ISN_STOREENV:
1936 smsg("%4d STOREENV $%s", current, iptr->isn_arg.string);
1937 break;
1938 case ISN_STOREREG:
Bram Moolenaar10827722020-03-23 22:53:22 +01001939 smsg("%4d STOREREG @%c", current, (int)iptr->isn_arg.number);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001940 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001941 case ISN_STORENR:
1942 smsg("%4d STORE %lld in $%d", current,
Bram Moolenaara471eea2020-03-04 22:20:26 +01001943 iptr->isn_arg.storenr.stnr_val,
1944 iptr->isn_arg.storenr.stnr_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001945 break;
1946
1947 // constants
1948 case ISN_PUSHNR:
Bram Moolenaar10827722020-03-23 22:53:22 +01001949 smsg("%4d PUSHNR %lld", current,
1950 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001951 break;
1952 case ISN_PUSHBOOL:
1953 case ISN_PUSHSPEC:
1954 smsg("%4d PUSH %s", current,
1955 get_var_special_name(iptr->isn_arg.number));
1956 break;
1957 case ISN_PUSHF:
Bram Moolenaara5d59532020-01-26 21:42:03 +01001958#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001959 smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber);
Bram Moolenaara5d59532020-01-26 21:42:03 +01001960#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001961 break;
1962 case ISN_PUSHS:
1963 smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string);
1964 break;
1965 case ISN_PUSHBLOB:
1966 {
1967 char_u *r;
1968 char_u numbuf[NUMBUFLEN];
1969 char_u *tofree;
1970
1971 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01001972 smsg("%4d PUSHBLOB %s", current, r);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001973 vim_free(tofree);
1974 }
1975 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001976 case ISN_PUSHFUNC:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01001977 {
1978 char *name = (char *)iptr->isn_arg.string;
1979
1980 smsg("%4d PUSHFUNC \"%s\"", current,
1981 name == NULL ? "[none]" : name);
1982 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001983 break;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001984 case ISN_PUSHCHANNEL:
1985#ifdef FEAT_JOB_CHANNEL
1986 {
1987 channel_T *channel = iptr->isn_arg.channel;
1988
1989 smsg("%4d PUSHCHANNEL %d", current,
1990 channel == NULL ? 0 : channel->ch_id);
1991 }
1992#endif
1993 break;
1994 case ISN_PUSHJOB:
1995#ifdef FEAT_JOB_CHANNEL
1996 {
1997 typval_T tv;
1998 char_u *name;
1999
2000 tv.v_type = VAR_JOB;
2001 tv.vval.v_job = iptr->isn_arg.job;
2002 name = tv_get_string(&tv);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01002003 smsg("%4d PUSHJOB \"%s\"", current, name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01002004 }
2005#endif
2006 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002007 case ISN_PUSHEXC:
2008 smsg("%4d PUSH v:exception", current);
2009 break;
2010 case ISN_NEWLIST:
Bram Moolenaar10827722020-03-23 22:53:22 +01002011 smsg("%4d NEWLIST size %lld", current,
2012 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002013 break;
2014 case ISN_NEWDICT:
Bram Moolenaar10827722020-03-23 22:53:22 +01002015 smsg("%4d NEWDICT size %lld", current,
2016 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002017 break;
2018
2019 // function call
2020 case ISN_BCALL:
2021 {
2022 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc;
2023
2024 smsg("%4d BCALL %s(argc %d)", current,
2025 internal_func_name(cbfunc->cbf_idx),
2026 cbfunc->cbf_argcount);
2027 }
2028 break;
2029 case ISN_DCALL:
2030 {
2031 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc;
2032 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
2033 + cdfunc->cdf_idx;
2034
2035 smsg("%4d DCALL %s(argc %d)", current,
2036 df->df_ufunc->uf_name_exp != NULL
2037 ? df->df_ufunc->uf_name_exp
2038 : df->df_ufunc->uf_name, cdfunc->cdf_argcount);
2039 }
2040 break;
2041 case ISN_UCALL:
2042 {
2043 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
2044
2045 smsg("%4d UCALL %s(argc %d)", current,
2046 cufunc->cuf_name, cufunc->cuf_argcount);
2047 }
2048 break;
2049 case ISN_PCALL:
2050 {
2051 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc;
2052
2053 smsg("%4d PCALL%s (argc %d)", current,
2054 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
2055 }
2056 break;
Bram Moolenaarbd5da372020-03-31 23:13:10 +02002057 case ISN_PCALL_END:
2058 smsg("%4d PCALL end", current);
2059 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002060 case ISN_RETURN:
2061 smsg("%4d RETURN", current);
2062 break;
2063 case ISN_FUNCREF:
2064 {
2065 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
2066 + iptr->isn_arg.number;
2067
2068 smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name);
2069 }
2070 break;
2071
2072 case ISN_JUMP:
2073 {
2074 char *when = "?";
2075
2076 switch (iptr->isn_arg.jump.jump_when)
2077 {
2078 case JUMP_ALWAYS:
2079 when = "JUMP";
2080 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002081 case JUMP_AND_KEEP_IF_TRUE:
2082 when = "JUMP_AND_KEEP_IF_TRUE";
2083 break;
2084 case JUMP_IF_FALSE:
2085 when = "JUMP_IF_FALSE";
2086 break;
2087 case JUMP_AND_KEEP_IF_FALSE:
2088 when = "JUMP_AND_KEEP_IF_FALSE";
2089 break;
2090 }
Bram Moolenaar8a677a32020-03-12 19:15:45 +01002091 smsg("%4d %s -> %d", current, when,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002092 iptr->isn_arg.jump.jump_where);
2093 }
2094 break;
2095
2096 case ISN_FOR:
2097 {
2098 forloop_T *forloop = &iptr->isn_arg.forloop;
2099
2100 smsg("%4d FOR $%d -> %d", current,
2101 forloop->for_idx, forloop->for_end);
2102 }
2103 break;
2104
2105 case ISN_TRY:
2106 {
2107 try_T *try = &iptr->isn_arg.try;
2108
2109 smsg("%4d TRY catch -> %d, finally -> %d", current,
2110 try->try_catch, try->try_finally);
2111 }
2112 break;
2113 case ISN_CATCH:
2114 // TODO
2115 smsg("%4d CATCH", current);
2116 break;
2117 case ISN_ENDTRY:
2118 smsg("%4d ENDTRY", current);
2119 break;
2120 case ISN_THROW:
2121 smsg("%4d THROW", current);
2122 break;
2123
2124 // expression operations on number
2125 case ISN_OPNR:
2126 case ISN_OPFLOAT:
2127 case ISN_OPANY:
2128 {
2129 char *what;
2130 char *ins;
2131
2132 switch (iptr->isn_arg.op.op_type)
2133 {
2134 case EXPR_MULT: what = "*"; break;
2135 case EXPR_DIV: what = "/"; break;
2136 case EXPR_REM: what = "%"; break;
2137 case EXPR_SUB: what = "-"; break;
2138 case EXPR_ADD: what = "+"; break;
2139 default: what = "???"; break;
2140 }
2141 switch (iptr->isn_type)
2142 {
2143 case ISN_OPNR: ins = "OPNR"; break;
2144 case ISN_OPFLOAT: ins = "OPFLOAT"; break;
2145 case ISN_OPANY: ins = "OPANY"; break;
2146 default: ins = "???"; break;
2147 }
2148 smsg("%4d %s %s", current, ins, what);
2149 }
2150 break;
2151
2152 case ISN_COMPAREBOOL:
2153 case ISN_COMPARESPECIAL:
2154 case ISN_COMPARENR:
2155 case ISN_COMPAREFLOAT:
2156 case ISN_COMPARESTRING:
2157 case ISN_COMPAREBLOB:
2158 case ISN_COMPARELIST:
2159 case ISN_COMPAREDICT:
2160 case ISN_COMPAREFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002161 case ISN_COMPAREANY:
2162 {
2163 char *p;
2164 char buf[10];
2165 char *type;
2166
2167 switch (iptr->isn_arg.op.op_type)
2168 {
2169 case EXPR_EQUAL: p = "=="; break;
2170 case EXPR_NEQUAL: p = "!="; break;
2171 case EXPR_GREATER: p = ">"; break;
2172 case EXPR_GEQUAL: p = ">="; break;
2173 case EXPR_SMALLER: p = "<"; break;
2174 case EXPR_SEQUAL: p = "<="; break;
2175 case EXPR_MATCH: p = "=~"; break;
2176 case EXPR_IS: p = "is"; break;
2177 case EXPR_ISNOT: p = "isnot"; break;
2178 case EXPR_NOMATCH: p = "!~"; break;
2179 default: p = "???"; break;
2180 }
2181 STRCPY(buf, p);
2182 if (iptr->isn_arg.op.op_ic == TRUE)
2183 strcat(buf, "?");
2184 switch(iptr->isn_type)
2185 {
2186 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break;
2187 case ISN_COMPARESPECIAL:
2188 type = "COMPARESPECIAL"; break;
2189 case ISN_COMPARENR: type = "COMPARENR"; break;
2190 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break;
2191 case ISN_COMPARESTRING:
2192 type = "COMPARESTRING"; break;
2193 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break;
2194 case ISN_COMPARELIST: type = "COMPARELIST"; break;
2195 case ISN_COMPAREDICT: type = "COMPAREDICT"; break;
2196 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002197 case ISN_COMPAREANY: type = "COMPAREANY"; break;
2198 default: type = "???"; break;
2199 }
2200
2201 smsg("%4d %s %s", current, type, buf);
2202 }
2203 break;
2204
2205 case ISN_ADDLIST: smsg("%4d ADDLIST", current); break;
2206 case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break;
2207
2208 // expression operations
2209 case ISN_CONCAT: smsg("%4d CONCAT", current); break;
2210 case ISN_INDEX: smsg("%4d INDEX", current); break;
2211 case ISN_MEMBER: smsg("%4d MEMBER %s", current,
2212 iptr->isn_arg.string); break;
2213 case ISN_NEGATENR: smsg("%4d NEGATENR", current); break;
2214
2215 case ISN_CHECKNR: smsg("%4d CHECKNR", current); break;
2216 case ISN_CHECKTYPE: smsg("%4d CHECKTYPE %s stack[%d]", current,
2217 vartype_name(iptr->isn_arg.type.ct_type),
2218 iptr->isn_arg.type.ct_off);
2219 break;
2220 case ISN_2BOOL: if (iptr->isn_arg.number)
2221 smsg("%4d INVERT (!val)", current);
2222 else
2223 smsg("%4d 2BOOL (!!val)", current);
2224 break;
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002225 case ISN_2STRING: smsg("%4d 2STRING stack[%lld]", current,
2226 (long long)(iptr->isn_arg.number));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002227 break;
2228
2229 case ISN_DROP: smsg("%4d DROP", current); break;
2230 }
2231 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002232}
2233
2234/*
2235 * Return TRUE when "tv" is not falsey: non-zero, non-empty string, non-empty
2236 * list, etc. Mostly like what JavaScript does, except that empty list and
2237 * empty dictionary are FALSE.
2238 */
2239 int
2240tv2bool(typval_T *tv)
2241{
2242 switch (tv->v_type)
2243 {
2244 case VAR_NUMBER:
2245 return tv->vval.v_number != 0;
2246 case VAR_FLOAT:
2247#ifdef FEAT_FLOAT
2248 return tv->vval.v_float != 0.0;
2249#else
2250 break;
2251#endif
2252 case VAR_PARTIAL:
2253 return tv->vval.v_partial != NULL;
2254 case VAR_FUNC:
2255 case VAR_STRING:
2256 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL;
2257 case VAR_LIST:
2258 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0;
2259 case VAR_DICT:
2260 return tv->vval.v_dict != NULL
2261 && tv->vval.v_dict->dv_hashtab.ht_used > 0;
2262 case VAR_BOOL:
2263 case VAR_SPECIAL:
2264 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE;
2265 case VAR_JOB:
2266#ifdef FEAT_JOB_CHANNEL
2267 return tv->vval.v_job != NULL;
2268#else
2269 break;
2270#endif
2271 case VAR_CHANNEL:
2272#ifdef FEAT_JOB_CHANNEL
2273 return tv->vval.v_channel != NULL;
2274#else
2275 break;
2276#endif
2277 case VAR_BLOB:
2278 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0;
2279 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02002280 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002281 case VAR_VOID:
2282 break;
2283 }
2284 return FALSE;
2285}
2286
2287/*
2288 * If "tv" is a string give an error and return FAIL.
2289 */
2290 int
2291check_not_string(typval_T *tv)
2292{
2293 if (tv->v_type == VAR_STRING)
2294 {
2295 emsg(_("E1030: Using a String as a Number"));
2296 clear_tv(tv);
2297 return FAIL;
2298 }
2299 return OK;
2300}
2301
2302
2303#endif // FEAT_EVAL