Mercurial > vim
comparison src/vim9execute.c @ 19181:94eda51ba9ba v8.2.0149
patch 8.2.0149: maintaining a Vim9 branch separately is more work
Commit: https://github.com/vim/vim/commit/8a7d6542b33e5d2b352262305c3bfdb2d14e1cf8
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jan 26 15:56:19 2020 +0100
patch 8.2.0149: maintaining a Vim9 branch separately is more work
Problem: Maintaining a Vim9 branch separately is more work.
Solution: Merge the Vim9 script changes.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 26 Jan 2020 16:00:05 +0100 |
parents | |
children | 133ef7ba4e4e |
comparison
equal
deleted
inserted
replaced
19180:8edf0aeb71b9 | 19181:94eda51ba9ba |
---|---|
1 /* 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. | |
26 typedef 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 */ | |
57 typedef 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 /* | |
73 * Return the number of arguments, including any vararg. | |
74 */ | |
75 static int | |
76 ufunc_argcount(ufunc_T *ufunc) | |
77 { | |
78 return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0); | |
79 } | |
80 | |
81 /* | |
82 * Call compiled function "cdf_idx" from compiled code. | |
83 * | |
84 * Stack has: | |
85 * - current arguments (already there) | |
86 * - omitted optional argument (default values) added here | |
87 * - stack frame: | |
88 * - pointer to calling function | |
89 * - Index of next instruction in calling function | |
90 * - previous frame pointer | |
91 * - reserved space for local variables | |
92 */ | |
93 static int | |
94 call_dfunc(int cdf_idx, int argcount, ectx_T *ectx) | |
95 { | |
96 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx; | |
97 ufunc_T *ufunc = dfunc->df_ufunc; | |
98 int optcount = ufunc_argcount(ufunc) - argcount; | |
99 int idx; | |
100 | |
101 if (dfunc->df_deleted) | |
102 { | |
103 emsg_funcname(e_func_deleted, ufunc->uf_name); | |
104 return FAIL; | |
105 } | |
106 | |
107 if (ga_grow(&ectx->ec_stack, optcount + 3 + dfunc->df_varcount) == FAIL) | |
108 return FAIL; | |
109 | |
110 // TODO: Put omitted argument default values on the stack. | |
111 if (optcount > 0) | |
112 { | |
113 emsg("optional arguments not implemented yet"); | |
114 return FAIL; | |
115 } | |
116 if (optcount < 0) | |
117 { | |
118 emsg("argument count wrong?"); | |
119 return FAIL; | |
120 } | |
121 // for (idx = argcount - dfunc->df_minarg; | |
122 // idx < dfunc->df_maxarg; ++idx) | |
123 // { | |
124 // copy_tv(&dfunc->df_defarg[idx], STACK_TV_BOT(0)); | |
125 // ++ectx->ec_stack.ga_len; | |
126 // } | |
127 | |
128 // Store current execution state in stack frame for ISN_RETURN. | |
129 // TODO: If the actual number of arguments doesn't match what the called | |
130 // function expects things go bad. | |
131 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx; | |
132 STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx; | |
133 STACK_TV_BOT(2)->vval.v_number = ectx->ec_frame; | |
134 ectx->ec_frame = ectx->ec_stack.ga_len; | |
135 | |
136 // Initialize local variables | |
137 for (idx = 0; idx < dfunc->df_varcount; ++idx) | |
138 STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN; | |
139 ectx->ec_stack.ga_len += STACK_FRAME_SIZE + dfunc->df_varcount; | |
140 | |
141 // Set execution state to the start of the called function. | |
142 ectx->ec_dfunc_idx = cdf_idx; | |
143 ectx->ec_instr = dfunc->df_instr; | |
144 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1); | |
145 ectx->ec_iidx = 0; | |
146 | |
147 return OK; | |
148 } | |
149 | |
150 // Get pointer to item in the stack. | |
151 #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx) | |
152 | |
153 /* | |
154 * Return from the current function. | |
155 */ | |
156 static void | |
157 func_return(ectx_T *ectx) | |
158 { | |
159 int ret_idx = ectx->ec_stack.ga_len - 1; | |
160 int idx; | |
161 dfunc_T *dfunc; | |
162 | |
163 // execution context goes one level up | |
164 estack_pop(); | |
165 | |
166 // Clear the local variables and temporary values, but not | |
167 // the return value. | |
168 for (idx = ectx->ec_frame + STACK_FRAME_SIZE; | |
169 idx < ectx->ec_stack.ga_len - 1; ++idx) | |
170 clear_tv(STACK_TV(idx)); | |
171 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; | |
172 ectx->ec_stack.ga_len = ectx->ec_frame | |
173 - ufunc_argcount(dfunc->df_ufunc) + 1; | |
174 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame)->vval.v_number; | |
175 ectx->ec_iidx = STACK_TV(ectx->ec_frame + 1)->vval.v_number; | |
176 ectx->ec_frame = STACK_TV(ectx->ec_frame + 2)->vval.v_number; | |
177 *STACK_TV_BOT(-1) = *STACK_TV(ret_idx); | |
178 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; | |
179 ectx->ec_instr = dfunc->df_instr; | |
180 } | |
181 | |
182 #undef STACK_TV | |
183 | |
184 /* | |
185 * Prepare arguments and rettv for calling a builtin or user function. | |
186 */ | |
187 static int | |
188 call_prepare(int argcount, typval_T *argvars, ectx_T *ectx) | |
189 { | |
190 int idx; | |
191 typval_T *tv; | |
192 | |
193 // Move arguments from bottom of the stack to argvars[] and add terminator. | |
194 for (idx = 0; idx < argcount; ++idx) | |
195 argvars[idx] = *STACK_TV_BOT(idx - argcount); | |
196 argvars[argcount].v_type = VAR_UNKNOWN; | |
197 | |
198 // Result replaces the arguments on the stack. | |
199 if (argcount > 0) | |
200 ectx->ec_stack.ga_len -= argcount - 1; | |
201 else if (ga_grow(&ectx->ec_stack, 1) == FAIL) | |
202 return FAIL; | |
203 else | |
204 ++ectx->ec_stack.ga_len; | |
205 | |
206 // Default return value is zero. | |
207 tv = STACK_TV_BOT(-1); | |
208 tv->v_type = VAR_NUMBER; | |
209 tv->vval.v_number = 0; | |
210 | |
211 return OK; | |
212 } | |
213 | |
214 /* | |
215 * Call a builtin function by index. | |
216 */ | |
217 static int | |
218 call_bfunc(int func_idx, int argcount, ectx_T *ectx) | |
219 { | |
220 typval_T argvars[MAX_FUNC_ARGS]; | |
221 int idx; | |
222 | |
223 if (call_prepare(argcount, argvars, ectx) == FAIL) | |
224 return FAIL; | |
225 | |
226 // Call the builtin function. | |
227 call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1)); | |
228 | |
229 // Clear the arguments. | |
230 for (idx = 0; idx < argcount; ++idx) | |
231 clear_tv(&argvars[idx]); | |
232 return OK; | |
233 } | |
234 | |
235 /* | |
236 * Execute a user defined function. | |
237 */ | |
238 static int | |
239 call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx) | |
240 { | |
241 typval_T argvars[MAX_FUNC_ARGS]; | |
242 funcexe_T funcexe; | |
243 int error; | |
244 int idx; | |
245 | |
246 if (ufunc->uf_dfunc_idx >= 0) | |
247 // The function has been compiled, can call it quickly. | |
248 return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx); | |
249 | |
250 if (call_prepare(argcount, argvars, ectx) == FAIL) | |
251 return FAIL; | |
252 vim_memset(&funcexe, 0, sizeof(funcexe)); | |
253 funcexe.evaluate = TRUE; | |
254 | |
255 // Call the user function. Result goes in last position on the stack. | |
256 // TODO: add selfdict if there is one | |
257 error = call_user_func_check(ufunc, argcount, argvars, | |
258 STACK_TV_BOT(-1), &funcexe, NULL); | |
259 | |
260 // Clear the arguments. | |
261 for (idx = 0; idx < argcount; ++idx) | |
262 clear_tv(&argvars[idx]); | |
263 | |
264 if (error != FCERR_NONE) | |
265 { | |
266 user_func_error(error, ufunc->uf_name); | |
267 return FAIL; | |
268 } | |
269 return OK; | |
270 } | |
271 | |
272 /* | |
273 * Execute a function by "name". | |
274 * This can be a builtin function or a user function. | |
275 * Returns FAIL if not found without an error message. | |
276 */ | |
277 static int | |
278 call_by_name(char_u *name, int argcount, ectx_T *ectx) | |
279 { | |
280 ufunc_T *ufunc; | |
281 | |
282 if (builtin_function(name, -1)) | |
283 { | |
284 int func_idx = find_internal_func(name); | |
285 | |
286 if (func_idx < 0) | |
287 return FAIL; | |
288 if (check_internal_func(func_idx, argcount) == FAIL) | |
289 return FAIL; | |
290 return call_bfunc(func_idx, argcount, ectx); | |
291 } | |
292 | |
293 ufunc = find_func(name, NULL); | |
294 if (ufunc != NULL) | |
295 return call_ufunc(ufunc, argcount, ectx); | |
296 | |
297 return FAIL; | |
298 } | |
299 | |
300 static int | |
301 call_partial(typval_T *tv, int argcount, ectx_T *ectx) | |
302 { | |
303 char_u *name; | |
304 int called_emsg_before = called_emsg; | |
305 | |
306 if (tv->v_type == VAR_PARTIAL) | |
307 { | |
308 partial_T *pt = tv->vval.v_partial; | |
309 | |
310 if (pt->pt_func != NULL) | |
311 return call_ufunc(pt->pt_func, argcount, ectx); | |
312 name = pt->pt_name; | |
313 } | |
314 else | |
315 name = tv->vval.v_string; | |
316 if (call_by_name(name, argcount, ectx) == FAIL) | |
317 { | |
318 if (called_emsg == called_emsg_before) | |
319 semsg(_(e_unknownfunc), name); | |
320 return FAIL; | |
321 } | |
322 return OK; | |
323 } | |
324 | |
325 /* | |
326 * Execute a function by "name". | |
327 * This can be a builtin function, user function or a funcref. | |
328 */ | |
329 static int | |
330 call_eval_func(char_u *name, int argcount, ectx_T *ectx) | |
331 { | |
332 int called_emsg_before = called_emsg; | |
333 | |
334 if (call_by_name(name, argcount, ectx) == FAIL | |
335 && called_emsg == called_emsg_before) | |
336 { | |
337 // "name" may be a variable that is a funcref or partial | |
338 // if find variable | |
339 // call_partial() | |
340 // else | |
341 // semsg(_(e_unknownfunc), name); | |
342 emsg("call_eval_func(partial) not implemented yet"); | |
343 return FAIL; | |
344 } | |
345 return OK; | |
346 } | |
347 | |
348 /* | |
349 * Call a "def" function from old Vim script. | |
350 * Return OK or FAIL. | |
351 */ | |
352 int | |
353 call_def_function( | |
354 ufunc_T *ufunc, | |
355 int argc, // nr of arguments | |
356 typval_T *argv, // arguments | |
357 typval_T *rettv) // return value | |
358 { | |
359 ectx_T ectx; // execution context | |
360 int initial_frame_ptr; | |
361 typval_T *tv; | |
362 int idx; | |
363 int ret = FAIL; | |
364 dfunc_T *dfunc; | |
365 | |
366 // Get pointer to item in the stack. | |
367 #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) | |
368 | |
369 // Get pointer to item at the bottom of the stack, -1 is the bottom. | |
370 #undef STACK_TV_BOT | |
371 #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx) | |
372 | |
373 // Get pointer to local variable on the stack. | |
374 #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame + STACK_FRAME_SIZE + idx) | |
375 | |
376 vim_memset(&ectx, 0, sizeof(ectx)); | |
377 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); | |
378 if (ga_grow(&ectx.ec_stack, 20) == FAIL) | |
379 goto failed; | |
380 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; | |
381 | |
382 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); | |
383 | |
384 // Put arguments on the stack. | |
385 for (idx = 0; idx < argc; ++idx) | |
386 { | |
387 copy_tv(&argv[idx], STACK_TV_BOT(0)); | |
388 ++ectx.ec_stack.ga_len; | |
389 } | |
390 | |
391 // Frame pointer points to just after arguments. | |
392 ectx.ec_frame = ectx.ec_stack.ga_len; | |
393 initial_frame_ptr = ectx.ec_frame; | |
394 | |
395 // dummy frame entries | |
396 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) | |
397 { | |
398 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; | |
399 ++ectx.ec_stack.ga_len; | |
400 } | |
401 | |
402 // Reserve space for local variables. | |
403 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; | |
404 for (idx = 0; idx < dfunc->df_varcount; ++idx) | |
405 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; | |
406 ectx.ec_stack.ga_len += dfunc->df_varcount; | |
407 | |
408 ectx.ec_instr = dfunc->df_instr; | |
409 ectx.ec_iidx = 0; | |
410 for (;;) | |
411 { | |
412 isn_T *iptr; | |
413 trycmd_T *trycmd = NULL; | |
414 | |
415 if (did_throw && !ectx.ec_in_catch) | |
416 { | |
417 garray_T *trystack = &ectx.ec_trystack; | |
418 | |
419 // An exception jumps to the first catch, finally, or returns from | |
420 // the current function. | |
421 if (trystack->ga_len > 0) | |
422 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; | |
423 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame) | |
424 { | |
425 // jump to ":catch" or ":finally" | |
426 ectx.ec_in_catch = TRUE; | |
427 ectx.ec_iidx = trycmd->tcd_catch_idx; | |
428 } | |
429 else | |
430 { | |
431 // not inside try or need to return from current functions. | |
432 if (ectx.ec_frame == initial_frame_ptr) | |
433 { | |
434 // At the toplevel we are done. Push a dummy return value. | |
435 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
436 goto failed; | |
437 tv = STACK_TV_BOT(0); | |
438 tv->v_type = VAR_NUMBER; | |
439 tv->vval.v_number = 0; | |
440 ++ectx.ec_stack.ga_len; | |
441 goto done; | |
442 } | |
443 | |
444 func_return(&ectx); | |
445 } | |
446 continue; | |
447 } | |
448 | |
449 iptr = &ectx.ec_instr[ectx.ec_iidx++]; | |
450 switch (iptr->isn_type) | |
451 { | |
452 // execute Ex command line | |
453 case ISN_EXEC: | |
454 do_cmdline_cmd(iptr->isn_arg.string); | |
455 break; | |
456 | |
457 // execute :echo {string} ... | |
458 case ISN_ECHO: | |
459 { | |
460 int count = iptr->isn_arg.echo.echo_count; | |
461 int atstart = TRUE; | |
462 int needclr = TRUE; | |
463 | |
464 for (idx = 0; idx < count; ++idx) | |
465 { | |
466 tv = STACK_TV_BOT(idx - count); | |
467 echo_one(tv, iptr->isn_arg.echo.echo_with_white, | |
468 &atstart, &needclr); | |
469 clear_tv(tv); | |
470 } | |
471 ectx.ec_stack.ga_len -= count; | |
472 } | |
473 break; | |
474 | |
475 // load local variable or argument | |
476 case ISN_LOAD: | |
477 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
478 goto failed; | |
479 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); | |
480 ++ectx.ec_stack.ga_len; | |
481 break; | |
482 | |
483 // load v: variable | |
484 case ISN_LOADV: | |
485 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
486 goto failed; | |
487 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0)); | |
488 ++ectx.ec_stack.ga_len; | |
489 break; | |
490 | |
491 // load s: variable in vim9script | |
492 case ISN_LOADSCRIPT: | |
493 { | |
494 scriptitem_T *si = | |
495 &SCRIPT_ITEM(iptr->isn_arg.script.script_sid); | |
496 svar_T *sv; | |
497 | |
498 sv = ((svar_T *)si->sn_var_vals.ga_data) | |
499 + iptr->isn_arg.script.script_idx; | |
500 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
501 goto failed; | |
502 copy_tv(sv->sv_tv, STACK_TV_BOT(0)); | |
503 ++ectx.ec_stack.ga_len; | |
504 } | |
505 break; | |
506 | |
507 // load s: variable in old script | |
508 case ISN_LOADS: | |
509 { | |
510 hashtab_T *ht = &SCRIPT_VARS(iptr->isn_arg.loads.ls_sid); | |
511 char_u *name = iptr->isn_arg.loads.ls_name; | |
512 dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE); | |
513 if (di == NULL) | |
514 { | |
515 semsg(_("E121: Undefined variable: s:%s"), name); | |
516 goto failed; | |
517 } | |
518 else | |
519 { | |
520 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
521 goto failed; | |
522 copy_tv(&di->di_tv, STACK_TV_BOT(0)); | |
523 ++ectx.ec_stack.ga_len; | |
524 } | |
525 } | |
526 break; | |
527 | |
528 // load g: variable | |
529 case ISN_LOADG: | |
530 { | |
531 dictitem_T *di; | |
532 | |
533 di = find_var_in_ht(get_globvar_ht(), 0, | |
534 iptr->isn_arg.string, TRUE); | |
535 if (di == NULL) | |
536 { | |
537 semsg(_("E121: Undefined variable: g:%s"), | |
538 iptr->isn_arg.string); | |
539 goto failed; | |
540 } | |
541 else | |
542 { | |
543 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
544 goto failed; | |
545 copy_tv(&di->di_tv, STACK_TV_BOT(0)); | |
546 ++ectx.ec_stack.ga_len; | |
547 } | |
548 } | |
549 break; | |
550 | |
551 // load &option | |
552 case ISN_LOADOPT: | |
553 { | |
554 typval_T optval; | |
555 char_u *name = iptr->isn_arg.string; | |
556 | |
557 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
558 goto failed; | |
559 get_option_tv(&name, &optval, TRUE); | |
560 *STACK_TV_BOT(0) = optval; | |
561 ++ectx.ec_stack.ga_len; | |
562 } | |
563 break; | |
564 | |
565 // load $ENV | |
566 case ISN_LOADENV: | |
567 { | |
568 typval_T optval; | |
569 char_u *name = iptr->isn_arg.string; | |
570 | |
571 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
572 goto failed; | |
573 get_env_tv(&name, &optval, TRUE); | |
574 *STACK_TV_BOT(0) = optval; | |
575 ++ectx.ec_stack.ga_len; | |
576 } | |
577 break; | |
578 | |
579 // load @register | |
580 case ISN_LOADREG: | |
581 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
582 goto failed; | |
583 tv = STACK_TV_BOT(0); | |
584 tv->v_type = VAR_STRING; | |
585 tv->vval.v_string = get_reg_contents( | |
586 iptr->isn_arg.number, GREG_EXPR_SRC); | |
587 ++ectx.ec_stack.ga_len; | |
588 break; | |
589 | |
590 // store local variable | |
591 case ISN_STORE: | |
592 --ectx.ec_stack.ga_len; | |
593 tv = STACK_TV_VAR(iptr->isn_arg.number); | |
594 clear_tv(tv); | |
595 *tv = *STACK_TV_BOT(0); | |
596 break; | |
597 | |
598 // store script-local variable | |
599 case ISN_STORESCRIPT: | |
600 { | |
601 scriptitem_T *si = &SCRIPT_ITEM( | |
602 iptr->isn_arg.script.script_sid); | |
603 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) | |
604 + iptr->isn_arg.script.script_idx; | |
605 | |
606 --ectx.ec_stack.ga_len; | |
607 clear_tv(sv->sv_tv); | |
608 *sv->sv_tv = *STACK_TV_BOT(0); | |
609 } | |
610 break; | |
611 | |
612 // store option | |
613 case ISN_STOREOPT: | |
614 { | |
615 long n = 0; | |
616 char_u *s = NULL; | |
617 char *msg; | |
618 | |
619 --ectx.ec_stack.ga_len; | |
620 tv = STACK_TV_BOT(0); | |
621 if (tv->v_type == VAR_STRING) | |
622 s = tv->vval.v_string; | |
623 else if (tv->v_type == VAR_NUMBER) | |
624 n = tv->vval.v_number; | |
625 else | |
626 { | |
627 emsg(_("E1051: Expected string or number")); | |
628 goto failed; | |
629 } | |
630 msg = set_option_value(iptr->isn_arg.storeopt.so_name, | |
631 n, s, iptr->isn_arg.storeopt.so_flags); | |
632 if (msg != NULL) | |
633 { | |
634 emsg(_(msg)); | |
635 goto failed; | |
636 } | |
637 clear_tv(tv); | |
638 } | |
639 break; | |
640 | |
641 // store g: variable | |
642 case ISN_STOREG: | |
643 { | |
644 dictitem_T *di; | |
645 | |
646 --ectx.ec_stack.ga_len; | |
647 di = find_var_in_ht(get_globvar_ht(), 0, | |
648 iptr->isn_arg.string, TRUE); | |
649 if (di == NULL) | |
650 { | |
651 funccal_entry_T entry; | |
652 | |
653 save_funccal(&entry); | |
654 set_var_const(iptr->isn_arg.string, NULL, | |
655 STACK_TV_BOT(0), FALSE, 0); | |
656 restore_funccal(); | |
657 } | |
658 else | |
659 { | |
660 clear_tv(&di->di_tv); | |
661 di->di_tv = *STACK_TV_BOT(0); | |
662 } | |
663 } | |
664 break; | |
665 | |
666 // store number in local variable | |
667 case ISN_STORENR: | |
668 tv = STACK_TV_VAR(iptr->isn_arg.storenr.str_idx); | |
669 clear_tv(tv); | |
670 tv->v_type = VAR_NUMBER; | |
671 tv->vval.v_number = iptr->isn_arg.storenr.str_val; | |
672 break; | |
673 | |
674 // push constant | |
675 case ISN_PUSHNR: | |
676 case ISN_PUSHBOOL: | |
677 case ISN_PUSHSPEC: | |
678 case ISN_PUSHF: | |
679 case ISN_PUSHS: | |
680 case ISN_PUSHBLOB: | |
681 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
682 goto failed; | |
683 tv = STACK_TV_BOT(0); | |
684 ++ectx.ec_stack.ga_len; | |
685 switch (iptr->isn_type) | |
686 { | |
687 case ISN_PUSHNR: | |
688 tv->v_type = VAR_NUMBER; | |
689 tv->vval.v_number = iptr->isn_arg.number; | |
690 break; | |
691 case ISN_PUSHBOOL: | |
692 tv->v_type = VAR_BOOL; | |
693 tv->vval.v_number = iptr->isn_arg.number; | |
694 break; | |
695 case ISN_PUSHSPEC: | |
696 tv->v_type = VAR_SPECIAL; | |
697 tv->vval.v_number = iptr->isn_arg.number; | |
698 break; | |
699 #ifdef FEAT_FLOAT | |
700 case ISN_PUSHF: | |
701 tv->v_type = VAR_FLOAT; | |
702 tv->vval.v_float = iptr->isn_arg.fnumber; | |
703 break; | |
704 #endif | |
705 case ISN_PUSHBLOB: | |
706 blob_copy(iptr->isn_arg.blob, tv); | |
707 break; | |
708 default: | |
709 tv->v_type = VAR_STRING; | |
710 tv->vval.v_string = vim_strsave(iptr->isn_arg.string); | |
711 } | |
712 break; | |
713 | |
714 // create a list from items on the stack; uses a single allocation | |
715 // for the list header and the items | |
716 case ISN_NEWLIST: | |
717 { | |
718 int count = iptr->isn_arg.number; | |
719 list_T *list = list_alloc_with_items(count); | |
720 | |
721 if (list == NULL) | |
722 goto failed; | |
723 for (idx = 0; idx < count; ++idx) | |
724 list_set_item(list, idx, STACK_TV_BOT(idx - count)); | |
725 | |
726 if (count > 0) | |
727 ectx.ec_stack.ga_len -= count - 1; | |
728 else if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
729 goto failed; | |
730 else | |
731 ++ectx.ec_stack.ga_len; | |
732 tv = STACK_TV_BOT(-1); | |
733 tv->v_type = VAR_LIST; | |
734 tv->vval.v_list = list; | |
735 ++list->lv_refcount; | |
736 } | |
737 break; | |
738 | |
739 // create a dict from items on the stack | |
740 case ISN_NEWDICT: | |
741 { | |
742 int count = iptr->isn_arg.number; | |
743 dict_T *dict = dict_alloc(); | |
744 dictitem_T *item; | |
745 | |
746 if (dict == NULL) | |
747 goto failed; | |
748 for (idx = 0; idx < count; ++idx) | |
749 { | |
750 // check key type is VAR_STRING | |
751 tv = STACK_TV_BOT(2 * (idx - count)); | |
752 item = dictitem_alloc(tv->vval.v_string); | |
753 clear_tv(tv); | |
754 if (item == NULL) | |
755 goto failed; | |
756 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); | |
757 item->di_tv.v_lock = 0; | |
758 if (dict_add(dict, item) == FAIL) | |
759 goto failed; | |
760 } | |
761 | |
762 if (count > 0) | |
763 ectx.ec_stack.ga_len -= 2 * count - 1; | |
764 else if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
765 goto failed; | |
766 else | |
767 ++ectx.ec_stack.ga_len; | |
768 tv = STACK_TV_BOT(-1); | |
769 tv->v_type = VAR_DICT; | |
770 tv->vval.v_dict = dict; | |
771 ++dict->dv_refcount; | |
772 } | |
773 break; | |
774 | |
775 // call a :def function | |
776 case ISN_DCALL: | |
777 if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx, | |
778 iptr->isn_arg.dfunc.cdf_argcount, | |
779 &ectx) == FAIL) | |
780 goto failed; | |
781 break; | |
782 | |
783 // call a builtin function | |
784 case ISN_BCALL: | |
785 SOURCING_LNUM = iptr->isn_lnum; | |
786 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx, | |
787 iptr->isn_arg.bfunc.cbf_argcount, | |
788 &ectx) == FAIL) | |
789 goto failed; | |
790 break; | |
791 | |
792 // call a funcref or partial | |
793 case ISN_PCALL: | |
794 { | |
795 cpfunc_T *pfunc = &iptr->isn_arg.pfunc; | |
796 int r; | |
797 typval_T partial; | |
798 | |
799 SOURCING_LNUM = iptr->isn_lnum; | |
800 if (pfunc->cpf_top) | |
801 { | |
802 // funcref is above the arguments | |
803 tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1); | |
804 } | |
805 else | |
806 { | |
807 // Get the funcref from the stack. | |
808 --ectx.ec_stack.ga_len; | |
809 partial = *STACK_TV_BOT(0); | |
810 tv = &partial; | |
811 } | |
812 r = call_partial(tv, pfunc->cpf_argcount, &ectx); | |
813 if (tv == &partial) | |
814 clear_tv(&partial); | |
815 if (r == FAIL) | |
816 goto failed; | |
817 | |
818 if (pfunc->cpf_top) | |
819 { | |
820 // Get the funcref from the stack, overwrite with the | |
821 // return value. | |
822 clear_tv(tv); | |
823 --ectx.ec_stack.ga_len; | |
824 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); | |
825 } | |
826 } | |
827 break; | |
828 | |
829 // call a user defined function or funcref/partial | |
830 case ISN_UCALL: | |
831 { | |
832 cufunc_T *cufunc = &iptr->isn_arg.ufunc; | |
833 | |
834 SOURCING_LNUM = iptr->isn_lnum; | |
835 if (call_eval_func(cufunc->cuf_name, | |
836 cufunc->cuf_argcount, &ectx) == FAIL) | |
837 goto failed; | |
838 } | |
839 break; | |
840 | |
841 // return from a :def function call | |
842 case ISN_RETURN: | |
843 { | |
844 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame | |
845 && trycmd->tcd_finally_idx != 0) | |
846 { | |
847 // jump to ":finally" | |
848 ectx.ec_iidx = trycmd->tcd_finally_idx; | |
849 trycmd->tcd_return = TRUE; | |
850 } | |
851 else | |
852 { | |
853 // Restore previous function. If the frame pointer | |
854 // is zero then there is none and we are done. | |
855 if (ectx.ec_frame == initial_frame_ptr) | |
856 goto done; | |
857 | |
858 func_return(&ectx); | |
859 } | |
860 } | |
861 break; | |
862 | |
863 // push a function reference to a compiled function | |
864 case ISN_FUNCREF: | |
865 { | |
866 partial_T *pt = NULL; | |
867 | |
868 pt = ALLOC_CLEAR_ONE(partial_T); | |
869 if (pt == NULL) | |
870 goto failed; | |
871 dfunc = ((dfunc_T *)def_functions.ga_data) | |
872 + iptr->isn_arg.number; | |
873 pt->pt_func = dfunc->df_ufunc; | |
874 pt->pt_refcount = 1; | |
875 ++dfunc->df_ufunc->uf_refcount; | |
876 | |
877 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
878 goto failed; | |
879 tv = STACK_TV_BOT(0); | |
880 ++ectx.ec_stack.ga_len; | |
881 tv->vval.v_partial = pt; | |
882 tv->v_type = VAR_PARTIAL; | |
883 } | |
884 break; | |
885 | |
886 // jump if a condition is met | |
887 case ISN_JUMP: | |
888 { | |
889 jumpwhen_T when = iptr->isn_arg.jump.jump_when; | |
890 int jump = TRUE; | |
891 | |
892 if (when != JUMP_ALWAYS) | |
893 { | |
894 tv = STACK_TV_BOT(-1); | |
895 jump = tv2bool(tv); | |
896 if (when == JUMP_IF_FALSE | |
897 || when == JUMP_AND_KEEP_IF_FALSE) | |
898 jump = !jump; | |
899 if (when == JUMP_IF_FALSE || when == JUMP_IF_TRUE | |
900 || !jump) | |
901 { | |
902 // drop the value from the stack | |
903 clear_tv(tv); | |
904 --ectx.ec_stack.ga_len; | |
905 } | |
906 } | |
907 if (jump) | |
908 ectx.ec_iidx = iptr->isn_arg.jump.jump_where; | |
909 } | |
910 break; | |
911 | |
912 // top of a for loop | |
913 case ISN_FOR: | |
914 { | |
915 list_T *list = STACK_TV_BOT(-1)->vval.v_list; | |
916 typval_T *idxtv = | |
917 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx); | |
918 | |
919 // push the next item from the list | |
920 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
921 goto failed; | |
922 if (++idxtv->vval.v_number >= list->lv_len) | |
923 // past the end of the list, jump to "endfor" | |
924 ectx.ec_iidx = iptr->isn_arg.forloop.for_end; | |
925 else if (list->lv_first == &range_list_item) | |
926 { | |
927 // non-materialized range() list | |
928 tv = STACK_TV_BOT(0); | |
929 tv->v_type = VAR_NUMBER; | |
930 tv->vval.v_number = list_find_nr( | |
931 list, idxtv->vval.v_number, NULL); | |
932 ++ectx.ec_stack.ga_len; | |
933 } | |
934 else | |
935 { | |
936 listitem_T *li = list_find(list, idxtv->vval.v_number); | |
937 | |
938 if (li == NULL) | |
939 goto failed; | |
940 copy_tv(&li->li_tv, STACK_TV_BOT(0)); | |
941 ++ectx.ec_stack.ga_len; | |
942 } | |
943 } | |
944 break; | |
945 | |
946 // start of ":try" block | |
947 case ISN_TRY: | |
948 { | |
949 if (ga_grow(&ectx.ec_trystack, 1) == FAIL) | |
950 goto failed; | |
951 trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data) | |
952 + ectx.ec_trystack.ga_len; | |
953 ++ectx.ec_trystack.ga_len; | |
954 ++trylevel; | |
955 trycmd->tcd_frame = ectx.ec_frame; | |
956 trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch; | |
957 trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally; | |
958 } | |
959 break; | |
960 | |
961 case ISN_PUSHEXC: | |
962 if (current_exception == NULL) | |
963 { | |
964 iemsg("Evaluating catch while current_exception is NULL"); | |
965 goto failed; | |
966 } | |
967 if (ga_grow(&ectx.ec_stack, 1) == FAIL) | |
968 goto failed; | |
969 tv = STACK_TV_BOT(0); | |
970 ++ectx.ec_stack.ga_len; | |
971 tv->v_type = VAR_STRING; | |
972 tv->vval.v_string = vim_strsave( | |
973 (char_u *)current_exception->value); | |
974 break; | |
975 | |
976 case ISN_CATCH: | |
977 { | |
978 garray_T *trystack = &ectx.ec_trystack; | |
979 | |
980 if (trystack->ga_len > 0) | |
981 { | |
982 trycmd = ((trycmd_T *)trystack->ga_data) | |
983 + trystack->ga_len - 1; | |
984 trycmd->tcd_caught = TRUE; | |
985 } | |
986 did_emsg = got_int = did_throw = FALSE; | |
987 catch_exception(current_exception); | |
988 } | |
989 break; | |
990 | |
991 // end of ":try" block | |
992 case ISN_ENDTRY: | |
993 { | |
994 garray_T *trystack = &ectx.ec_trystack; | |
995 | |
996 if (trystack->ga_len > 0) | |
997 { | |
998 --trystack->ga_len; | |
999 --trylevel; | |
1000 trycmd = ((trycmd_T *)trystack->ga_data) | |
1001 + trystack->ga_len; | |
1002 if (trycmd->tcd_caught) | |
1003 { | |
1004 // discard the exception | |
1005 if (caught_stack == current_exception) | |
1006 caught_stack = caught_stack->caught; | |
1007 discard_current_exception(); | |
1008 } | |
1009 | |
1010 if (trycmd->tcd_return) | |
1011 { | |
1012 // Restore previous function. If the frame pointer | |
1013 // is zero then there is none and we are done. | |
1014 if (ectx.ec_frame == initial_frame_ptr) | |
1015 goto done; | |
1016 | |
1017 func_return(&ectx); | |
1018 } | |
1019 } | |
1020 } | |
1021 break; | |
1022 | |
1023 case ISN_THROW: | |
1024 --ectx.ec_stack.ga_len; | |
1025 tv = STACK_TV_BOT(0); | |
1026 if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL) | |
1027 { | |
1028 vim_free(tv->vval.v_string); | |
1029 goto failed; | |
1030 } | |
1031 did_throw = TRUE; | |
1032 break; | |
1033 | |
1034 // compare with special values | |
1035 case ISN_COMPAREBOOL: | |
1036 case ISN_COMPARESPECIAL: | |
1037 { | |
1038 typval_T *tv1 = STACK_TV_BOT(-2); | |
1039 typval_T *tv2 = STACK_TV_BOT(-1); | |
1040 varnumber_T arg1 = tv1->vval.v_number; | |
1041 varnumber_T arg2 = tv2->vval.v_number; | |
1042 int res; | |
1043 | |
1044 switch (iptr->isn_arg.op.op_type) | |
1045 { | |
1046 case EXPR_EQUAL: res = arg1 == arg2; break; | |
1047 case EXPR_NEQUAL: res = arg1 != arg2; break; | |
1048 default: res = 0; break; | |
1049 } | |
1050 | |
1051 --ectx.ec_stack.ga_len; | |
1052 tv1->v_type = VAR_BOOL; | |
1053 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; | |
1054 } | |
1055 break; | |
1056 | |
1057 // Operation with two number arguments | |
1058 case ISN_OPNR: | |
1059 case ISN_COMPARENR: | |
1060 { | |
1061 typval_T *tv1 = STACK_TV_BOT(-2); | |
1062 typval_T *tv2 = STACK_TV_BOT(-1); | |
1063 varnumber_T arg1 = tv1->vval.v_number; | |
1064 varnumber_T arg2 = tv2->vval.v_number; | |
1065 varnumber_T res; | |
1066 | |
1067 switch (iptr->isn_arg.op.op_type) | |
1068 { | |
1069 case EXPR_MULT: res = arg1 * arg2; break; | |
1070 case EXPR_DIV: res = arg1 / arg2; break; | |
1071 case EXPR_REM: res = arg1 % arg2; break; | |
1072 case EXPR_SUB: res = arg1 - arg2; break; | |
1073 case EXPR_ADD: res = arg1 + arg2; break; | |
1074 | |
1075 case EXPR_EQUAL: res = arg1 == arg2; break; | |
1076 case EXPR_NEQUAL: res = arg1 != arg2; break; | |
1077 case EXPR_GREATER: res = arg1 > arg2; break; | |
1078 case EXPR_GEQUAL: res = arg1 >= arg2; break; | |
1079 case EXPR_SMALLER: res = arg1 < arg2; break; | |
1080 case EXPR_SEQUAL: res = arg1 <= arg2; break; | |
1081 default: res = 0; break; | |
1082 } | |
1083 | |
1084 --ectx.ec_stack.ga_len; | |
1085 if (iptr->isn_type == ISN_COMPARENR) | |
1086 { | |
1087 tv1->v_type = VAR_BOOL; | |
1088 tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; | |
1089 } | |
1090 else | |
1091 tv1->vval.v_number = res; | |
1092 } | |
1093 break; | |
1094 | |
1095 // Computation with two float arguments | |
1096 case ISN_OPFLOAT: | |
1097 case ISN_COMPAREFLOAT: | |
1098 { | |
1099 typval_T *tv1 = STACK_TV_BOT(-2); | |
1100 typval_T *tv2 = STACK_TV_BOT(-1); | |
1101 float_T arg1 = tv1->vval.v_float; | |
1102 float_T arg2 = tv2->vval.v_float; | |
1103 float_T res = 0; | |
1104 int cmp = FALSE; | |
1105 | |
1106 switch (iptr->isn_arg.op.op_type) | |
1107 { | |
1108 case EXPR_MULT: res = arg1 * arg2; break; | |
1109 case EXPR_DIV: res = arg1 / arg2; break; | |
1110 case EXPR_SUB: res = arg1 - arg2; break; | |
1111 case EXPR_ADD: res = arg1 + arg2; break; | |
1112 | |
1113 case EXPR_EQUAL: cmp = arg1 == arg2; break; | |
1114 case EXPR_NEQUAL: cmp = arg1 != arg2; break; | |
1115 case EXPR_GREATER: cmp = arg1 > arg2; break; | |
1116 case EXPR_GEQUAL: cmp = arg1 >= arg2; break; | |
1117 case EXPR_SMALLER: cmp = arg1 < arg2; break; | |
1118 case EXPR_SEQUAL: cmp = arg1 <= arg2; break; | |
1119 default: cmp = 0; break; | |
1120 } | |
1121 --ectx.ec_stack.ga_len; | |
1122 if (iptr->isn_type == ISN_COMPAREFLOAT) | |
1123 { | |
1124 tv1->v_type = VAR_BOOL; | |
1125 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; | |
1126 } | |
1127 else | |
1128 tv1->vval.v_float = res; | |
1129 } | |
1130 break; | |
1131 | |
1132 case ISN_COMPARELIST: | |
1133 { | |
1134 typval_T *tv1 = STACK_TV_BOT(-2); | |
1135 typval_T *tv2 = STACK_TV_BOT(-1); | |
1136 list_T *arg1 = tv1->vval.v_list; | |
1137 list_T *arg2 = tv2->vval.v_list; | |
1138 int cmp = FALSE; | |
1139 int ic = iptr->isn_arg.op.op_ic; | |
1140 | |
1141 switch (iptr->isn_arg.op.op_type) | |
1142 { | |
1143 case EXPR_EQUAL: cmp = | |
1144 list_equal(arg1, arg2, ic, FALSE); break; | |
1145 case EXPR_NEQUAL: cmp = | |
1146 !list_equal(arg1, arg2, ic, FALSE); break; | |
1147 case EXPR_IS: cmp = arg1 == arg2; break; | |
1148 case EXPR_ISNOT: cmp = arg1 != arg2; break; | |
1149 default: cmp = 0; break; | |
1150 } | |
1151 --ectx.ec_stack.ga_len; | |
1152 clear_tv(tv1); | |
1153 clear_tv(tv2); | |
1154 tv1->v_type = VAR_BOOL; | |
1155 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; | |
1156 } | |
1157 break; | |
1158 | |
1159 case ISN_COMPAREBLOB: | |
1160 { | |
1161 typval_T *tv1 = STACK_TV_BOT(-2); | |
1162 typval_T *tv2 = STACK_TV_BOT(-1); | |
1163 blob_T *arg1 = tv1->vval.v_blob; | |
1164 blob_T *arg2 = tv2->vval.v_blob; | |
1165 int cmp = FALSE; | |
1166 | |
1167 switch (iptr->isn_arg.op.op_type) | |
1168 { | |
1169 case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break; | |
1170 case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break; | |
1171 case EXPR_IS: cmp = arg1 == arg2; break; | |
1172 case EXPR_ISNOT: cmp = arg1 != arg2; break; | |
1173 default: cmp = 0; break; | |
1174 } | |
1175 --ectx.ec_stack.ga_len; | |
1176 clear_tv(tv1); | |
1177 clear_tv(tv2); | |
1178 tv1->v_type = VAR_BOOL; | |
1179 tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; | |
1180 } | |
1181 break; | |
1182 | |
1183 // TODO: handle separately | |
1184 case ISN_COMPARESTRING: | |
1185 case ISN_COMPAREDICT: | |
1186 case ISN_COMPAREFUNC: | |
1187 case ISN_COMPAREPARTIAL: | |
1188 case ISN_COMPAREANY: | |
1189 { | |
1190 typval_T *tv1 = STACK_TV_BOT(-2); | |
1191 typval_T *tv2 = STACK_TV_BOT(-1); | |
1192 exptype_T exptype = iptr->isn_arg.op.op_type; | |
1193 int ic = iptr->isn_arg.op.op_ic; | |
1194 | |
1195 typval_compare(tv1, tv2, exptype, ic); | |
1196 clear_tv(tv2); | |
1197 tv1->v_type = VAR_BOOL; | |
1198 tv1->vval.v_number = tv1->vval.v_number | |
1199 ? VVAL_TRUE : VVAL_FALSE; | |
1200 --ectx.ec_stack.ga_len; | |
1201 } | |
1202 break; | |
1203 | |
1204 case ISN_ADDLIST: | |
1205 case ISN_ADDBLOB: | |
1206 { | |
1207 typval_T *tv1 = STACK_TV_BOT(-2); | |
1208 typval_T *tv2 = STACK_TV_BOT(-1); | |
1209 | |
1210 if (iptr->isn_type == ISN_ADDLIST) | |
1211 eval_addlist(tv1, tv2); | |
1212 else | |
1213 eval_addblob(tv1, tv2); | |
1214 clear_tv(tv2); | |
1215 --ectx.ec_stack.ga_len; | |
1216 } | |
1217 break; | |
1218 | |
1219 // Computation with two arguments of unknown type | |
1220 case ISN_OPANY: | |
1221 { | |
1222 typval_T *tv1 = STACK_TV_BOT(-2); | |
1223 typval_T *tv2 = STACK_TV_BOT(-1); | |
1224 varnumber_T n1, n2; | |
1225 #ifdef FEAT_FLOAT | |
1226 float_T f1 = 0, f2 = 0; | |
1227 #endif | |
1228 int error = FALSE; | |
1229 | |
1230 if (iptr->isn_arg.op.op_type == EXPR_ADD) | |
1231 { | |
1232 if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST) | |
1233 { | |
1234 eval_addlist(tv1, tv2); | |
1235 clear_tv(tv2); | |
1236 --ectx.ec_stack.ga_len; | |
1237 break; | |
1238 } | |
1239 else if (tv1->v_type == VAR_BLOB | |
1240 && tv2->v_type == VAR_BLOB) | |
1241 { | |
1242 eval_addblob(tv1, tv2); | |
1243 clear_tv(tv2); | |
1244 --ectx.ec_stack.ga_len; | |
1245 break; | |
1246 } | |
1247 } | |
1248 #ifdef FEAT_FLOAT | |
1249 if (tv1->v_type == VAR_FLOAT) | |
1250 { | |
1251 f1 = tv1->vval.v_float; | |
1252 n1 = 0; | |
1253 } | |
1254 else | |
1255 #endif | |
1256 { | |
1257 n1 = tv_get_number_chk(tv1, &error); | |
1258 if (error) | |
1259 goto failed; | |
1260 #ifdef FEAT_FLOAT | |
1261 if (tv2->v_type == VAR_FLOAT) | |
1262 f1 = n1; | |
1263 #endif | |
1264 } | |
1265 #ifdef FEAT_FLOAT | |
1266 if (tv2->v_type == VAR_FLOAT) | |
1267 { | |
1268 f2 = tv2->vval.v_float; | |
1269 n2 = 0; | |
1270 } | |
1271 else | |
1272 #endif | |
1273 { | |
1274 n2 = tv_get_number_chk(tv2, &error); | |
1275 if (error) | |
1276 goto failed; | |
1277 #ifdef FEAT_FLOAT | |
1278 if (tv1->v_type == VAR_FLOAT) | |
1279 f2 = n2; | |
1280 #endif | |
1281 } | |
1282 #ifdef FEAT_FLOAT | |
1283 // if there is a float on either side the result is a float | |
1284 if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT) | |
1285 { | |
1286 switch (iptr->isn_arg.op.op_type) | |
1287 { | |
1288 case EXPR_MULT: f1 = f1 * f2; break; | |
1289 case EXPR_DIV: f1 = f1 / f2; break; | |
1290 case EXPR_SUB: f1 = f1 - f2; break; | |
1291 case EXPR_ADD: f1 = f1 + f2; break; | |
1292 default: emsg(_(e_modulus)); goto failed; | |
1293 } | |
1294 clear_tv(tv1); | |
1295 clear_tv(tv2); | |
1296 tv1->v_type = VAR_FLOAT; | |
1297 tv1->vval.v_float = f1; | |
1298 --ectx.ec_stack.ga_len; | |
1299 } | |
1300 else | |
1301 #endif | |
1302 { | |
1303 switch (iptr->isn_arg.op.op_type) | |
1304 { | |
1305 case EXPR_MULT: n1 = n1 * n2; break; | |
1306 case EXPR_DIV: n1 = num_divide(n1, n2); break; | |
1307 case EXPR_SUB: n1 = n1 - n2; break; | |
1308 case EXPR_ADD: n1 = n1 + n2; break; | |
1309 default: n1 = num_modulus(n1, n2); break; | |
1310 } | |
1311 clear_tv(tv1); | |
1312 clear_tv(tv2); | |
1313 tv1->v_type = VAR_NUMBER; | |
1314 tv1->vval.v_number = n1; | |
1315 --ectx.ec_stack.ga_len; | |
1316 } | |
1317 } | |
1318 break; | |
1319 | |
1320 case ISN_CONCAT: | |
1321 { | |
1322 char_u *str1 = STACK_TV_BOT(-2)->vval.v_string; | |
1323 char_u *str2 = STACK_TV_BOT(-1)->vval.v_string; | |
1324 char_u *res; | |
1325 | |
1326 res = concat_str(str1, str2); | |
1327 clear_tv(STACK_TV_BOT(-2)); | |
1328 clear_tv(STACK_TV_BOT(-1)); | |
1329 --ectx.ec_stack.ga_len; | |
1330 STACK_TV_BOT(-1)->vval.v_string = res; | |
1331 } | |
1332 break; | |
1333 | |
1334 case ISN_INDEX: | |
1335 { | |
1336 list_T *list; | |
1337 varnumber_T n; | |
1338 listitem_T *li; | |
1339 | |
1340 // list index: list is at stack-2, index at stack-1 | |
1341 tv = STACK_TV_BOT(-2); | |
1342 if (tv->v_type != VAR_LIST) | |
1343 { | |
1344 emsg(_(e_listreq)); | |
1345 goto failed; | |
1346 } | |
1347 list = tv->vval.v_list; | |
1348 | |
1349 tv = STACK_TV_BOT(-1); | |
1350 if (tv->v_type != VAR_NUMBER) | |
1351 { | |
1352 emsg(_(e_number_exp)); | |
1353 goto failed; | |
1354 } | |
1355 n = tv->vval.v_number; | |
1356 clear_tv(tv); | |
1357 if ((li = list_find(list, n)) == NULL) | |
1358 { | |
1359 semsg(_(e_listidx), n); | |
1360 goto failed; | |
1361 } | |
1362 --ectx.ec_stack.ga_len; | |
1363 clear_tv(STACK_TV_BOT(-1)); | |
1364 copy_tv(&li->li_tv, STACK_TV_BOT(-1)); | |
1365 } | |
1366 break; | |
1367 | |
1368 // dict member with string key | |
1369 case ISN_MEMBER: | |
1370 { | |
1371 dict_T *dict; | |
1372 dictitem_T *di; | |
1373 | |
1374 tv = STACK_TV_BOT(-1); | |
1375 if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) | |
1376 { | |
1377 emsg(_(e_dictreq)); | |
1378 goto failed; | |
1379 } | |
1380 dict = tv->vval.v_dict; | |
1381 | |
1382 if ((di = dict_find(dict, iptr->isn_arg.string, -1)) | |
1383 == NULL) | |
1384 { | |
1385 semsg(_(e_dictkey), iptr->isn_arg.string); | |
1386 goto failed; | |
1387 } | |
1388 clear_tv(tv); | |
1389 copy_tv(&di->di_tv, tv); | |
1390 } | |
1391 break; | |
1392 | |
1393 case ISN_NEGATENR: | |
1394 tv = STACK_TV_BOT(-1); | |
1395 tv->vval.v_number = -tv->vval.v_number; | |
1396 break; | |
1397 | |
1398 case ISN_CHECKNR: | |
1399 { | |
1400 int error = FALSE; | |
1401 | |
1402 tv = STACK_TV_BOT(-1); | |
1403 if (check_not_string(tv) == FAIL) | |
1404 { | |
1405 --ectx.ec_stack.ga_len; | |
1406 goto failed; | |
1407 } | |
1408 (void)tv_get_number_chk(tv, &error); | |
1409 if (error) | |
1410 goto failed; | |
1411 } | |
1412 break; | |
1413 | |
1414 case ISN_CHECKTYPE: | |
1415 { | |
1416 checktype_T *ct = &iptr->isn_arg.type; | |
1417 | |
1418 tv = STACK_TV_BOT(ct->ct_off); | |
1419 if (tv->v_type != ct->ct_type) | |
1420 { | |
1421 semsg(_("E1029: Expected %s but got %s"), | |
1422 vartype_name(ct->ct_type), | |
1423 vartype_name(tv->v_type)); | |
1424 goto failed; | |
1425 } | |
1426 } | |
1427 break; | |
1428 | |
1429 case ISN_2BOOL: | |
1430 { | |
1431 int n; | |
1432 | |
1433 tv = STACK_TV_BOT(-1); | |
1434 n = tv2bool(tv); | |
1435 if (iptr->isn_arg.number) // invert | |
1436 n = !n; | |
1437 clear_tv(tv); | |
1438 tv->v_type = VAR_BOOL; | |
1439 tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE; | |
1440 } | |
1441 break; | |
1442 | |
1443 case ISN_2STRING: | |
1444 { | |
1445 char_u *str; | |
1446 | |
1447 tv = STACK_TV_BOT(iptr->isn_arg.number); | |
1448 if (tv->v_type != VAR_STRING) | |
1449 { | |
1450 str = typval_tostring(tv); | |
1451 clear_tv(tv); | |
1452 tv->v_type = VAR_STRING; | |
1453 tv->vval.v_string = str; | |
1454 } | |
1455 } | |
1456 break; | |
1457 | |
1458 case ISN_DROP: | |
1459 --ectx.ec_stack.ga_len; | |
1460 clear_tv(STACK_TV_BOT(0)); | |
1461 break; | |
1462 } | |
1463 } | |
1464 | |
1465 done: | |
1466 // function finished, get result from the stack. | |
1467 tv = STACK_TV_BOT(-1); | |
1468 *rettv = *tv; | |
1469 tv->v_type = VAR_UNKNOWN; | |
1470 ret = OK; | |
1471 | |
1472 failed: | |
1473 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx) | |
1474 clear_tv(STACK_TV(idx)); | |
1475 vim_free(ectx.ec_stack.ga_data); | |
1476 return ret; | |
1477 } | |
1478 | |
1479 #define DISASSEMBLE 1 | |
1480 | |
1481 /* | |
1482 * ":dissassemble". | |
1483 */ | |
1484 void | |
1485 ex_disassemble(exarg_T *eap) | |
1486 { | |
1487 #ifdef DISASSEMBLE | |
1488 ufunc_T *ufunc = find_func(eap->arg, NULL); | |
1489 dfunc_T *dfunc; | |
1490 isn_T *instr; | |
1491 int current; | |
1492 int line_idx = 0; | |
1493 int prev_current = 0; | |
1494 | |
1495 if (ufunc == NULL) | |
1496 { | |
1497 semsg("Cannot find function %s", eap->arg); | |
1498 return; | |
1499 } | |
1500 if (ufunc->uf_dfunc_idx < 0) | |
1501 { | |
1502 semsg("Function %s is not compiled", eap->arg); | |
1503 return; | |
1504 } | |
1505 if (ufunc->uf_name_exp != NULL) | |
1506 msg((char *)ufunc->uf_name_exp); | |
1507 else | |
1508 msg((char *)ufunc->uf_name); | |
1509 | |
1510 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; | |
1511 instr = dfunc->df_instr; | |
1512 for (current = 0; current < dfunc->df_instr_count; ++current) | |
1513 { | |
1514 isn_T *iptr = &instr[current]; | |
1515 | |
1516 while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len) | |
1517 { | |
1518 if (current > prev_current) | |
1519 { | |
1520 msg_puts("\n\n"); | |
1521 prev_current = current; | |
1522 } | |
1523 msg(((char **)ufunc->uf_lines.ga_data)[line_idx++]); | |
1524 } | |
1525 | |
1526 switch (iptr->isn_type) | |
1527 { | |
1528 case ISN_EXEC: | |
1529 smsg("%4d EXEC %s", current, iptr->isn_arg.string); | |
1530 break; | |
1531 case ISN_ECHO: | |
1532 { | |
1533 echo_T *echo = &iptr->isn_arg.echo; | |
1534 | |
1535 smsg("%4d %s %d", current, | |
1536 echo->echo_with_white ? "ECHO" : "ECHON", | |
1537 echo->echo_count); | |
1538 } | |
1539 break; | |
1540 case ISN_LOAD: | |
1541 if (iptr->isn_arg.number < 0) | |
1542 smsg("%4d LOAD arg[%lld]", current, | |
1543 iptr->isn_arg.number + STACK_FRAME_SIZE); | |
1544 else | |
1545 smsg("%4d LOAD $%lld", current, iptr->isn_arg.number); | |
1546 break; | |
1547 case ISN_LOADV: | |
1548 smsg("%4d LOADV v:%s", current, | |
1549 get_vim_var_name(iptr->isn_arg.number)); | |
1550 break; | |
1551 case ISN_LOADSCRIPT: | |
1552 { | |
1553 scriptitem_T *si = | |
1554 &SCRIPT_ITEM(iptr->isn_arg.script.script_sid); | |
1555 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) | |
1556 + iptr->isn_arg.script.script_idx; | |
1557 | |
1558 smsg("%4d LOADSCRIPT %s from %s", current, | |
1559 sv->sv_name, si->sn_name); | |
1560 } | |
1561 break; | |
1562 case ISN_LOADS: | |
1563 { | |
1564 scriptitem_T *si = &SCRIPT_ITEM(iptr->isn_arg.loads.ls_sid); | |
1565 | |
1566 smsg("%4d LOADS s:%s from %s", current, | |
1567 iptr->isn_arg.string, si->sn_name); | |
1568 } | |
1569 break; | |
1570 case ISN_LOADG: | |
1571 smsg("%4d LOADG g:%s", current, iptr->isn_arg.string); | |
1572 break; | |
1573 case ISN_LOADOPT: | |
1574 smsg("%4d LOADOPT %s", current, iptr->isn_arg.string); | |
1575 break; | |
1576 case ISN_LOADENV: | |
1577 smsg("%4d LOADENV %s", current, iptr->isn_arg.string); | |
1578 break; | |
1579 case ISN_LOADREG: | |
1580 smsg("%4d LOADREG @%c", current, iptr->isn_arg.number); | |
1581 break; | |
1582 | |
1583 case ISN_STORE: | |
1584 smsg("%4d STORE $%lld", current, iptr->isn_arg.number); | |
1585 break; | |
1586 case ISN_STOREG: | |
1587 smsg("%4d STOREG g:%s", current, iptr->isn_arg.string); | |
1588 break; | |
1589 case ISN_STORESCRIPT: | |
1590 { | |
1591 scriptitem_T *si = | |
1592 &SCRIPT_ITEM(iptr->isn_arg.script.script_sid); | |
1593 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) | |
1594 + iptr->isn_arg.script.script_idx; | |
1595 | |
1596 smsg("%4d STORESCRIPT %s in %s", current, | |
1597 sv->sv_name, si->sn_name); | |
1598 } | |
1599 break; | |
1600 case ISN_STOREOPT: | |
1601 smsg("%4d STOREOPT &%s", current, | |
1602 iptr->isn_arg.storeopt.so_name); | |
1603 break; | |
1604 | |
1605 case ISN_STORENR: | |
1606 smsg("%4d STORE %lld in $%d", current, | |
1607 iptr->isn_arg.storenr.str_val, | |
1608 iptr->isn_arg.storenr.str_idx); | |
1609 break; | |
1610 | |
1611 // constants | |
1612 case ISN_PUSHNR: | |
1613 smsg("%4d PUSHNR %lld", current, iptr->isn_arg.number); | |
1614 break; | |
1615 case ISN_PUSHBOOL: | |
1616 case ISN_PUSHSPEC: | |
1617 smsg("%4d PUSH %s", current, | |
1618 get_var_special_name(iptr->isn_arg.number)); | |
1619 break; | |
1620 case ISN_PUSHF: | |
1621 smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber); | |
1622 break; | |
1623 case ISN_PUSHS: | |
1624 smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string); | |
1625 break; | |
1626 case ISN_PUSHBLOB: | |
1627 { | |
1628 char_u *r; | |
1629 char_u numbuf[NUMBUFLEN]; | |
1630 char_u *tofree; | |
1631 | |
1632 r = blob2string(iptr->isn_arg.blob, &tofree, numbuf); | |
1633 smsg("%4d PUSHBLOB \"%s\"", current, r); | |
1634 vim_free(tofree); | |
1635 } | |
1636 break; | |
1637 case ISN_PUSHEXC: | |
1638 smsg("%4d PUSH v:exception", current); | |
1639 break; | |
1640 case ISN_NEWLIST: | |
1641 smsg("%4d NEWLIST size %lld", current, iptr->isn_arg.number); | |
1642 break; | |
1643 case ISN_NEWDICT: | |
1644 smsg("%4d NEWDICT size %lld", current, iptr->isn_arg.number); | |
1645 break; | |
1646 | |
1647 // function call | |
1648 case ISN_BCALL: | |
1649 { | |
1650 cbfunc_T *cbfunc = &iptr->isn_arg.bfunc; | |
1651 | |
1652 smsg("%4d BCALL %s(argc %d)", current, | |
1653 internal_func_name(cbfunc->cbf_idx), | |
1654 cbfunc->cbf_argcount); | |
1655 } | |
1656 break; | |
1657 case ISN_DCALL: | |
1658 { | |
1659 cdfunc_T *cdfunc = &iptr->isn_arg.dfunc; | |
1660 dfunc_T *df = ((dfunc_T *)def_functions.ga_data) | |
1661 + cdfunc->cdf_idx; | |
1662 | |
1663 smsg("%4d DCALL %s(argc %d)", current, | |
1664 df->df_ufunc->uf_name_exp != NULL | |
1665 ? df->df_ufunc->uf_name_exp | |
1666 : df->df_ufunc->uf_name, cdfunc->cdf_argcount); | |
1667 } | |
1668 break; | |
1669 case ISN_UCALL: | |
1670 { | |
1671 cufunc_T *cufunc = &iptr->isn_arg.ufunc; | |
1672 | |
1673 smsg("%4d UCALL %s(argc %d)", current, | |
1674 cufunc->cuf_name, cufunc->cuf_argcount); | |
1675 } | |
1676 break; | |
1677 case ISN_PCALL: | |
1678 { | |
1679 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc; | |
1680 | |
1681 smsg("%4d PCALL%s (argc %d)", current, | |
1682 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); | |
1683 } | |
1684 break; | |
1685 case ISN_RETURN: | |
1686 smsg("%4d RETURN", current); | |
1687 break; | |
1688 case ISN_FUNCREF: | |
1689 { | |
1690 dfunc_T *df = ((dfunc_T *)def_functions.ga_data) | |
1691 + iptr->isn_arg.number; | |
1692 | |
1693 smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name); | |
1694 } | |
1695 break; | |
1696 | |
1697 case ISN_JUMP: | |
1698 { | |
1699 char *when = "?"; | |
1700 | |
1701 switch (iptr->isn_arg.jump.jump_when) | |
1702 { | |
1703 case JUMP_ALWAYS: | |
1704 when = "JUMP"; | |
1705 break; | |
1706 case JUMP_IF_TRUE: | |
1707 when = "JUMP_IF_TRUE"; | |
1708 break; | |
1709 case JUMP_AND_KEEP_IF_TRUE: | |
1710 when = "JUMP_AND_KEEP_IF_TRUE"; | |
1711 break; | |
1712 case JUMP_IF_FALSE: | |
1713 when = "JUMP_IF_FALSE"; | |
1714 break; | |
1715 case JUMP_AND_KEEP_IF_FALSE: | |
1716 when = "JUMP_AND_KEEP_IF_FALSE"; | |
1717 break; | |
1718 } | |
1719 smsg("%4d %s -> %lld", current, when, | |
1720 iptr->isn_arg.jump.jump_where); | |
1721 } | |
1722 break; | |
1723 | |
1724 case ISN_FOR: | |
1725 { | |
1726 forloop_T *forloop = &iptr->isn_arg.forloop; | |
1727 | |
1728 smsg("%4d FOR $%d -> %d", current, | |
1729 forloop->for_idx, forloop->for_end); | |
1730 } | |
1731 break; | |
1732 | |
1733 case ISN_TRY: | |
1734 { | |
1735 try_T *try = &iptr->isn_arg.try; | |
1736 | |
1737 smsg("%4d TRY catch -> %d, finally -> %d", current, | |
1738 try->try_catch, try->try_finally); | |
1739 } | |
1740 break; | |
1741 case ISN_CATCH: | |
1742 // TODO | |
1743 smsg("%4d CATCH", current); | |
1744 break; | |
1745 case ISN_ENDTRY: | |
1746 smsg("%4d ENDTRY", current); | |
1747 break; | |
1748 case ISN_THROW: | |
1749 smsg("%4d THROW", current); | |
1750 break; | |
1751 | |
1752 // expression operations on number | |
1753 case ISN_OPNR: | |
1754 case ISN_OPFLOAT: | |
1755 case ISN_OPANY: | |
1756 { | |
1757 char *what; | |
1758 char *ins; | |
1759 | |
1760 switch (iptr->isn_arg.op.op_type) | |
1761 { | |
1762 case EXPR_MULT: what = "*"; break; | |
1763 case EXPR_DIV: what = "/"; break; | |
1764 case EXPR_REM: what = "%"; break; | |
1765 case EXPR_SUB: what = "-"; break; | |
1766 case EXPR_ADD: what = "+"; break; | |
1767 default: what = "???"; break; | |
1768 } | |
1769 switch (iptr->isn_type) | |
1770 { | |
1771 case ISN_OPNR: ins = "OPNR"; break; | |
1772 case ISN_OPFLOAT: ins = "OPFLOAT"; break; | |
1773 case ISN_OPANY: ins = "OPANY"; break; | |
1774 default: ins = "???"; break; | |
1775 } | |
1776 smsg("%4d %s %s", current, ins, what); | |
1777 } | |
1778 break; | |
1779 | |
1780 case ISN_COMPAREBOOL: | |
1781 case ISN_COMPARESPECIAL: | |
1782 case ISN_COMPARENR: | |
1783 case ISN_COMPAREFLOAT: | |
1784 case ISN_COMPARESTRING: | |
1785 case ISN_COMPAREBLOB: | |
1786 case ISN_COMPARELIST: | |
1787 case ISN_COMPAREDICT: | |
1788 case ISN_COMPAREFUNC: | |
1789 case ISN_COMPAREPARTIAL: | |
1790 case ISN_COMPAREANY: | |
1791 { | |
1792 char *p; | |
1793 char buf[10]; | |
1794 char *type; | |
1795 | |
1796 switch (iptr->isn_arg.op.op_type) | |
1797 { | |
1798 case EXPR_EQUAL: p = "=="; break; | |
1799 case EXPR_NEQUAL: p = "!="; break; | |
1800 case EXPR_GREATER: p = ">"; break; | |
1801 case EXPR_GEQUAL: p = ">="; break; | |
1802 case EXPR_SMALLER: p = "<"; break; | |
1803 case EXPR_SEQUAL: p = "<="; break; | |
1804 case EXPR_MATCH: p = "=~"; break; | |
1805 case EXPR_IS: p = "is"; break; | |
1806 case EXPR_ISNOT: p = "isnot"; break; | |
1807 case EXPR_NOMATCH: p = "!~"; break; | |
1808 default: p = "???"; break; | |
1809 } | |
1810 STRCPY(buf, p); | |
1811 if (iptr->isn_arg.op.op_ic == TRUE) | |
1812 strcat(buf, "?"); | |
1813 switch(iptr->isn_type) | |
1814 { | |
1815 case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break; | |
1816 case ISN_COMPARESPECIAL: | |
1817 type = "COMPARESPECIAL"; break; | |
1818 case ISN_COMPARENR: type = "COMPARENR"; break; | |
1819 case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break; | |
1820 case ISN_COMPARESTRING: | |
1821 type = "COMPARESTRING"; break; | |
1822 case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break; | |
1823 case ISN_COMPARELIST: type = "COMPARELIST"; break; | |
1824 case ISN_COMPAREDICT: type = "COMPAREDICT"; break; | |
1825 case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break; | |
1826 case ISN_COMPAREPARTIAL: | |
1827 type = "COMPAREPARTIAL"; break; | |
1828 case ISN_COMPAREANY: type = "COMPAREANY"; break; | |
1829 default: type = "???"; break; | |
1830 } | |
1831 | |
1832 smsg("%4d %s %s", current, type, buf); | |
1833 } | |
1834 break; | |
1835 | |
1836 case ISN_ADDLIST: smsg("%4d ADDLIST", current); break; | |
1837 case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break; | |
1838 | |
1839 // expression operations | |
1840 case ISN_CONCAT: smsg("%4d CONCAT", current); break; | |
1841 case ISN_INDEX: smsg("%4d INDEX", current); break; | |
1842 case ISN_MEMBER: smsg("%4d MEMBER %s", current, | |
1843 iptr->isn_arg.string); break; | |
1844 case ISN_NEGATENR: smsg("%4d NEGATENR", current); break; | |
1845 | |
1846 case ISN_CHECKNR: smsg("%4d CHECKNR", current); break; | |
1847 case ISN_CHECKTYPE: smsg("%4d CHECKTYPE %s stack[%d]", current, | |
1848 vartype_name(iptr->isn_arg.type.ct_type), | |
1849 iptr->isn_arg.type.ct_off); | |
1850 break; | |
1851 case ISN_2BOOL: if (iptr->isn_arg.number) | |
1852 smsg("%4d INVERT (!val)", current); | |
1853 else | |
1854 smsg("%4d 2BOOL (!!val)", current); | |
1855 break; | |
1856 case ISN_2STRING: smsg("%4d 2STRING stack[%d]", current, | |
1857 iptr->isn_arg.number); | |
1858 break; | |
1859 | |
1860 case ISN_DROP: smsg("%4d DROP", current); break; | |
1861 } | |
1862 } | |
1863 #endif | |
1864 } | |
1865 | |
1866 /* | |
1867 * Return TRUE when "tv" is not falsey: non-zero, non-empty string, non-empty | |
1868 * list, etc. Mostly like what JavaScript does, except that empty list and | |
1869 * empty dictionary are FALSE. | |
1870 */ | |
1871 int | |
1872 tv2bool(typval_T *tv) | |
1873 { | |
1874 switch (tv->v_type) | |
1875 { | |
1876 case VAR_NUMBER: | |
1877 return tv->vval.v_number != 0; | |
1878 case VAR_FLOAT: | |
1879 #ifdef FEAT_FLOAT | |
1880 return tv->vval.v_float != 0.0; | |
1881 #else | |
1882 break; | |
1883 #endif | |
1884 case VAR_PARTIAL: | |
1885 return tv->vval.v_partial != NULL; | |
1886 case VAR_FUNC: | |
1887 case VAR_STRING: | |
1888 return tv->vval.v_string != NULL && *tv->vval.v_string != NUL; | |
1889 case VAR_LIST: | |
1890 return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0; | |
1891 case VAR_DICT: | |
1892 return tv->vval.v_dict != NULL | |
1893 && tv->vval.v_dict->dv_hashtab.ht_used > 0; | |
1894 case VAR_BOOL: | |
1895 case VAR_SPECIAL: | |
1896 return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE; | |
1897 case VAR_JOB: | |
1898 #ifdef FEAT_JOB_CHANNEL | |
1899 return tv->vval.v_job != NULL; | |
1900 #else | |
1901 break; | |
1902 #endif | |
1903 case VAR_CHANNEL: | |
1904 #ifdef FEAT_JOB_CHANNEL | |
1905 return tv->vval.v_channel != NULL; | |
1906 #else | |
1907 break; | |
1908 #endif | |
1909 case VAR_BLOB: | |
1910 return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0; | |
1911 case VAR_UNKNOWN: | |
1912 case VAR_VOID: | |
1913 break; | |
1914 } | |
1915 return FALSE; | |
1916 } | |
1917 | |
1918 /* | |
1919 * If "tv" is a string give an error and return FAIL. | |
1920 */ | |
1921 int | |
1922 check_not_string(typval_T *tv) | |
1923 { | |
1924 if (tv->v_type == VAR_STRING) | |
1925 { | |
1926 emsg(_("E1030: Using a String as a Number")); | |
1927 clear_tv(tv); | |
1928 return FAIL; | |
1929 } | |
1930 return OK; | |
1931 } | |
1932 | |
1933 | |
1934 #endif // FEAT_EVAL |