18a7d6542SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet: 28a7d6542SBram Moolenaar * 38a7d6542SBram Moolenaar * VIM - Vi IMproved by Bram Moolenaar 48a7d6542SBram Moolenaar * 58a7d6542SBram Moolenaar * Do ":help uganda" in Vim to read copying and usage conditions. 68a7d6542SBram Moolenaar * Do ":help credits" in Vim to see a list of people who contributed. 78a7d6542SBram Moolenaar * See README.txt for an overview of the Vim source code. 88a7d6542SBram Moolenaar */ 98a7d6542SBram Moolenaar 108a7d6542SBram Moolenaar /* 118a7d6542SBram Moolenaar * vim9execute.c: execute Vim9 script instructions 128a7d6542SBram Moolenaar */ 138a7d6542SBram Moolenaar 148a7d6542SBram Moolenaar #define USING_FLOAT_STUFF 158a7d6542SBram Moolenaar #include "vim.h" 168a7d6542SBram Moolenaar 178a7d6542SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO) 188a7d6542SBram Moolenaar 198a7d6542SBram Moolenaar #ifdef VMS 208a7d6542SBram Moolenaar # include <float.h> 218a7d6542SBram Moolenaar #endif 228a7d6542SBram Moolenaar 238a7d6542SBram Moolenaar #include "vim9.h" 248a7d6542SBram Moolenaar 258a7d6542SBram Moolenaar // Structure put on ec_trystack when ISN_TRY is encountered. 268a7d6542SBram Moolenaar typedef struct { 27bf67ea1aSBram Moolenaar int tcd_frame_idx; // ec_frame_idx when ISN_TRY was encountered 288a7d6542SBram Moolenaar int tcd_catch_idx; // instruction of the first catch 298a7d6542SBram Moolenaar int tcd_finally_idx; // instruction of the finally block 308a7d6542SBram Moolenaar int tcd_caught; // catch block entered 318a7d6542SBram Moolenaar int tcd_return; // when TRUE return from end of :finally 328a7d6542SBram Moolenaar } trycmd_T; 338a7d6542SBram Moolenaar 348a7d6542SBram Moolenaar 358a7d6542SBram Moolenaar // A stack is used to store: 368a7d6542SBram Moolenaar // - arguments passed to a :def function 378a7d6542SBram Moolenaar // - info about the calling function, to use when returning 388a7d6542SBram Moolenaar // - local variables 398a7d6542SBram Moolenaar // - temporary values 408a7d6542SBram Moolenaar // 418a7d6542SBram Moolenaar // In detail (FP == Frame Pointer): 428a7d6542SBram Moolenaar // arg1 first argument from caller (if present) 438a7d6542SBram Moolenaar // arg2 second argument from caller (if present) 448a7d6542SBram Moolenaar // extra_arg1 any missing optional argument default value 458a7d6542SBram Moolenaar // FP -> cur_func calling function 468a7d6542SBram Moolenaar // current previous instruction pointer 478a7d6542SBram Moolenaar // frame_ptr previous Frame Pointer 488a7d6542SBram Moolenaar // var1 space for local variable 498a7d6542SBram Moolenaar // var2 space for local variable 508a7d6542SBram Moolenaar // .... fixed space for max. number of local variables 518a7d6542SBram Moolenaar // temp temporary values 528a7d6542SBram Moolenaar // .... flexible space for temporary values (can grow big) 538a7d6542SBram Moolenaar 548a7d6542SBram Moolenaar /* 558a7d6542SBram Moolenaar * Execution context. 568a7d6542SBram Moolenaar */ 578a7d6542SBram Moolenaar typedef struct { 588a7d6542SBram Moolenaar garray_T ec_stack; // stack of typval_T values 59bf67ea1aSBram Moolenaar int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx 608a7d6542SBram Moolenaar 61c8cd2b34SBram Moolenaar garray_T *ec_outer_stack; // stack used for closures 62c8cd2b34SBram Moolenaar int ec_outer_frame; // stack frame in ec_outer_stack 63c8cd2b34SBram Moolenaar 648a7d6542SBram Moolenaar garray_T ec_trystack; // stack of trycmd_T values 658a7d6542SBram Moolenaar int ec_in_catch; // when TRUE in catch or finally block 668a7d6542SBram Moolenaar 678a7d6542SBram Moolenaar int ec_dfunc_idx; // current function index 688a7d6542SBram Moolenaar isn_T *ec_instr; // array with instructions 698a7d6542SBram Moolenaar int ec_iidx; // index in ec_instr: instruction to execute 70148ce7aeSBram Moolenaar 71148ce7aeSBram Moolenaar garray_T ec_funcrefs; // partials that might be a closure 728a7d6542SBram Moolenaar } ectx_T; 738a7d6542SBram Moolenaar 748a7d6542SBram Moolenaar // Get pointer to item relative to the bottom of the stack, -1 is the last one. 7511107babSBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx)) 768a7d6542SBram Moolenaar 77418f1df5SBram Moolenaar void 78418f1df5SBram Moolenaar to_string_error(vartype_T vartype) 79418f1df5SBram Moolenaar { 80451c2e35SBram Moolenaar semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype)); 81418f1df5SBram Moolenaar } 82418f1df5SBram Moolenaar 838a7d6542SBram Moolenaar /* 84170fcfcfSBram Moolenaar * Return the number of arguments, including optional arguments and any vararg. 858a7d6542SBram Moolenaar */ 868a7d6542SBram Moolenaar static int 878a7d6542SBram Moolenaar ufunc_argcount(ufunc_T *ufunc) 888a7d6542SBram Moolenaar { 898a7d6542SBram Moolenaar return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0); 908a7d6542SBram Moolenaar } 918a7d6542SBram Moolenaar 928a7d6542SBram Moolenaar /* 93170fcfcfSBram Moolenaar * Set the instruction index, depending on omitted arguments, where the default 94170fcfcfSBram Moolenaar * values are to be computed. If all optional arguments are present, start 95170fcfcfSBram Moolenaar * with the function body. 96170fcfcfSBram Moolenaar * The expression evaluation is at the start of the instructions: 97170fcfcfSBram Moolenaar * 0 -> EVAL default1 98170fcfcfSBram Moolenaar * STORE arg[-2] 99170fcfcfSBram Moolenaar * 1 -> EVAL default2 100170fcfcfSBram Moolenaar * STORE arg[-1] 101170fcfcfSBram Moolenaar * 2 -> function body 102170fcfcfSBram Moolenaar */ 103170fcfcfSBram Moolenaar static void 104170fcfcfSBram Moolenaar init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx) 105170fcfcfSBram Moolenaar { 106170fcfcfSBram Moolenaar if (ufunc->uf_def_args.ga_len == 0) 107170fcfcfSBram Moolenaar ectx->ec_iidx = 0; 108170fcfcfSBram Moolenaar else 109170fcfcfSBram Moolenaar { 110170fcfcfSBram Moolenaar int defcount = ufunc->uf_args.ga_len - argcount; 111170fcfcfSBram Moolenaar 112170fcfcfSBram Moolenaar // If there is a varargs argument defcount can be negative, no defaults 113170fcfcfSBram Moolenaar // to evaluate then. 114170fcfcfSBram Moolenaar if (defcount < 0) 115170fcfcfSBram Moolenaar defcount = 0; 116170fcfcfSBram Moolenaar ectx->ec_iidx = ufunc->uf_def_arg_idx[ 117170fcfcfSBram Moolenaar ufunc->uf_def_args.ga_len - defcount]; 118170fcfcfSBram Moolenaar } 119170fcfcfSBram Moolenaar } 120170fcfcfSBram Moolenaar 121170fcfcfSBram Moolenaar /* 122fe270817SBram Moolenaar * Create a new list from "count" items at the bottom of the stack. 123fe270817SBram Moolenaar * When "count" is zero an empty list is added to the stack. 124fe270817SBram Moolenaar */ 125fe270817SBram Moolenaar static int 126fe270817SBram Moolenaar exe_newlist(int count, ectx_T *ectx) 127fe270817SBram Moolenaar { 128fe270817SBram Moolenaar list_T *list = list_alloc_with_items(count); 129fe270817SBram Moolenaar int idx; 130fe270817SBram Moolenaar typval_T *tv; 131fe270817SBram Moolenaar 132fe270817SBram Moolenaar if (list == NULL) 133fe270817SBram Moolenaar return FAIL; 134fe270817SBram Moolenaar for (idx = 0; idx < count; ++idx) 135fe270817SBram Moolenaar list_set_item(list, idx, STACK_TV_BOT(idx - count)); 136fe270817SBram Moolenaar 137fe270817SBram Moolenaar if (count > 0) 138fe270817SBram Moolenaar ectx->ec_stack.ga_len -= count - 1; 139270d0388SBram Moolenaar else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) 140fe270817SBram Moolenaar return FAIL; 141fe270817SBram Moolenaar else 142fe270817SBram Moolenaar ++ectx->ec_stack.ga_len; 143fe270817SBram Moolenaar tv = STACK_TV_BOT(-1); 144fe270817SBram Moolenaar tv->v_type = VAR_LIST; 145fe270817SBram Moolenaar tv->vval.v_list = list; 146fe270817SBram Moolenaar ++list->lv_refcount; 147fe270817SBram Moolenaar return OK; 148fe270817SBram Moolenaar } 149fe270817SBram Moolenaar 150fe270817SBram Moolenaar /* 1518a7d6542SBram Moolenaar * Call compiled function "cdf_idx" from compiled code. 1528a7d6542SBram Moolenaar * 1538a7d6542SBram Moolenaar * Stack has: 1548a7d6542SBram Moolenaar * - current arguments (already there) 1558a7d6542SBram Moolenaar * - omitted optional argument (default values) added here 1568a7d6542SBram Moolenaar * - stack frame: 1578a7d6542SBram Moolenaar * - pointer to calling function 1588a7d6542SBram Moolenaar * - Index of next instruction in calling function 1598a7d6542SBram Moolenaar * - previous frame pointer 1608a7d6542SBram Moolenaar * - reserved space for local variables 1618a7d6542SBram Moolenaar */ 1628a7d6542SBram Moolenaar static int 1631378fbc4SBram Moolenaar call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx) 1648a7d6542SBram Moolenaar { 1651378fbc4SBram Moolenaar int argcount = argcount_arg; 1668a7d6542SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx; 1678a7d6542SBram Moolenaar ufunc_T *ufunc = dfunc->df_ufunc; 1681378fbc4SBram Moolenaar int arg_to_add; 1691378fbc4SBram Moolenaar int vararg_count = 0; 170148ce7aeSBram Moolenaar int varcount; 1718a7d6542SBram Moolenaar int idx; 172c620c055SBram Moolenaar estack_T *entry; 1738a7d6542SBram Moolenaar 1748a7d6542SBram Moolenaar if (dfunc->df_deleted) 1758a7d6542SBram Moolenaar { 1768a7d6542SBram Moolenaar emsg_funcname(e_func_deleted, ufunc->uf_name); 1778a7d6542SBram Moolenaar return FAIL; 1788a7d6542SBram Moolenaar } 1798a7d6542SBram Moolenaar 1801378fbc4SBram Moolenaar if (ufunc->uf_va_name != NULL) 1811378fbc4SBram Moolenaar { 182fe270817SBram Moolenaar // Need to make a list out of the vararg arguments. 1831378fbc4SBram Moolenaar // Stack at time of call with 2 varargs: 1841378fbc4SBram Moolenaar // normal_arg 1851378fbc4SBram Moolenaar // optional_arg 1861378fbc4SBram Moolenaar // vararg_1 1871378fbc4SBram Moolenaar // vararg_2 188fe270817SBram Moolenaar // After creating the list: 1891378fbc4SBram Moolenaar // normal_arg 1901378fbc4SBram Moolenaar // optional_arg 191fe270817SBram Moolenaar // vararg-list 192fe270817SBram Moolenaar // With missing optional arguments we get: 193fe270817SBram Moolenaar // normal_arg 194fe270817SBram Moolenaar // After creating the list 195fe270817SBram Moolenaar // normal_arg 196fe270817SBram Moolenaar // (space for optional_arg) 197fe270817SBram Moolenaar // vararg-list 1981378fbc4SBram Moolenaar vararg_count = argcount - ufunc->uf_args.ga_len; 1991378fbc4SBram Moolenaar if (vararg_count < 0) 2001378fbc4SBram Moolenaar vararg_count = 0; 2011378fbc4SBram Moolenaar else 2021378fbc4SBram Moolenaar argcount -= vararg_count; 203fe270817SBram Moolenaar if (exe_newlist(vararg_count, ectx) == FAIL) 2041378fbc4SBram Moolenaar return FAIL; 205fe270817SBram Moolenaar 206fe270817SBram Moolenaar vararg_count = 1; 2071378fbc4SBram Moolenaar } 2081378fbc4SBram Moolenaar 209fe270817SBram Moolenaar arg_to_add = ufunc->uf_args.ga_len - argcount; 2101378fbc4SBram Moolenaar if (arg_to_add < 0) 2111378fbc4SBram Moolenaar { 21279e8db9aSBram Moolenaar if (arg_to_add == -1) 213451c2e35SBram Moolenaar emsg(_(e_one_argument_too_many)); 21479e8db9aSBram Moolenaar else 215451c2e35SBram Moolenaar semsg(_(e_nr_arguments_too_many), -arg_to_add); 2161378fbc4SBram Moolenaar return FAIL; 2171378fbc4SBram Moolenaar } 218148ce7aeSBram Moolenaar 219148ce7aeSBram Moolenaar // Reserve space for: 220148ce7aeSBram Moolenaar // - missing arguments 221148ce7aeSBram Moolenaar // - stack frame 222148ce7aeSBram Moolenaar // - local variables 223148ce7aeSBram Moolenaar // - if needed: a counter for number of closures created in 224148ce7aeSBram Moolenaar // ectx->ec_funcrefs. 225148ce7aeSBram Moolenaar varcount = dfunc->df_varcount + dfunc->df_has_closure; 226148ce7aeSBram Moolenaar if (ga_grow(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE + varcount) 227148ce7aeSBram Moolenaar == FAIL) 2288a7d6542SBram Moolenaar return FAIL; 2298a7d6542SBram Moolenaar 230fe270817SBram Moolenaar // Move the vararg-list to below the missing optional arguments. 231fe270817SBram Moolenaar if (vararg_count > 0 && arg_to_add > 0) 232fe270817SBram Moolenaar *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1); 233170fcfcfSBram Moolenaar 234170fcfcfSBram Moolenaar // Reserve space for omitted optional arguments, filled in soon. 2351378fbc4SBram Moolenaar for (idx = 0; idx < arg_to_add; ++idx) 236fe270817SBram Moolenaar STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN; 2371378fbc4SBram Moolenaar ectx->ec_stack.ga_len += arg_to_add; 2388a7d6542SBram Moolenaar 2398a7d6542SBram Moolenaar // Store current execution state in stack frame for ISN_RETURN. 2408a7d6542SBram Moolenaar STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx; 2418a7d6542SBram Moolenaar STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx; 2425366e1aeSBram Moolenaar STACK_TV_BOT(2)->vval.v_string = (void *)ectx->ec_outer_stack; 2435366e1aeSBram Moolenaar STACK_TV_BOT(3)->vval.v_number = ectx->ec_outer_frame; 2445366e1aeSBram Moolenaar STACK_TV_BOT(4)->vval.v_number = ectx->ec_frame_idx; 245bf67ea1aSBram Moolenaar ectx->ec_frame_idx = ectx->ec_stack.ga_len; 2468a7d6542SBram Moolenaar 2478a7d6542SBram Moolenaar // Initialize local variables 248148ce7aeSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 2498a7d6542SBram Moolenaar STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN; 250148ce7aeSBram Moolenaar if (dfunc->df_has_closure) 251148ce7aeSBram Moolenaar { 252148ce7aeSBram Moolenaar typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + dfunc->df_varcount); 253148ce7aeSBram Moolenaar 254148ce7aeSBram Moolenaar tv->v_type = VAR_NUMBER; 255148ce7aeSBram Moolenaar tv->vval.v_number = 0; 256148ce7aeSBram Moolenaar } 257148ce7aeSBram Moolenaar ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount; 2588a7d6542SBram Moolenaar 2598a7d6542SBram Moolenaar // Set execution state to the start of the called function. 2608a7d6542SBram Moolenaar ectx->ec_dfunc_idx = cdf_idx; 2618a7d6542SBram Moolenaar ectx->ec_instr = dfunc->df_instr; 262c620c055SBram Moolenaar entry = estack_push_ufunc(dfunc->df_ufunc, 1); 263c620c055SBram Moolenaar if (entry != NULL) 264c620c055SBram Moolenaar { 265c620c055SBram Moolenaar // Set the script context to the script where the function was defined. 266c620c055SBram Moolenaar // TODO: save more than the SID? 267c620c055SBram Moolenaar entry->es_save_sid = current_sctx.sc_sid; 268c620c055SBram Moolenaar current_sctx.sc_sid = ufunc->uf_script_ctx.sc_sid; 269c620c055SBram Moolenaar } 270170fcfcfSBram Moolenaar 271170fcfcfSBram Moolenaar // Decide where to start execution, handles optional arguments. 272170fcfcfSBram Moolenaar init_instr_idx(ufunc, argcount, ectx); 2738a7d6542SBram Moolenaar 2748a7d6542SBram Moolenaar return OK; 2758a7d6542SBram Moolenaar } 2768a7d6542SBram Moolenaar 2778a7d6542SBram Moolenaar // Get pointer to item in the stack. 2788a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx) 2798a7d6542SBram Moolenaar 2808a7d6542SBram Moolenaar /* 281bf67ea1aSBram Moolenaar * Used when returning from a function: Check if any closure is still 282bf67ea1aSBram Moolenaar * referenced. If so then move the arguments and variables to a separate piece 283bf67ea1aSBram Moolenaar * of stack to be used when the closure is called. 284bf67ea1aSBram Moolenaar * When "free_arguments" is TRUE the arguments are to be freed. 285bf67ea1aSBram Moolenaar * Returns FAIL when out of memory. 286bf67ea1aSBram Moolenaar */ 287bf67ea1aSBram Moolenaar static int 288bf67ea1aSBram Moolenaar handle_closure_in_use(ectx_T *ectx, int free_arguments) 289bf67ea1aSBram Moolenaar { 290bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 291bf67ea1aSBram Moolenaar + ectx->ec_dfunc_idx; 292fdeab65dSBram Moolenaar int argcount; 293fdeab65dSBram Moolenaar int top; 294bf67ea1aSBram Moolenaar int idx; 295bf67ea1aSBram Moolenaar typval_T *tv; 296bf67ea1aSBram Moolenaar int closure_in_use = FALSE; 297148ce7aeSBram Moolenaar garray_T *gap = &ectx->ec_funcrefs; 298148ce7aeSBram Moolenaar varnumber_T closure_count; 299bf67ea1aSBram Moolenaar 300fdeab65dSBram Moolenaar if (dfunc->df_ufunc == NULL) 301148ce7aeSBram Moolenaar return OK; // function was freed 302148ce7aeSBram Moolenaar if (dfunc->df_has_closure == 0) 303148ce7aeSBram Moolenaar return OK; // no closures 304148ce7aeSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + dfunc->df_varcount); 305148ce7aeSBram Moolenaar closure_count = tv->vval.v_number; 306148ce7aeSBram Moolenaar if (closure_count == 0) 307148ce7aeSBram Moolenaar return OK; // no funcrefs created 308148ce7aeSBram Moolenaar 309fdeab65dSBram Moolenaar argcount = ufunc_argcount(dfunc->df_ufunc); 310fdeab65dSBram Moolenaar top = ectx->ec_frame_idx - argcount; 311fdeab65dSBram Moolenaar 312bf67ea1aSBram Moolenaar // Check if any created closure is still in use. 313148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 314bf67ea1aSBram Moolenaar { 315c70bdab0SBram Moolenaar partial_T *pt; 316c70bdab0SBram Moolenaar int off = gap->ga_len - closure_count + idx; 317148ce7aeSBram Moolenaar 318c70bdab0SBram Moolenaar if (off < 0) 319c70bdab0SBram Moolenaar continue; // count is off or already done 320c70bdab0SBram Moolenaar pt = ((partial_T **)gap->ga_data)[off]; 321148ce7aeSBram Moolenaar if (pt->pt_refcount > 1) 322221fcc74SBram Moolenaar { 323148ce7aeSBram Moolenaar int refcount = pt->pt_refcount; 324221fcc74SBram Moolenaar int i; 325221fcc74SBram Moolenaar 326f821ddaaSBram Moolenaar // A Reference in a local variables doesn't count, it gets 327221fcc74SBram Moolenaar // unreferenced on return. 328221fcc74SBram Moolenaar for (i = 0; i < dfunc->df_varcount; ++i) 329221fcc74SBram Moolenaar { 330221fcc74SBram Moolenaar typval_T *stv = STACK_TV(ectx->ec_frame_idx 331221fcc74SBram Moolenaar + STACK_FRAME_SIZE + i); 332148ce7aeSBram Moolenaar if (stv->v_type == VAR_PARTIAL && pt == stv->vval.v_partial) 333221fcc74SBram Moolenaar --refcount; 334221fcc74SBram Moolenaar } 335221fcc74SBram Moolenaar if (refcount > 1) 336f7779c63SBram Moolenaar { 337bf67ea1aSBram Moolenaar closure_in_use = TRUE; 338f7779c63SBram Moolenaar break; 339f7779c63SBram Moolenaar } 340bf67ea1aSBram Moolenaar } 341221fcc74SBram Moolenaar } 342bf67ea1aSBram Moolenaar 343bf67ea1aSBram Moolenaar if (closure_in_use) 344bf67ea1aSBram Moolenaar { 345bf67ea1aSBram Moolenaar funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T); 346bf67ea1aSBram Moolenaar typval_T *stack; 347bf67ea1aSBram Moolenaar 348bf67ea1aSBram Moolenaar // A closure is using the arguments and/or local variables. 349bf67ea1aSBram Moolenaar // Move them to the called function. 350bf67ea1aSBram Moolenaar if (funcstack == NULL) 351bf67ea1aSBram Moolenaar return FAIL; 35285d5e2b7SBram Moolenaar funcstack->fs_var_offset = argcount + STACK_FRAME_SIZE; 35385d5e2b7SBram Moolenaar funcstack->fs_ga.ga_len = funcstack->fs_var_offset + dfunc->df_varcount; 354bf67ea1aSBram Moolenaar stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len); 355bf67ea1aSBram Moolenaar funcstack->fs_ga.ga_data = stack; 356bf67ea1aSBram Moolenaar if (stack == NULL) 357bf67ea1aSBram Moolenaar { 358bf67ea1aSBram Moolenaar vim_free(funcstack); 359bf67ea1aSBram Moolenaar return FAIL; 360bf67ea1aSBram Moolenaar } 361bf67ea1aSBram Moolenaar 362bf67ea1aSBram Moolenaar // Move or copy the arguments. 363bf67ea1aSBram Moolenaar for (idx = 0; idx < argcount; ++idx) 364bf67ea1aSBram Moolenaar { 365bf67ea1aSBram Moolenaar tv = STACK_TV(top + idx); 366bf67ea1aSBram Moolenaar if (free_arguments) 367bf67ea1aSBram Moolenaar { 368bf67ea1aSBram Moolenaar *(stack + idx) = *tv; 369bf67ea1aSBram Moolenaar tv->v_type = VAR_UNKNOWN; 370bf67ea1aSBram Moolenaar } 371bf67ea1aSBram Moolenaar else 372bf67ea1aSBram Moolenaar copy_tv(tv, stack + idx); 373bf67ea1aSBram Moolenaar } 374bf67ea1aSBram Moolenaar // Move the local variables. 375bf67ea1aSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 376bf67ea1aSBram Moolenaar { 377bf67ea1aSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx); 378f821ddaaSBram Moolenaar 37985d5e2b7SBram Moolenaar // A partial created for a local function, that is also used as a 38085d5e2b7SBram Moolenaar // local variable, has a reference count for the variable, thus 38185d5e2b7SBram Moolenaar // will never go down to zero. When all these refcounts are one 38285d5e2b7SBram Moolenaar // then the funcstack is unused. We need to count how many we have 38385d5e2b7SBram Moolenaar // so we need when to check. 384f821ddaaSBram Moolenaar if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) 385f821ddaaSBram Moolenaar { 386f821ddaaSBram Moolenaar int i; 387f821ddaaSBram Moolenaar 388148ce7aeSBram Moolenaar for (i = 0; i < closure_count; ++i) 38985d5e2b7SBram Moolenaar if (tv->vval.v_partial == ((partial_T **)gap->ga_data)[ 39085d5e2b7SBram Moolenaar gap->ga_len - closure_count + i]) 39185d5e2b7SBram Moolenaar ++funcstack->fs_min_refcount; 392f821ddaaSBram Moolenaar } 393f821ddaaSBram Moolenaar 39485d5e2b7SBram Moolenaar *(stack + funcstack->fs_var_offset + idx) = *tv; 395bf67ea1aSBram Moolenaar tv->v_type = VAR_UNKNOWN; 396bf67ea1aSBram Moolenaar } 397bf67ea1aSBram Moolenaar 398148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 399bf67ea1aSBram Moolenaar { 400148ce7aeSBram Moolenaar partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len 401148ce7aeSBram Moolenaar - closure_count + idx]; 402148ce7aeSBram Moolenaar if (pt->pt_refcount > 1) 403f7779c63SBram Moolenaar { 404bf67ea1aSBram Moolenaar ++funcstack->fs_refcount; 405148ce7aeSBram Moolenaar pt->pt_funcstack = funcstack; 406148ce7aeSBram Moolenaar pt->pt_ectx_stack = &funcstack->fs_ga; 407148ce7aeSBram Moolenaar pt->pt_ectx_frame = ectx->ec_frame_idx - top; 408f7779c63SBram Moolenaar } 409bf67ea1aSBram Moolenaar } 410bf67ea1aSBram Moolenaar } 411148ce7aeSBram Moolenaar 412148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 413148ce7aeSBram Moolenaar partial_unref(((partial_T **)gap->ga_data)[gap->ga_len 414148ce7aeSBram Moolenaar - closure_count + idx]); 415148ce7aeSBram Moolenaar gap->ga_len -= closure_count; 416148ce7aeSBram Moolenaar if (gap->ga_len == 0) 417148ce7aeSBram Moolenaar ga_clear(gap); 418bf67ea1aSBram Moolenaar 419bf67ea1aSBram Moolenaar return OK; 420bf67ea1aSBram Moolenaar } 421bf67ea1aSBram Moolenaar 422bf67ea1aSBram Moolenaar /* 42385d5e2b7SBram Moolenaar * Called when a partial is freed or its reference count goes down to one. The 42485d5e2b7SBram Moolenaar * funcstack may be the only reference to the partials in the local variables. 42585d5e2b7SBram Moolenaar * Go over all of them, the funcref and can be freed if all partials 42685d5e2b7SBram Moolenaar * referencing the funcstack have a reference count of one. 42785d5e2b7SBram Moolenaar */ 42885d5e2b7SBram Moolenaar void 42985d5e2b7SBram Moolenaar funcstack_check_refcount(funcstack_T *funcstack) 43085d5e2b7SBram Moolenaar { 43185d5e2b7SBram Moolenaar int i; 43285d5e2b7SBram Moolenaar garray_T *gap = &funcstack->fs_ga; 43385d5e2b7SBram Moolenaar int done = 0; 43485d5e2b7SBram Moolenaar 43585d5e2b7SBram Moolenaar if (funcstack->fs_refcount > funcstack->fs_min_refcount) 43685d5e2b7SBram Moolenaar return; 43785d5e2b7SBram Moolenaar for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i) 43885d5e2b7SBram Moolenaar { 43985d5e2b7SBram Moolenaar typval_T *tv = ((typval_T *)gap->ga_data) + i; 44085d5e2b7SBram Moolenaar 44185d5e2b7SBram Moolenaar if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL 44285d5e2b7SBram Moolenaar && tv->vval.v_partial->pt_funcstack == funcstack 44385d5e2b7SBram Moolenaar && tv->vval.v_partial->pt_refcount == 1) 44485d5e2b7SBram Moolenaar ++done; 44585d5e2b7SBram Moolenaar } 44685d5e2b7SBram Moolenaar if (done == funcstack->fs_min_refcount) 44785d5e2b7SBram Moolenaar { 44885d5e2b7SBram Moolenaar typval_T *stack = gap->ga_data; 44985d5e2b7SBram Moolenaar 45085d5e2b7SBram Moolenaar // All partials referencing the funcstack have a reference count of 45185d5e2b7SBram Moolenaar // one, thus the funcstack is no longer of use. 45285d5e2b7SBram Moolenaar for (i = 0; i < gap->ga_len; ++i) 45385d5e2b7SBram Moolenaar clear_tv(stack + i); 45485d5e2b7SBram Moolenaar vim_free(stack); 45585d5e2b7SBram Moolenaar vim_free(funcstack); 45685d5e2b7SBram Moolenaar } 45785d5e2b7SBram Moolenaar } 45885d5e2b7SBram Moolenaar 45985d5e2b7SBram Moolenaar /* 4608a7d6542SBram Moolenaar * Return from the current function. 4618a7d6542SBram Moolenaar */ 462bf67ea1aSBram Moolenaar static int 4638a7d6542SBram Moolenaar func_return(ectx_T *ectx) 4648a7d6542SBram Moolenaar { 4658a7d6542SBram Moolenaar int idx; 466bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 467bf67ea1aSBram Moolenaar + ectx->ec_dfunc_idx; 468bf67ea1aSBram Moolenaar int argcount = ufunc_argcount(dfunc->df_ufunc); 469bf67ea1aSBram Moolenaar int top = ectx->ec_frame_idx - argcount; 470c620c055SBram Moolenaar estack_T *entry; 4718a7d6542SBram Moolenaar 4728a7d6542SBram Moolenaar // execution context goes one level up 473c620c055SBram Moolenaar entry = estack_pop(); 474c620c055SBram Moolenaar if (entry != NULL) 475c620c055SBram Moolenaar current_sctx.sc_sid = entry->es_save_sid; 4768a7d6542SBram Moolenaar 477bf67ea1aSBram Moolenaar if (handle_closure_in_use(ectx, TRUE) == FAIL) 478bf67ea1aSBram Moolenaar return FAIL; 479bf67ea1aSBram Moolenaar 480bf67ea1aSBram Moolenaar // Clear the arguments. 481bf67ea1aSBram Moolenaar for (idx = top; idx < ectx->ec_frame_idx; ++idx) 482bf67ea1aSBram Moolenaar clear_tv(STACK_TV(idx)); 483bf67ea1aSBram Moolenaar 484bf67ea1aSBram Moolenaar // Clear local variables and temp values, but not the return value. 485bf67ea1aSBram Moolenaar for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE; 4868a7d6542SBram Moolenaar idx < ectx->ec_stack.ga_len - 1; ++idx) 4878a7d6542SBram Moolenaar clear_tv(STACK_TV(idx)); 488170fcfcfSBram Moolenaar 489170fcfcfSBram Moolenaar // Restore the previous frame. 490bf67ea1aSBram Moolenaar ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame_idx)->vval.v_number; 491bf67ea1aSBram Moolenaar ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx + 1)->vval.v_number; 4925366e1aeSBram Moolenaar ectx->ec_outer_stack = 4935366e1aeSBram Moolenaar (void *)STACK_TV(ectx->ec_frame_idx + 2)->vval.v_string; 4945366e1aeSBram Moolenaar ectx->ec_outer_frame = STACK_TV(ectx->ec_frame_idx + 3)->vval.v_number; 4955366e1aeSBram Moolenaar // restoring ec_frame_idx must be last 4965366e1aeSBram Moolenaar ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx + 4)->vval.v_number; 4978a7d6542SBram Moolenaar dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; 4988a7d6542SBram Moolenaar ectx->ec_instr = dfunc->df_instr; 499170fcfcfSBram Moolenaar 500170fcfcfSBram Moolenaar // Reset the stack to the position before the call, move the return value 501170fcfcfSBram Moolenaar // to the top of the stack. 502170fcfcfSBram Moolenaar idx = ectx->ec_stack.ga_len - 1; 503170fcfcfSBram Moolenaar ectx->ec_stack.ga_len = top + 1; 504170fcfcfSBram Moolenaar *STACK_TV_BOT(-1) = *STACK_TV(idx); 505bf67ea1aSBram Moolenaar 506bf67ea1aSBram Moolenaar return OK; 5078a7d6542SBram Moolenaar } 5088a7d6542SBram Moolenaar 5098a7d6542SBram Moolenaar #undef STACK_TV 5108a7d6542SBram Moolenaar 5118a7d6542SBram Moolenaar /* 5128a7d6542SBram Moolenaar * Prepare arguments and rettv for calling a builtin or user function. 5138a7d6542SBram Moolenaar */ 5148a7d6542SBram Moolenaar static int 5158a7d6542SBram Moolenaar call_prepare(int argcount, typval_T *argvars, ectx_T *ectx) 5168a7d6542SBram Moolenaar { 5178a7d6542SBram Moolenaar int idx; 5188a7d6542SBram Moolenaar typval_T *tv; 5198a7d6542SBram Moolenaar 5208a7d6542SBram Moolenaar // Move arguments from bottom of the stack to argvars[] and add terminator. 5218a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 5228a7d6542SBram Moolenaar argvars[idx] = *STACK_TV_BOT(idx - argcount); 5238a7d6542SBram Moolenaar argvars[argcount].v_type = VAR_UNKNOWN; 5248a7d6542SBram Moolenaar 5258a7d6542SBram Moolenaar // Result replaces the arguments on the stack. 5268a7d6542SBram Moolenaar if (argcount > 0) 5278a7d6542SBram Moolenaar ectx->ec_stack.ga_len -= argcount - 1; 528270d0388SBram Moolenaar else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) 5298a7d6542SBram Moolenaar return FAIL; 5308a7d6542SBram Moolenaar else 5318a7d6542SBram Moolenaar ++ectx->ec_stack.ga_len; 5328a7d6542SBram Moolenaar 5338a7d6542SBram Moolenaar // Default return value is zero. 5348a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 5358a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 5368a7d6542SBram Moolenaar tv->vval.v_number = 0; 5378a7d6542SBram Moolenaar 5388a7d6542SBram Moolenaar return OK; 5398a7d6542SBram Moolenaar } 5408a7d6542SBram Moolenaar 54108f7a41bSBram Moolenaar // Ugly global to avoid passing the execution context around through many 54208f7a41bSBram Moolenaar // layers. 54308f7a41bSBram Moolenaar static ectx_T *current_ectx = NULL; 54408f7a41bSBram Moolenaar 5458a7d6542SBram Moolenaar /* 5468a7d6542SBram Moolenaar * Call a builtin function by index. 5478a7d6542SBram Moolenaar */ 5488a7d6542SBram Moolenaar static int 5498a7d6542SBram Moolenaar call_bfunc(int func_idx, int argcount, ectx_T *ectx) 5508a7d6542SBram Moolenaar { 5518a7d6542SBram Moolenaar typval_T argvars[MAX_FUNC_ARGS]; 5528a7d6542SBram Moolenaar int idx; 5538a1c1013SBram Moolenaar int did_emsg_before = did_emsg; 55408f7a41bSBram Moolenaar ectx_T *prev_ectx = current_ectx; 5558a7d6542SBram Moolenaar 5568a7d6542SBram Moolenaar if (call_prepare(argcount, argvars, ectx) == FAIL) 5578a7d6542SBram Moolenaar return FAIL; 5588a7d6542SBram Moolenaar 55908f7a41bSBram Moolenaar // Call the builtin function. Set "current_ectx" so that when it 56008f7a41bSBram Moolenaar // recursively invokes call_def_function() a closure context can be set. 56108f7a41bSBram Moolenaar current_ectx = ectx; 5628a7d6542SBram Moolenaar call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1)); 56308f7a41bSBram Moolenaar current_ectx = prev_ectx; 5648a7d6542SBram Moolenaar 5658a7d6542SBram Moolenaar // Clear the arguments. 5668a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 5678a7d6542SBram Moolenaar clear_tv(&argvars[idx]); 568015f4267SBram Moolenaar 5698a1c1013SBram Moolenaar if (did_emsg != did_emsg_before) 570015f4267SBram Moolenaar return FAIL; 5718a7d6542SBram Moolenaar return OK; 5728a7d6542SBram Moolenaar } 5738a7d6542SBram Moolenaar 5748a7d6542SBram Moolenaar /* 5758a7d6542SBram Moolenaar * Execute a user defined function. 5767eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 5778a7d6542SBram Moolenaar */ 5788a7d6542SBram Moolenaar static int 5797eeefd4aSBram Moolenaar call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr) 5808a7d6542SBram Moolenaar { 5818a7d6542SBram Moolenaar typval_T argvars[MAX_FUNC_ARGS]; 5828a7d6542SBram Moolenaar funcexe_T funcexe; 5838a7d6542SBram Moolenaar int error; 5848a7d6542SBram Moolenaar int idx; 585ed677f55SBram Moolenaar int called_emsg_before = called_emsg; 5868a7d6542SBram Moolenaar 5870cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_TO_BE_COMPILED 588822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL) 589822ba247SBram Moolenaar return FAIL; 5900cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_COMPILED) 5917eeefd4aSBram Moolenaar { 5927eeefd4aSBram Moolenaar // The function has been compiled, can call it quickly. For a function 5937eeefd4aSBram Moolenaar // that was defined later: we can call it directly next time. 5947eeefd4aSBram Moolenaar if (iptr != NULL) 5957eeefd4aSBram Moolenaar { 59620431c9dSBram Moolenaar delete_instr(iptr); 5977eeefd4aSBram Moolenaar iptr->isn_type = ISN_DCALL; 5987eeefd4aSBram Moolenaar iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx; 5997eeefd4aSBram Moolenaar iptr->isn_arg.dfunc.cdf_argcount = argcount; 6007eeefd4aSBram Moolenaar } 6018a7d6542SBram Moolenaar return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx); 6027eeefd4aSBram Moolenaar } 6038a7d6542SBram Moolenaar 6048a7d6542SBram Moolenaar if (call_prepare(argcount, argvars, ectx) == FAIL) 6058a7d6542SBram Moolenaar return FAIL; 606a80faa89SBram Moolenaar CLEAR_FIELD(funcexe); 6078a7d6542SBram Moolenaar funcexe.evaluate = TRUE; 6088a7d6542SBram Moolenaar 6098a7d6542SBram Moolenaar // Call the user function. Result goes in last position on the stack. 6108a7d6542SBram Moolenaar // TODO: add selfdict if there is one 6118a7d6542SBram Moolenaar error = call_user_func_check(ufunc, argcount, argvars, 6128a7d6542SBram Moolenaar STACK_TV_BOT(-1), &funcexe, NULL); 6138a7d6542SBram Moolenaar 6148a7d6542SBram Moolenaar // Clear the arguments. 6158a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 6168a7d6542SBram Moolenaar clear_tv(&argvars[idx]); 6178a7d6542SBram Moolenaar 6188a7d6542SBram Moolenaar if (error != FCERR_NONE) 6198a7d6542SBram Moolenaar { 6208a7d6542SBram Moolenaar user_func_error(error, ufunc->uf_name); 6218a7d6542SBram Moolenaar return FAIL; 6228a7d6542SBram Moolenaar } 623ed677f55SBram Moolenaar if (called_emsg > called_emsg_before) 624ed677f55SBram Moolenaar // Error other than from calling the function itself. 625ed677f55SBram Moolenaar return FAIL; 6268a7d6542SBram Moolenaar return OK; 6278a7d6542SBram Moolenaar } 6288a7d6542SBram Moolenaar 6298a7d6542SBram Moolenaar /* 630a177344dSBram Moolenaar * Return TRUE if an error was given or CTRL-C was pressed. 631a177344dSBram Moolenaar */ 632a177344dSBram Moolenaar static int 633a177344dSBram Moolenaar vim9_aborting(int prev_called_emsg) 634a177344dSBram Moolenaar { 635a177344dSBram Moolenaar return called_emsg > prev_called_emsg || got_int || did_throw; 636a177344dSBram Moolenaar } 637a177344dSBram Moolenaar 638a177344dSBram Moolenaar /* 6398a7d6542SBram Moolenaar * Execute a function by "name". 6408a7d6542SBram Moolenaar * This can be a builtin function or a user function. 6417eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 6428a7d6542SBram Moolenaar * Returns FAIL if not found without an error message. 6438a7d6542SBram Moolenaar */ 6448a7d6542SBram Moolenaar static int 6457eeefd4aSBram Moolenaar call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) 6468a7d6542SBram Moolenaar { 6478a7d6542SBram Moolenaar ufunc_T *ufunc; 6488a7d6542SBram Moolenaar 6498a7d6542SBram Moolenaar if (builtin_function(name, -1)) 6508a7d6542SBram Moolenaar { 6518a7d6542SBram Moolenaar int func_idx = find_internal_func(name); 6528a7d6542SBram Moolenaar 6538a7d6542SBram Moolenaar if (func_idx < 0) 6548a7d6542SBram Moolenaar return FAIL; 655389df259SBram Moolenaar if (check_internal_func(func_idx, argcount) < 0) 6568a7d6542SBram Moolenaar return FAIL; 6578a7d6542SBram Moolenaar return call_bfunc(func_idx, argcount, ectx); 6588a7d6542SBram Moolenaar } 6598a7d6542SBram Moolenaar 6604c17ad94SBram Moolenaar ufunc = find_func(name, FALSE, NULL); 661a177344dSBram Moolenaar 662a177344dSBram Moolenaar if (ufunc == NULL) 663a177344dSBram Moolenaar { 664a177344dSBram Moolenaar int called_emsg_before = called_emsg; 665a177344dSBram Moolenaar 666a177344dSBram Moolenaar if (script_autoload(name, TRUE)) 667a177344dSBram Moolenaar // loaded a package, search for the function again 668a177344dSBram Moolenaar ufunc = find_func(name, FALSE, NULL); 669a177344dSBram Moolenaar if (vim9_aborting(called_emsg_before)) 670a177344dSBram Moolenaar return FAIL; // bail out if loading the script caused an error 671a177344dSBram Moolenaar } 672a177344dSBram Moolenaar 6738a7d6542SBram Moolenaar if (ufunc != NULL) 6747eeefd4aSBram Moolenaar return call_ufunc(ufunc, argcount, ectx, iptr); 6758a7d6542SBram Moolenaar 6768a7d6542SBram Moolenaar return FAIL; 6778a7d6542SBram Moolenaar } 6788a7d6542SBram Moolenaar 6798a7d6542SBram Moolenaar static int 680a90afb9aSBram Moolenaar call_partial(typval_T *tv, int argcount_arg, ectx_T *ectx) 6818a7d6542SBram Moolenaar { 682a90afb9aSBram Moolenaar int argcount = argcount_arg; 683bd5da371SBram Moolenaar char_u *name = NULL; 6848a7d6542SBram Moolenaar int called_emsg_before = called_emsg; 68595006e3dSBram Moolenaar int res; 6868a7d6542SBram Moolenaar 6878a7d6542SBram Moolenaar if (tv->v_type == VAR_PARTIAL) 6888a7d6542SBram Moolenaar { 6898a7d6542SBram Moolenaar partial_T *pt = tv->vval.v_partial; 690a90afb9aSBram Moolenaar int i; 691a90afb9aSBram Moolenaar 692a90afb9aSBram Moolenaar if (pt->pt_argc > 0) 693a90afb9aSBram Moolenaar { 694a90afb9aSBram Moolenaar // Make space for arguments from the partial, shift the "argcount" 695a90afb9aSBram Moolenaar // arguments up. 696a90afb9aSBram Moolenaar if (ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL) 697a90afb9aSBram Moolenaar return FAIL; 698a90afb9aSBram Moolenaar for (i = 1; i <= argcount; ++i) 699a90afb9aSBram Moolenaar *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i); 700a90afb9aSBram Moolenaar ectx->ec_stack.ga_len += pt->pt_argc; 701a90afb9aSBram Moolenaar argcount += pt->pt_argc; 702a90afb9aSBram Moolenaar 703a90afb9aSBram Moolenaar // copy the arguments from the partial onto the stack 704a90afb9aSBram Moolenaar for (i = 0; i < pt->pt_argc; ++i) 705a90afb9aSBram Moolenaar copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i)); 706a90afb9aSBram Moolenaar } 7078a7d6542SBram Moolenaar 7088a7d6542SBram Moolenaar if (pt->pt_func != NULL) 709f7779c63SBram Moolenaar { 710f7779c63SBram Moolenaar int ret = call_ufunc(pt->pt_func, argcount, ectx, NULL); 711f7779c63SBram Moolenaar 712f7779c63SBram Moolenaar // closure may need the function context where it was defined 713f7779c63SBram Moolenaar ectx->ec_outer_stack = pt->pt_ectx_stack; 714f7779c63SBram Moolenaar ectx->ec_outer_frame = pt->pt_ectx_frame; 715f7779c63SBram Moolenaar 716f7779c63SBram Moolenaar return ret; 717f7779c63SBram Moolenaar } 7188a7d6542SBram Moolenaar name = pt->pt_name; 7198a7d6542SBram Moolenaar } 720bd5da371SBram Moolenaar else if (tv->v_type == VAR_FUNC) 7218a7d6542SBram Moolenaar name = tv->vval.v_string; 72295006e3dSBram Moolenaar if (name != NULL) 72395006e3dSBram Moolenaar { 72495006e3dSBram Moolenaar char_u fname_buf[FLEN_FIXED + 1]; 72595006e3dSBram Moolenaar char_u *tofree = NULL; 72695006e3dSBram Moolenaar int error = FCERR_NONE; 72795006e3dSBram Moolenaar char_u *fname; 72895006e3dSBram Moolenaar 72995006e3dSBram Moolenaar // May need to translate <SNR>123_ to K_SNR. 73095006e3dSBram Moolenaar fname = fname_trans_sid(name, fname_buf, &tofree, &error); 73195006e3dSBram Moolenaar if (error != FCERR_NONE) 73295006e3dSBram Moolenaar res = FAIL; 73395006e3dSBram Moolenaar else 73495006e3dSBram Moolenaar res = call_by_name(fname, argcount, ectx, NULL); 73595006e3dSBram Moolenaar vim_free(tofree); 73695006e3dSBram Moolenaar } 73795006e3dSBram Moolenaar 73895006e3dSBram Moolenaar if (name == NULL || res == FAIL) 7398a7d6542SBram Moolenaar { 7408a7d6542SBram Moolenaar if (called_emsg == called_emsg_before) 741015f4267SBram Moolenaar semsg(_(e_unknownfunc), 742015f4267SBram Moolenaar name == NULL ? (char_u *)"[unknown]" : name); 7438a7d6542SBram Moolenaar return FAIL; 7448a7d6542SBram Moolenaar } 7458a7d6542SBram Moolenaar return OK; 7468a7d6542SBram Moolenaar } 7478a7d6542SBram Moolenaar 7488a7d6542SBram Moolenaar /* 7490b4c66c6SBram Moolenaar * Check if "lock" is VAR_LOCKED or VAR_FIXED. If so give an error and return 7500b4c66c6SBram Moolenaar * TRUE. 7510b4c66c6SBram Moolenaar */ 7520b4c66c6SBram Moolenaar static int 7530b4c66c6SBram Moolenaar error_if_locked(int lock, char *error) 7540b4c66c6SBram Moolenaar { 7550b4c66c6SBram Moolenaar if (lock & (VAR_LOCKED | VAR_FIXED)) 7560b4c66c6SBram Moolenaar { 7570b4c66c6SBram Moolenaar emsg(_(error)); 7580b4c66c6SBram Moolenaar return TRUE; 7590b4c66c6SBram Moolenaar } 7600b4c66c6SBram Moolenaar return FALSE; 7610b4c66c6SBram Moolenaar } 7620b4c66c6SBram Moolenaar 7630b4c66c6SBram Moolenaar /* 7640bbf722aSBram Moolenaar * Store "tv" in variable "name". 7650bbf722aSBram Moolenaar * This is for s: and g: variables. 7660bbf722aSBram Moolenaar */ 7670bbf722aSBram Moolenaar static void 7680bbf722aSBram Moolenaar store_var(char_u *name, typval_T *tv) 7690bbf722aSBram Moolenaar { 7700bbf722aSBram Moolenaar funccal_entry_T entry; 7710bbf722aSBram Moolenaar 7720bbf722aSBram Moolenaar save_funccal(&entry); 77330fd8204SBram Moolenaar set_var_const(name, NULL, tv, FALSE, ASSIGN_NO_DECL); 7740bbf722aSBram Moolenaar restore_funccal(); 7750bbf722aSBram Moolenaar } 7760bbf722aSBram Moolenaar 777d3aac291SBram Moolenaar 7780bbf722aSBram Moolenaar /* 7798a7d6542SBram Moolenaar * Execute a function by "name". 7808a7d6542SBram Moolenaar * This can be a builtin function, user function or a funcref. 7817eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 7828a7d6542SBram Moolenaar */ 7838a7d6542SBram Moolenaar static int 7847eeefd4aSBram Moolenaar call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) 7858a7d6542SBram Moolenaar { 7868a7d6542SBram Moolenaar int called_emsg_before = called_emsg; 787ed677f55SBram Moolenaar int res; 7888a7d6542SBram Moolenaar 789ed677f55SBram Moolenaar res = call_by_name(name, argcount, ectx, iptr); 790ed677f55SBram Moolenaar if (res == FAIL && called_emsg == called_emsg_before) 7918a7d6542SBram Moolenaar { 7921df8b3fbSBram Moolenaar dictitem_T *v; 7931df8b3fbSBram Moolenaar 7941df8b3fbSBram Moolenaar v = find_var(name, NULL, FALSE); 7951df8b3fbSBram Moolenaar if (v == NULL) 7961df8b3fbSBram Moolenaar { 7971df8b3fbSBram Moolenaar semsg(_(e_unknownfunc), name); 7988a7d6542SBram Moolenaar return FAIL; 7998a7d6542SBram Moolenaar } 8001df8b3fbSBram Moolenaar if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC) 8011df8b3fbSBram Moolenaar { 8021df8b3fbSBram Moolenaar semsg(_(e_unknownfunc), name); 8031df8b3fbSBram Moolenaar return FAIL; 8041df8b3fbSBram Moolenaar } 8051df8b3fbSBram Moolenaar return call_partial(&v->di_tv, argcount, ectx); 8061df8b3fbSBram Moolenaar } 807ed677f55SBram Moolenaar return res; 8088a7d6542SBram Moolenaar } 8098a7d6542SBram Moolenaar 8108a7d6542SBram Moolenaar /* 8118a7d6542SBram Moolenaar * Call a "def" function from old Vim script. 8128a7d6542SBram Moolenaar * Return OK or FAIL. 8138a7d6542SBram Moolenaar */ 8148a7d6542SBram Moolenaar int 8158a7d6542SBram Moolenaar call_def_function( 8168a7d6542SBram Moolenaar ufunc_T *ufunc, 81723e03252SBram Moolenaar int argc_arg, // nr of arguments 8188a7d6542SBram Moolenaar typval_T *argv, // arguments 8196f5b6dfbSBram Moolenaar partial_T *partial, // optional partial for context 8208a7d6542SBram Moolenaar typval_T *rettv) // return value 8218a7d6542SBram Moolenaar { 8228a7d6542SBram Moolenaar ectx_T ectx; // execution context 82323e03252SBram Moolenaar int argc = argc_arg; 824bf67ea1aSBram Moolenaar int initial_frame_idx; 8258a7d6542SBram Moolenaar typval_T *tv; 8268a7d6542SBram Moolenaar int idx; 8278a7d6542SBram Moolenaar int ret = FAIL; 828170fcfcfSBram Moolenaar int defcount = ufunc->uf_args.ga_len - argc; 829ee8580e5SBram Moolenaar sctx_T save_current_sctx = current_sctx; 830270d0388SBram Moolenaar int breakcheck_count = 0; 83125e0f586SBram Moolenaar int called_emsg_before = called_emsg; 83277e5dcc3SBram Moolenaar int save_suppress_errthrow = suppress_errthrow; 8338a7d6542SBram Moolenaar 8348a7d6542SBram Moolenaar // Get pointer to item in the stack. 8358a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) 8368a7d6542SBram Moolenaar 8378a7d6542SBram Moolenaar // Get pointer to item at the bottom of the stack, -1 is the bottom. 8388a7d6542SBram Moolenaar #undef STACK_TV_BOT 8398a7d6542SBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx) 8408a7d6542SBram Moolenaar 8411378fbc4SBram Moolenaar // Get pointer to a local variable on the stack. Negative for arguments. 842bf67ea1aSBram Moolenaar #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx) 8438a7d6542SBram Moolenaar 844c8cd2b34SBram Moolenaar // Like STACK_TV_VAR but use the outer scope 845c8cd2b34SBram Moolenaar #define STACK_OUT_TV_VAR(idx) (((typval_T *)ectx.ec_outer_stack->ga_data) + ectx.ec_outer_frame + STACK_FRAME_SIZE + idx) 846c8cd2b34SBram Moolenaar 8470cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_NOT_COMPILED 8480cb5bcf5SBram Moolenaar || (ufunc->uf_def_status == UF_TO_BE_COMPILED 849822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL)) 85025e0f586SBram Moolenaar { 85125e0f586SBram Moolenaar if (called_emsg == called_emsg_before) 852451c2e35SBram Moolenaar semsg(_(e_function_is_not_compiled_str), 853682d0a15SBram Moolenaar printable_func_name(ufunc)); 854822ba247SBram Moolenaar return FAIL; 85525e0f586SBram Moolenaar } 856822ba247SBram Moolenaar 85709689a02SBram Moolenaar { 858822ba247SBram Moolenaar // Check the function was really compiled. 85909689a02SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 86009689a02SBram Moolenaar + ufunc->uf_dfunc_idx; 86109689a02SBram Moolenaar if (dfunc->df_instr == NULL) 86238ddf333SBram Moolenaar { 86338ddf333SBram Moolenaar iemsg("using call_def_function() on not compiled function"); 86409689a02SBram Moolenaar return FAIL; 86509689a02SBram Moolenaar } 86638ddf333SBram Moolenaar } 8678a7d6542SBram Moolenaar 8683b6a6eb7SBram Moolenaar CLEAR_FIELD(ectx); 8693b6a6eb7SBram Moolenaar ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; 8703b6a6eb7SBram Moolenaar ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); 8713b6a6eb7SBram Moolenaar if (ga_grow(&ectx.ec_stack, 20) == FAIL) 8723b6a6eb7SBram Moolenaar return FAIL; 8738a7d6542SBram Moolenaar ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); 874148ce7aeSBram Moolenaar ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10); 8758a7d6542SBram Moolenaar 8768a7d6542SBram Moolenaar // Put arguments on the stack. 8778a7d6542SBram Moolenaar for (idx = 0; idx < argc; ++idx) 8788a7d6542SBram Moolenaar { 87965b9545fSBram Moolenaar if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len 8808b565c2cSBram Moolenaar && check_typval_type(ufunc->uf_arg_types[idx], &argv[idx], 8818b565c2cSBram Moolenaar idx + 1) == FAIL) 88265b9545fSBram Moolenaar goto failed_early; 8838a7d6542SBram Moolenaar copy_tv(&argv[idx], STACK_TV_BOT(0)); 8848a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 8858a7d6542SBram Moolenaar } 88623e03252SBram Moolenaar 88723e03252SBram Moolenaar // Turn varargs into a list. Empty list if no args. 88823e03252SBram Moolenaar if (ufunc->uf_va_name != NULL) 88923e03252SBram Moolenaar { 89023e03252SBram Moolenaar int vararg_count = argc - ufunc->uf_args.ga_len; 89123e03252SBram Moolenaar 89223e03252SBram Moolenaar if (vararg_count < 0) 89323e03252SBram Moolenaar vararg_count = 0; 89423e03252SBram Moolenaar else 89523e03252SBram Moolenaar argc -= vararg_count; 89623e03252SBram Moolenaar if (exe_newlist(vararg_count, &ectx) == FAIL) 8971a2f4bf6SBram Moolenaar goto failed_early; 89824aa48b7SBram Moolenaar 89924aa48b7SBram Moolenaar // Check the type of the list items. 90024aa48b7SBram Moolenaar tv = STACK_TV_BOT(-1); 90124aa48b7SBram Moolenaar if (ufunc->uf_va_type != NULL 9022f8cbc4bSBram Moolenaar && ufunc->uf_va_type != &t_any 90324aa48b7SBram Moolenaar && ufunc->uf_va_type->tt_member != &t_any 90424aa48b7SBram Moolenaar && tv->vval.v_list != NULL) 90524aa48b7SBram Moolenaar { 90624aa48b7SBram Moolenaar type_T *expected = ufunc->uf_va_type->tt_member; 90724aa48b7SBram Moolenaar listitem_T *li = tv->vval.v_list->lv_first; 90824aa48b7SBram Moolenaar 90924aa48b7SBram Moolenaar for (idx = 0; idx < vararg_count; ++idx) 91024aa48b7SBram Moolenaar { 9118b565c2cSBram Moolenaar if (check_typval_type(expected, &li->li_tv, 9128b565c2cSBram Moolenaar argc + idx + 1) == FAIL) 91324aa48b7SBram Moolenaar goto failed_early; 91424aa48b7SBram Moolenaar li = li->li_next; 91524aa48b7SBram Moolenaar } 91624aa48b7SBram Moolenaar } 91724aa48b7SBram Moolenaar 91823e03252SBram Moolenaar if (defcount > 0) 91923e03252SBram Moolenaar // Move varargs list to below missing default arguments. 92023e03252SBram Moolenaar *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1); 92123e03252SBram Moolenaar --ectx.ec_stack.ga_len; 92223e03252SBram Moolenaar } 92323e03252SBram Moolenaar 924170fcfcfSBram Moolenaar // Make space for omitted arguments, will store default value below. 92523e03252SBram Moolenaar // Any varargs list goes after them. 926170fcfcfSBram Moolenaar if (defcount > 0) 927170fcfcfSBram Moolenaar for (idx = 0; idx < defcount; ++idx) 928170fcfcfSBram Moolenaar { 929170fcfcfSBram Moolenaar STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; 930170fcfcfSBram Moolenaar ++ectx.ec_stack.ga_len; 931170fcfcfSBram Moolenaar } 93223e03252SBram Moolenaar if (ufunc->uf_va_name != NULL) 93323e03252SBram Moolenaar ++ectx.ec_stack.ga_len; 9348a7d6542SBram Moolenaar 9358a7d6542SBram Moolenaar // Frame pointer points to just after arguments. 936bf67ea1aSBram Moolenaar ectx.ec_frame_idx = ectx.ec_stack.ga_len; 937bf67ea1aSBram Moolenaar initial_frame_idx = ectx.ec_frame_idx; 9388a7d6542SBram Moolenaar 9396f5b6dfbSBram Moolenaar if (partial != NULL) 9406f5b6dfbSBram Moolenaar { 94108f7a41bSBram Moolenaar if (partial->pt_ectx_stack == NULL && current_ectx != NULL) 94208f7a41bSBram Moolenaar { 94308f7a41bSBram Moolenaar // TODO: is this always the right way? 94408f7a41bSBram Moolenaar ectx.ec_outer_stack = ¤t_ectx->ec_stack; 94508f7a41bSBram Moolenaar ectx.ec_outer_frame = current_ectx->ec_frame_idx; 94608f7a41bSBram Moolenaar } 94708f7a41bSBram Moolenaar else 94808f7a41bSBram Moolenaar { 9496f5b6dfbSBram Moolenaar ectx.ec_outer_stack = partial->pt_ectx_stack; 9506f5b6dfbSBram Moolenaar ectx.ec_outer_frame = partial->pt_ectx_frame; 9516f5b6dfbSBram Moolenaar } 95208f7a41bSBram Moolenaar } 9536f5b6dfbSBram Moolenaar 9548a7d6542SBram Moolenaar // dummy frame entries 9558a7d6542SBram Moolenaar for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) 9568a7d6542SBram Moolenaar { 9578a7d6542SBram Moolenaar STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; 9588a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 9598a7d6542SBram Moolenaar } 9608a7d6542SBram Moolenaar 961bd5da371SBram Moolenaar { 962148ce7aeSBram Moolenaar // Reserve space for local variables and any closure reference count. 963bd5da371SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 964bd5da371SBram Moolenaar + ufunc->uf_dfunc_idx; 965bd5da371SBram Moolenaar 966148ce7aeSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 9678a7d6542SBram Moolenaar STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; 968148ce7aeSBram Moolenaar ectx.ec_stack.ga_len += dfunc->df_varcount; 969148ce7aeSBram Moolenaar if (dfunc->df_has_closure) 970148ce7aeSBram Moolenaar { 971148ce7aeSBram Moolenaar STACK_TV_VAR(idx)->v_type = VAR_NUMBER; 972148ce7aeSBram Moolenaar STACK_TV_VAR(idx)->vval.v_number = 0; 973148ce7aeSBram Moolenaar ++ectx.ec_stack.ga_len; 974148ce7aeSBram Moolenaar } 9758a7d6542SBram Moolenaar 9768a7d6542SBram Moolenaar ectx.ec_instr = dfunc->df_instr; 977bd5da371SBram Moolenaar } 978170fcfcfSBram Moolenaar 979ee8580e5SBram Moolenaar // Following errors are in the function, not the caller. 980a26b9700SBram Moolenaar // Commands behave like vim9script. 981ee8580e5SBram Moolenaar estack_push_ufunc(ufunc, 1); 982ee8580e5SBram Moolenaar current_sctx = ufunc->uf_script_ctx; 983a26b9700SBram Moolenaar current_sctx.sc_version = SCRIPT_VERSION_VIM9; 984a26b9700SBram Moolenaar 98577e5dcc3SBram Moolenaar // Do turn errors into exceptions. 98677e5dcc3SBram Moolenaar suppress_errthrow = FALSE; 98777e5dcc3SBram Moolenaar 988170fcfcfSBram Moolenaar // Decide where to start execution, handles optional arguments. 989170fcfcfSBram Moolenaar init_instr_idx(ufunc, argc, &ectx); 990170fcfcfSBram Moolenaar 9918a7d6542SBram Moolenaar for (;;) 9928a7d6542SBram Moolenaar { 9938a7d6542SBram Moolenaar isn_T *iptr; 99420431c9dSBram Moolenaar 995270d0388SBram Moolenaar if (++breakcheck_count >= 100) 996270d0388SBram Moolenaar { 997270d0388SBram Moolenaar line_breakcheck(); 998270d0388SBram Moolenaar breakcheck_count = 0; 999270d0388SBram Moolenaar } 100020431c9dSBram Moolenaar if (got_int) 100120431c9dSBram Moolenaar { 100220431c9dSBram Moolenaar // Turn CTRL-C into an exception. 100320431c9dSBram Moolenaar got_int = FALSE; 100497acfc78SBram Moolenaar if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL) 100520431c9dSBram Moolenaar goto failed; 100620431c9dSBram Moolenaar did_throw = TRUE; 100720431c9dSBram Moolenaar } 10088a7d6542SBram Moolenaar 1009a26b9700SBram Moolenaar if (did_emsg && msg_list != NULL && *msg_list != NULL) 1010a26b9700SBram Moolenaar { 1011a26b9700SBram Moolenaar // Turn an error message into an exception. 1012a26b9700SBram Moolenaar did_emsg = FALSE; 1013a26b9700SBram Moolenaar if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL) 1014a26b9700SBram Moolenaar goto failed; 1015a26b9700SBram Moolenaar did_throw = TRUE; 1016a26b9700SBram Moolenaar *msg_list = NULL; 1017a26b9700SBram Moolenaar } 1018a26b9700SBram Moolenaar 10198a7d6542SBram Moolenaar if (did_throw && !ectx.ec_in_catch) 10208a7d6542SBram Moolenaar { 10218a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 102220431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 10238a7d6542SBram Moolenaar 10248a7d6542SBram Moolenaar // An exception jumps to the first catch, finally, or returns from 10258a7d6542SBram Moolenaar // the current function. 10268a7d6542SBram Moolenaar if (trystack->ga_len > 0) 10278a7d6542SBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; 1028bf67ea1aSBram Moolenaar if (trycmd != NULL && trycmd->tcd_frame_idx == ectx.ec_frame_idx) 10298a7d6542SBram Moolenaar { 10308a7d6542SBram Moolenaar // jump to ":catch" or ":finally" 10318a7d6542SBram Moolenaar ectx.ec_in_catch = TRUE; 10328a7d6542SBram Moolenaar ectx.ec_iidx = trycmd->tcd_catch_idx; 10338a7d6542SBram Moolenaar } 10348a7d6542SBram Moolenaar else 10358a7d6542SBram Moolenaar { 1036cdd70f09SBram Moolenaar // Not inside try or need to return from current functions. 1037cdd70f09SBram Moolenaar // Push a dummy return value. 1038270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 10398a7d6542SBram Moolenaar goto failed; 10408a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 10418a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 10428a7d6542SBram Moolenaar tv->vval.v_number = 0; 10438a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 1044cdd70f09SBram Moolenaar if (ectx.ec_frame_idx == initial_frame_idx) 1045cdd70f09SBram Moolenaar { 1046cdd70f09SBram Moolenaar // At the toplevel we are done. 1047257cc5eeSBram Moolenaar need_rethrow = TRUE; 1048bf67ea1aSBram Moolenaar if (handle_closure_in_use(&ectx, FALSE) == FAIL) 1049bf67ea1aSBram Moolenaar goto failed; 10508a7d6542SBram Moolenaar goto done; 10518a7d6542SBram Moolenaar } 10528a7d6542SBram Moolenaar 1053bf67ea1aSBram Moolenaar if (func_return(&ectx) == FAIL) 1054bf67ea1aSBram Moolenaar goto failed; 10558a7d6542SBram Moolenaar } 10568a7d6542SBram Moolenaar continue; 10578a7d6542SBram Moolenaar } 10588a7d6542SBram Moolenaar 10598a7d6542SBram Moolenaar iptr = &ectx.ec_instr[ectx.ec_iidx++]; 10608a7d6542SBram Moolenaar switch (iptr->isn_type) 10618a7d6542SBram Moolenaar { 10628a7d6542SBram Moolenaar // execute Ex command line 10638a7d6542SBram Moolenaar case ISN_EXEC: 10646378c4feSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 10658a7d6542SBram Moolenaar do_cmdline_cmd(iptr->isn_arg.string); 10668a7d6542SBram Moolenaar break; 10678a7d6542SBram Moolenaar 1068cfe435d7SBram Moolenaar // execute Ex command from pieces on the stack 1069cfe435d7SBram Moolenaar case ISN_EXECCONCAT: 1070cfe435d7SBram Moolenaar { 1071cfe435d7SBram Moolenaar int count = iptr->isn_arg.number; 10727f6f56f4SBram Moolenaar size_t len = 0; 1073cfe435d7SBram Moolenaar int pass; 1074cfe435d7SBram Moolenaar int i; 1075cfe435d7SBram Moolenaar char_u *cmd = NULL; 1076cfe435d7SBram Moolenaar char_u *str; 1077cfe435d7SBram Moolenaar 1078cfe435d7SBram Moolenaar for (pass = 1; pass <= 2; ++pass) 1079cfe435d7SBram Moolenaar { 1080cfe435d7SBram Moolenaar for (i = 0; i < count; ++i) 1081cfe435d7SBram Moolenaar { 1082cfe435d7SBram Moolenaar tv = STACK_TV_BOT(i - count); 1083cfe435d7SBram Moolenaar str = tv->vval.v_string; 1084cfe435d7SBram Moolenaar if (str != NULL && *str != NUL) 1085cfe435d7SBram Moolenaar { 1086cfe435d7SBram Moolenaar if (pass == 2) 1087cfe435d7SBram Moolenaar STRCPY(cmd + len, str); 1088cfe435d7SBram Moolenaar len += STRLEN(str); 1089cfe435d7SBram Moolenaar } 1090cfe435d7SBram Moolenaar if (pass == 2) 1091cfe435d7SBram Moolenaar clear_tv(tv); 1092cfe435d7SBram Moolenaar } 1093cfe435d7SBram Moolenaar if (pass == 1) 1094cfe435d7SBram Moolenaar { 1095cfe435d7SBram Moolenaar cmd = alloc(len + 1); 1096cfe435d7SBram Moolenaar if (cmd == NULL) 1097cfe435d7SBram Moolenaar goto failed; 1098cfe435d7SBram Moolenaar len = 0; 1099cfe435d7SBram Moolenaar } 1100cfe435d7SBram Moolenaar } 1101cfe435d7SBram Moolenaar 11026378c4feSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1103cfe435d7SBram Moolenaar do_cmdline_cmd(cmd); 1104cfe435d7SBram Moolenaar vim_free(cmd); 1105cfe435d7SBram Moolenaar } 1106cfe435d7SBram Moolenaar break; 1107cfe435d7SBram Moolenaar 11088a7d6542SBram Moolenaar // execute :echo {string} ... 11098a7d6542SBram Moolenaar case ISN_ECHO: 11108a7d6542SBram Moolenaar { 11118a7d6542SBram Moolenaar int count = iptr->isn_arg.echo.echo_count; 11128a7d6542SBram Moolenaar int atstart = TRUE; 11138a7d6542SBram Moolenaar int needclr = TRUE; 11148a7d6542SBram Moolenaar 11158a7d6542SBram Moolenaar for (idx = 0; idx < count; ++idx) 11168a7d6542SBram Moolenaar { 11178a7d6542SBram Moolenaar tv = STACK_TV_BOT(idx - count); 11188a7d6542SBram Moolenaar echo_one(tv, iptr->isn_arg.echo.echo_with_white, 11198a7d6542SBram Moolenaar &atstart, &needclr); 11208a7d6542SBram Moolenaar clear_tv(tv); 11218a7d6542SBram Moolenaar } 1122e0807ea4SBram Moolenaar if (needclr) 1123e0807ea4SBram Moolenaar msg_clr_eos(); 11248a7d6542SBram Moolenaar ectx.ec_stack.ga_len -= count; 11258a7d6542SBram Moolenaar } 11268a7d6542SBram Moolenaar break; 11278a7d6542SBram Moolenaar 1128f93c7feaSBram Moolenaar // :execute {string} ... 1129f93c7feaSBram Moolenaar // :echomsg {string} ... 1130f93c7feaSBram Moolenaar // :echoerr {string} ... 1131ad39c094SBram Moolenaar case ISN_EXECUTE: 1132f93c7feaSBram Moolenaar case ISN_ECHOMSG: 1133f93c7feaSBram Moolenaar case ISN_ECHOERR: 1134ad39c094SBram Moolenaar { 1135ad39c094SBram Moolenaar int count = iptr->isn_arg.number; 1136ad39c094SBram Moolenaar garray_T ga; 1137ad39c094SBram Moolenaar char_u buf[NUMBUFLEN]; 1138ad39c094SBram Moolenaar char_u *p; 1139ad39c094SBram Moolenaar int len; 1140ad39c094SBram Moolenaar int failed = FALSE; 1141ad39c094SBram Moolenaar 1142ad39c094SBram Moolenaar ga_init2(&ga, 1, 80); 1143ad39c094SBram Moolenaar for (idx = 0; idx < count; ++idx) 1144ad39c094SBram Moolenaar { 1145ad39c094SBram Moolenaar tv = STACK_TV_BOT(idx - count); 1146e5abf7afSBram Moolenaar if (iptr->isn_type == ISN_EXECUTE) 1147e5abf7afSBram Moolenaar { 1148e5abf7afSBram Moolenaar if (tv->v_type == VAR_CHANNEL 1149e5abf7afSBram Moolenaar || tv->v_type == VAR_JOB) 1150ad39c094SBram Moolenaar { 11517517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1152ad39c094SBram Moolenaar emsg(_(e_inval_string)); 1153ad39c094SBram Moolenaar break; 1154ad39c094SBram Moolenaar } 1155ad39c094SBram Moolenaar else 1156ad39c094SBram Moolenaar p = tv_get_string_buf(tv, buf); 1157e5abf7afSBram Moolenaar } 1158e5abf7afSBram Moolenaar else 1159e5abf7afSBram Moolenaar p = tv_stringify(tv, buf); 1160ad39c094SBram Moolenaar 1161ad39c094SBram Moolenaar len = (int)STRLEN(p); 1162ad39c094SBram Moolenaar if (ga_grow(&ga, len + 2) == FAIL) 1163ad39c094SBram Moolenaar failed = TRUE; 1164ad39c094SBram Moolenaar else 1165ad39c094SBram Moolenaar { 1166ad39c094SBram Moolenaar if (ga.ga_len > 0) 1167ad39c094SBram Moolenaar ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; 1168ad39c094SBram Moolenaar STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); 1169ad39c094SBram Moolenaar ga.ga_len += len; 1170ad39c094SBram Moolenaar } 1171ad39c094SBram Moolenaar clear_tv(tv); 1172ad39c094SBram Moolenaar } 1173ad39c094SBram Moolenaar ectx.ec_stack.ga_len -= count; 1174e5abf7afSBram Moolenaar if (failed) 1175e5abf7afSBram Moolenaar goto on_error; 1176ad39c094SBram Moolenaar 1177e5abf7afSBram Moolenaar if (ga.ga_data != NULL) 1178f93c7feaSBram Moolenaar { 1179f93c7feaSBram Moolenaar if (iptr->isn_type == ISN_EXECUTE) 1180430deb19SBram Moolenaar { 1181430deb19SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1182ad39c094SBram Moolenaar do_cmdline_cmd((char_u *)ga.ga_data); 1183430deb19SBram Moolenaar } 1184f93c7feaSBram Moolenaar else 1185f93c7feaSBram Moolenaar { 1186f93c7feaSBram Moolenaar msg_sb_eol(); 1187f93c7feaSBram Moolenaar if (iptr->isn_type == ISN_ECHOMSG) 1188f93c7feaSBram Moolenaar { 1189f93c7feaSBram Moolenaar msg_attr(ga.ga_data, echo_attr); 1190f93c7feaSBram Moolenaar out_flush(); 1191f93c7feaSBram Moolenaar } 1192f93c7feaSBram Moolenaar else 1193f93c7feaSBram Moolenaar { 1194f93c7feaSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1195f93c7feaSBram Moolenaar emsg(ga.ga_data); 1196f93c7feaSBram Moolenaar } 1197f93c7feaSBram Moolenaar } 1198f93c7feaSBram Moolenaar } 1199ad39c094SBram Moolenaar ga_clear(&ga); 1200ad39c094SBram Moolenaar } 1201ad39c094SBram Moolenaar break; 1202ad39c094SBram Moolenaar 12038a7d6542SBram Moolenaar // load local variable or argument 12048a7d6542SBram Moolenaar case ISN_LOAD: 1205270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 12068a7d6542SBram Moolenaar goto failed; 12078a7d6542SBram Moolenaar copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); 12088a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 12098a7d6542SBram Moolenaar break; 12108a7d6542SBram Moolenaar 1211c8cd2b34SBram Moolenaar // load variable or argument from outer scope 1212c8cd2b34SBram Moolenaar case ISN_LOADOUTER: 1213270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 1214c8cd2b34SBram Moolenaar goto failed; 1215c8cd2b34SBram Moolenaar copy_tv(STACK_OUT_TV_VAR(iptr->isn_arg.number), 1216c8cd2b34SBram Moolenaar STACK_TV_BOT(0)); 1217c8cd2b34SBram Moolenaar ++ectx.ec_stack.ga_len; 1218c8cd2b34SBram Moolenaar break; 1219c8cd2b34SBram Moolenaar 12208a7d6542SBram Moolenaar // load v: variable 12218a7d6542SBram Moolenaar case ISN_LOADV: 1222270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 12238a7d6542SBram Moolenaar goto failed; 12248a7d6542SBram Moolenaar copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0)); 12258a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 12268a7d6542SBram Moolenaar break; 12278a7d6542SBram Moolenaar 1228b283a8a6SBram Moolenaar // load s: variable in Vim9 script 12298a7d6542SBram Moolenaar case ISN_LOADSCRIPT: 12308a7d6542SBram Moolenaar { 12318a7d6542SBram Moolenaar scriptitem_T *si = 123221b9e977SBram Moolenaar SCRIPT_ITEM(iptr->isn_arg.script.script_sid); 12338a7d6542SBram Moolenaar svar_T *sv; 12348a7d6542SBram Moolenaar 12358a7d6542SBram Moolenaar sv = ((svar_T *)si->sn_var_vals.ga_data) 12368a7d6542SBram Moolenaar + iptr->isn_arg.script.script_idx; 1237270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 12388a7d6542SBram Moolenaar goto failed; 12398a7d6542SBram Moolenaar copy_tv(sv->sv_tv, STACK_TV_BOT(0)); 12408a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 12418a7d6542SBram Moolenaar } 12428a7d6542SBram Moolenaar break; 12438a7d6542SBram Moolenaar 12448a7d6542SBram Moolenaar // load s: variable in old script 12458a7d6542SBram Moolenaar case ISN_LOADS: 12468a7d6542SBram Moolenaar { 1247b283a8a6SBram Moolenaar hashtab_T *ht = &SCRIPT_VARS( 1248b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 1249b283a8a6SBram Moolenaar char_u *name = iptr->isn_arg.loadstore.ls_name; 12508a7d6542SBram Moolenaar dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE); 12510bbf722aSBram Moolenaar 12528a7d6542SBram Moolenaar if (di == NULL) 12538a7d6542SBram Moolenaar { 12547517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1255451c2e35SBram Moolenaar semsg(_(e_undefined_variable_str), name); 1256f0b9f43cSBram Moolenaar goto on_error; 12578a7d6542SBram Moolenaar } 12588a7d6542SBram Moolenaar else 12598a7d6542SBram Moolenaar { 1260270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 12618a7d6542SBram Moolenaar goto failed; 12628a7d6542SBram Moolenaar copy_tv(&di->di_tv, STACK_TV_BOT(0)); 12638a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 12648a7d6542SBram Moolenaar } 12658a7d6542SBram Moolenaar } 12668a7d6542SBram Moolenaar break; 12678a7d6542SBram Moolenaar 1268d3aac291SBram Moolenaar // load g:/b:/w:/t: variable 12698a7d6542SBram Moolenaar case ISN_LOADG: 1270d3aac291SBram Moolenaar case ISN_LOADB: 1271d3aac291SBram Moolenaar case ISN_LOADW: 1272d3aac291SBram Moolenaar case ISN_LOADT: 12738a7d6542SBram Moolenaar { 1274d3aac291SBram Moolenaar dictitem_T *di = NULL; 1275d3aac291SBram Moolenaar hashtab_T *ht = NULL; 1276d3aac291SBram Moolenaar char namespace; 12772f8ce0aeSBram Moolenaar 1278d3aac291SBram Moolenaar switch (iptr->isn_type) 1279d3aac291SBram Moolenaar { 1280d3aac291SBram Moolenaar case ISN_LOADG: 1281d3aac291SBram Moolenaar ht = get_globvar_ht(); 1282d3aac291SBram Moolenaar namespace = 'g'; 1283d3aac291SBram Moolenaar break; 1284d3aac291SBram Moolenaar case ISN_LOADB: 1285d3aac291SBram Moolenaar ht = &curbuf->b_vars->dv_hashtab; 1286d3aac291SBram Moolenaar namespace = 'b'; 1287d3aac291SBram Moolenaar break; 1288d3aac291SBram Moolenaar case ISN_LOADW: 1289d3aac291SBram Moolenaar ht = &curwin->w_vars->dv_hashtab; 1290d3aac291SBram Moolenaar namespace = 'w'; 1291d3aac291SBram Moolenaar break; 1292d3aac291SBram Moolenaar case ISN_LOADT: 1293d3aac291SBram Moolenaar ht = &curtab->tp_vars->dv_hashtab; 1294d3aac291SBram Moolenaar namespace = 't'; 1295d3aac291SBram Moolenaar break; 1296d3aac291SBram Moolenaar default: // Cannot reach here 1297d3aac291SBram Moolenaar goto failed; 1298d3aac291SBram Moolenaar } 1299d3aac291SBram Moolenaar di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE); 13000bbf722aSBram Moolenaar 13018a7d6542SBram Moolenaar if (di == NULL) 13028a7d6542SBram Moolenaar { 13037517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1304451c2e35SBram Moolenaar semsg(_(e_undefined_variable_char_str), 1305d3aac291SBram Moolenaar namespace, iptr->isn_arg.string); 1306f0b9f43cSBram Moolenaar goto on_error; 13078a7d6542SBram Moolenaar } 13088a7d6542SBram Moolenaar else 13098a7d6542SBram Moolenaar { 1310270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 13118a7d6542SBram Moolenaar goto failed; 13128a7d6542SBram Moolenaar copy_tv(&di->di_tv, STACK_TV_BOT(0)); 13138a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 13148a7d6542SBram Moolenaar } 13158a7d6542SBram Moolenaar } 13168a7d6542SBram Moolenaar break; 13178a7d6542SBram Moolenaar 13182f8ce0aeSBram Moolenaar // load g:/b:/w:/t: namespace 13192f8ce0aeSBram Moolenaar case ISN_LOADGDICT: 13202f8ce0aeSBram Moolenaar case ISN_LOADBDICT: 13212f8ce0aeSBram Moolenaar case ISN_LOADWDICT: 13222f8ce0aeSBram Moolenaar case ISN_LOADTDICT: 13232f8ce0aeSBram Moolenaar { 13242f8ce0aeSBram Moolenaar dict_T *d = NULL; 13252f8ce0aeSBram Moolenaar 13262f8ce0aeSBram Moolenaar switch (iptr->isn_type) 13272f8ce0aeSBram Moolenaar { 1328682d0a15SBram Moolenaar case ISN_LOADGDICT: d = get_globvar_dict(); break; 1329682d0a15SBram Moolenaar case ISN_LOADBDICT: d = curbuf->b_vars; break; 1330682d0a15SBram Moolenaar case ISN_LOADWDICT: d = curwin->w_vars; break; 1331682d0a15SBram Moolenaar case ISN_LOADTDICT: d = curtab->tp_vars; break; 13322f8ce0aeSBram Moolenaar default: // Cannot reach here 13332f8ce0aeSBram Moolenaar goto failed; 13342f8ce0aeSBram Moolenaar } 13352f8ce0aeSBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 13362f8ce0aeSBram Moolenaar goto failed; 13372f8ce0aeSBram Moolenaar tv = STACK_TV_BOT(0); 13382f8ce0aeSBram Moolenaar tv->v_type = VAR_DICT; 13392f8ce0aeSBram Moolenaar tv->v_lock = 0; 13402f8ce0aeSBram Moolenaar tv->vval.v_dict = d; 13412f8ce0aeSBram Moolenaar ++ectx.ec_stack.ga_len; 13422f8ce0aeSBram Moolenaar } 13432f8ce0aeSBram Moolenaar break; 13442f8ce0aeSBram Moolenaar 13458a7d6542SBram Moolenaar // load &option 13468a7d6542SBram Moolenaar case ISN_LOADOPT: 13478a7d6542SBram Moolenaar { 13488a7d6542SBram Moolenaar typval_T optval; 13498a7d6542SBram Moolenaar char_u *name = iptr->isn_arg.string; 13508a7d6542SBram Moolenaar 1351a8c17704SBram Moolenaar // This is not expected to fail, name is checked during 1352a8c17704SBram Moolenaar // compilation: don't set SOURCING_LNUM. 1353270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 13548a7d6542SBram Moolenaar goto failed; 13559a78e6dfSBram Moolenaar if (eval_option(&name, &optval, TRUE) == FAIL) 135658ceca5cSBram Moolenaar goto failed; 13578a7d6542SBram Moolenaar *STACK_TV_BOT(0) = optval; 13588a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 13598a7d6542SBram Moolenaar } 13608a7d6542SBram Moolenaar break; 13618a7d6542SBram Moolenaar 13628a7d6542SBram Moolenaar // load $ENV 13638a7d6542SBram Moolenaar case ISN_LOADENV: 13648a7d6542SBram Moolenaar { 13658a7d6542SBram Moolenaar typval_T optval; 13668a7d6542SBram Moolenaar char_u *name = iptr->isn_arg.string; 13678a7d6542SBram Moolenaar 1368270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 13698a7d6542SBram Moolenaar goto failed; 13700bbf722aSBram Moolenaar // name is always valid, checked when compiling 13719a78e6dfSBram Moolenaar (void)eval_env_var(&name, &optval, TRUE); 13728a7d6542SBram Moolenaar *STACK_TV_BOT(0) = optval; 13738a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 13748a7d6542SBram Moolenaar } 13758a7d6542SBram Moolenaar break; 13768a7d6542SBram Moolenaar 13778a7d6542SBram Moolenaar // load @register 13788a7d6542SBram Moolenaar case ISN_LOADREG: 1379270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 13808a7d6542SBram Moolenaar goto failed; 13818a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 13828a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 13832f8ce0aeSBram Moolenaar tv->v_lock = 0; 13848a7d6542SBram Moolenaar tv->vval.v_string = get_reg_contents( 13858a7d6542SBram Moolenaar iptr->isn_arg.number, GREG_EXPR_SRC); 13868a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 13878a7d6542SBram Moolenaar break; 13888a7d6542SBram Moolenaar 13898a7d6542SBram Moolenaar // store local variable 13908a7d6542SBram Moolenaar case ISN_STORE: 13918a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 13928a7d6542SBram Moolenaar tv = STACK_TV_VAR(iptr->isn_arg.number); 13938a7d6542SBram Moolenaar clear_tv(tv); 13948a7d6542SBram Moolenaar *tv = *STACK_TV_BOT(0); 13958a7d6542SBram Moolenaar break; 13968a7d6542SBram Moolenaar 1397b68b346eSBram Moolenaar // store variable or argument in outer scope 1398b68b346eSBram Moolenaar case ISN_STOREOUTER: 1399b68b346eSBram Moolenaar --ectx.ec_stack.ga_len; 1400b68b346eSBram Moolenaar tv = STACK_OUT_TV_VAR(iptr->isn_arg.number); 1401b68b346eSBram Moolenaar clear_tv(tv); 1402b68b346eSBram Moolenaar *tv = *STACK_TV_BOT(0); 1403b68b346eSBram Moolenaar break; 1404b68b346eSBram Moolenaar 1405b283a8a6SBram Moolenaar // store s: variable in old script 1406b283a8a6SBram Moolenaar case ISN_STORES: 1407b283a8a6SBram Moolenaar { 1408b283a8a6SBram Moolenaar hashtab_T *ht = &SCRIPT_VARS( 1409b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 1410b283a8a6SBram Moolenaar char_u *name = iptr->isn_arg.loadstore.ls_name; 14110bbf722aSBram Moolenaar dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE); 1412b283a8a6SBram Moolenaar 1413b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 14140bbf722aSBram Moolenaar if (di == NULL) 14155deeb3f1SBram Moolenaar store_var(name, STACK_TV_BOT(0)); 14160bbf722aSBram Moolenaar else 14170bbf722aSBram Moolenaar { 1418b283a8a6SBram Moolenaar clear_tv(&di->di_tv); 1419b283a8a6SBram Moolenaar di->di_tv = *STACK_TV_BOT(0); 1420b283a8a6SBram Moolenaar } 14210bbf722aSBram Moolenaar } 1422b283a8a6SBram Moolenaar break; 1423b283a8a6SBram Moolenaar 1424b283a8a6SBram Moolenaar // store script-local variable in Vim9 script 14258a7d6542SBram Moolenaar case ISN_STORESCRIPT: 14268a7d6542SBram Moolenaar { 142721b9e977SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 14288a7d6542SBram Moolenaar iptr->isn_arg.script.script_sid); 14298a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 14308a7d6542SBram Moolenaar + iptr->isn_arg.script.script_idx; 14318a7d6542SBram Moolenaar 14328a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 14338a7d6542SBram Moolenaar clear_tv(sv->sv_tv); 14348a7d6542SBram Moolenaar *sv->sv_tv = *STACK_TV_BOT(0); 14358a7d6542SBram Moolenaar } 14368a7d6542SBram Moolenaar break; 14378a7d6542SBram Moolenaar 14388a7d6542SBram Moolenaar // store option 14398a7d6542SBram Moolenaar case ISN_STOREOPT: 14408a7d6542SBram Moolenaar { 14418a7d6542SBram Moolenaar long n = 0; 14428a7d6542SBram Moolenaar char_u *s = NULL; 14438a7d6542SBram Moolenaar char *msg; 14448a7d6542SBram Moolenaar 14458a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 14468a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 14478a7d6542SBram Moolenaar if (tv->v_type == VAR_STRING) 144897a2af39SBram Moolenaar { 14498a7d6542SBram Moolenaar s = tv->vval.v_string; 145097a2af39SBram Moolenaar if (s == NULL) 145197a2af39SBram Moolenaar s = (char_u *)""; 145297a2af39SBram Moolenaar } 14538a7d6542SBram Moolenaar else 1454a6e67e4fSBram Moolenaar // must be VAR_NUMBER, CHECKTYPE makes sure 1455a6e67e4fSBram Moolenaar n = tv->vval.v_number; 14568a7d6542SBram Moolenaar msg = set_option_value(iptr->isn_arg.storeopt.so_name, 14578a7d6542SBram Moolenaar n, s, iptr->isn_arg.storeopt.so_flags); 1458e75ba268SBram Moolenaar clear_tv(tv); 14598a7d6542SBram Moolenaar if (msg != NULL) 14608a7d6542SBram Moolenaar { 14617517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 14628a7d6542SBram Moolenaar emsg(_(msg)); 1463e859312eSBram Moolenaar goto on_error; 14648a7d6542SBram Moolenaar } 14658a7d6542SBram Moolenaar } 14668a7d6542SBram Moolenaar break; 14678a7d6542SBram Moolenaar 1468b283a8a6SBram Moolenaar // store $ENV 1469b283a8a6SBram Moolenaar case ISN_STOREENV: 1470b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 147120431c9dSBram Moolenaar tv = STACK_TV_BOT(0); 147220431c9dSBram Moolenaar vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv)); 147320431c9dSBram Moolenaar clear_tv(tv); 1474b283a8a6SBram Moolenaar break; 1475b283a8a6SBram Moolenaar 1476b283a8a6SBram Moolenaar // store @r 1477b283a8a6SBram Moolenaar case ISN_STOREREG: 1478b283a8a6SBram Moolenaar { 1479b283a8a6SBram Moolenaar int reg = iptr->isn_arg.number; 1480b283a8a6SBram Moolenaar 1481b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 1482401d9ffbSBram Moolenaar tv = STACK_TV_BOT(0); 1483b283a8a6SBram Moolenaar write_reg_contents(reg == '@' ? '"' : reg, 1484401d9ffbSBram Moolenaar tv_get_string(tv), -1, FALSE); 1485401d9ffbSBram Moolenaar clear_tv(tv); 1486b283a8a6SBram Moolenaar } 1487b283a8a6SBram Moolenaar break; 1488b283a8a6SBram Moolenaar 1489b283a8a6SBram Moolenaar // store v: variable 1490b283a8a6SBram Moolenaar case ISN_STOREV: 1491b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 1492b283a8a6SBram Moolenaar if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0)) 1493b283a8a6SBram Moolenaar == FAIL) 1494e859312eSBram Moolenaar // should not happen, type is checked when compiling 1495e859312eSBram Moolenaar goto on_error; 1496b283a8a6SBram Moolenaar break; 1497b283a8a6SBram Moolenaar 1498d3aac291SBram Moolenaar // store g:/b:/w:/t: variable 14998a7d6542SBram Moolenaar case ISN_STOREG: 1500d3aac291SBram Moolenaar case ISN_STOREB: 1501d3aac291SBram Moolenaar case ISN_STOREW: 1502d3aac291SBram Moolenaar case ISN_STORET: 15038a7d6542SBram Moolenaar { 15048a7d6542SBram Moolenaar dictitem_T *di; 1505d3aac291SBram Moolenaar hashtab_T *ht; 1506d3aac291SBram Moolenaar switch (iptr->isn_type) 1507d3aac291SBram Moolenaar { 1508d3aac291SBram Moolenaar case ISN_STOREG: 1509d3aac291SBram Moolenaar ht = get_globvar_ht(); 1510d3aac291SBram Moolenaar break; 1511d3aac291SBram Moolenaar case ISN_STOREB: 1512d3aac291SBram Moolenaar ht = &curbuf->b_vars->dv_hashtab; 1513d3aac291SBram Moolenaar break; 1514d3aac291SBram Moolenaar case ISN_STOREW: 1515d3aac291SBram Moolenaar ht = &curwin->w_vars->dv_hashtab; 1516d3aac291SBram Moolenaar break; 1517d3aac291SBram Moolenaar case ISN_STORET: 1518d3aac291SBram Moolenaar ht = &curtab->tp_vars->dv_hashtab; 1519d3aac291SBram Moolenaar break; 1520d3aac291SBram Moolenaar default: // Cannot reach here 1521d3aac291SBram Moolenaar goto failed; 1522d3aac291SBram Moolenaar } 15238a7d6542SBram Moolenaar 15248a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 1525bf67ea1aSBram Moolenaar di = find_var_in_ht(ht, 0, iptr->isn_arg.string + 2, TRUE); 15268a7d6542SBram Moolenaar if (di == NULL) 15270bbf722aSBram Moolenaar store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); 15288a7d6542SBram Moolenaar else 15298a7d6542SBram Moolenaar { 15308a7d6542SBram Moolenaar clear_tv(&di->di_tv); 15318a7d6542SBram Moolenaar di->di_tv = *STACK_TV_BOT(0); 15328a7d6542SBram Moolenaar } 15338a7d6542SBram Moolenaar } 15348a7d6542SBram Moolenaar break; 15358a7d6542SBram Moolenaar 15368a7d6542SBram Moolenaar // store number in local variable 15378a7d6542SBram Moolenaar case ISN_STORENR: 1538a471eeaeSBram Moolenaar tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx); 15398a7d6542SBram Moolenaar clear_tv(tv); 15408a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 1541a471eeaeSBram Moolenaar tv->vval.v_number = iptr->isn_arg.storenr.stnr_val; 15428a7d6542SBram Moolenaar break; 15438a7d6542SBram Moolenaar 15441cc2a94fSBram Moolenaar // store value in list variable 15451cc2a94fSBram Moolenaar case ISN_STORELIST: 15461cc2a94fSBram Moolenaar { 15471cc2a94fSBram Moolenaar typval_T *tv_idx = STACK_TV_BOT(-2); 15481cc2a94fSBram Moolenaar varnumber_T lidx = tv_idx->vval.v_number; 15491cc2a94fSBram Moolenaar typval_T *tv_list = STACK_TV_BOT(-1); 15501cc2a94fSBram Moolenaar list_T *list = tv_list->vval.v_list; 15511cc2a94fSBram Moolenaar 15520b4c66c6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 15531cc2a94fSBram Moolenaar if (lidx < 0 && list->lv_len + lidx >= 0) 15541cc2a94fSBram Moolenaar // negative index is relative to the end 15551cc2a94fSBram Moolenaar lidx = list->lv_len + lidx; 15561cc2a94fSBram Moolenaar if (lidx < 0 || lidx > list->lv_len) 15571cc2a94fSBram Moolenaar { 15581cc2a94fSBram Moolenaar semsg(_(e_listidx), lidx); 1559e859312eSBram Moolenaar goto on_error; 15601cc2a94fSBram Moolenaar } 15611cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-3); 15621cc2a94fSBram Moolenaar if (lidx < list->lv_len) 15631cc2a94fSBram Moolenaar { 15641cc2a94fSBram Moolenaar listitem_T *li = list_find(list, lidx); 15651cc2a94fSBram Moolenaar 15660b4c66c6SBram Moolenaar if (error_if_locked(li->li_tv.v_lock, 15670b4c66c6SBram Moolenaar e_cannot_change_list_item)) 15680b4c66c6SBram Moolenaar goto failed; 15691cc2a94fSBram Moolenaar // overwrite existing list item 15701cc2a94fSBram Moolenaar clear_tv(&li->li_tv); 15711cc2a94fSBram Moolenaar li->li_tv = *tv; 15721cc2a94fSBram Moolenaar } 15731cc2a94fSBram Moolenaar else 15741cc2a94fSBram Moolenaar { 15750b4c66c6SBram Moolenaar if (error_if_locked(list->lv_lock, 15760b4c66c6SBram Moolenaar e_cannot_change_list)) 15770b4c66c6SBram Moolenaar goto failed; 1578e859312eSBram Moolenaar // append to list, only fails when out of memory 15791cc2a94fSBram Moolenaar if (list_append_tv(list, tv) == FAIL) 15801cc2a94fSBram Moolenaar goto failed; 15811cc2a94fSBram Moolenaar clear_tv(tv); 15821cc2a94fSBram Moolenaar } 15831cc2a94fSBram Moolenaar clear_tv(tv_idx); 15841cc2a94fSBram Moolenaar clear_tv(tv_list); 1585f163bd5eSBram Moolenaar ectx.ec_stack.ga_len -= 3; 15861cc2a94fSBram Moolenaar } 15871cc2a94fSBram Moolenaar break; 15881cc2a94fSBram Moolenaar 15891cc2a94fSBram Moolenaar // store value in dict variable 15901cc2a94fSBram Moolenaar case ISN_STOREDICT: 15911cc2a94fSBram Moolenaar { 15921cc2a94fSBram Moolenaar typval_T *tv_key = STACK_TV_BOT(-2); 15931cc2a94fSBram Moolenaar char_u *key = tv_key->vval.v_string; 15941cc2a94fSBram Moolenaar typval_T *tv_dict = STACK_TV_BOT(-1); 15951cc2a94fSBram Moolenaar dict_T *dict = tv_dict->vval.v_dict; 15961cc2a94fSBram Moolenaar dictitem_T *di; 15971cc2a94fSBram Moolenaar 15980b4c66c6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 15998e4c8c85SBram Moolenaar if (dict == NULL) 16008e4c8c85SBram Moolenaar { 1601bc4c5051SBram Moolenaar emsg(_(e_dictionary_not_set)); 16028e4c8c85SBram Moolenaar goto on_error; 16038e4c8c85SBram Moolenaar } 160458626872SBram Moolenaar if (key == NULL) 160558626872SBram Moolenaar key = (char_u *)""; 16061cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-3); 16071cc2a94fSBram Moolenaar di = dict_find(dict, key, -1); 16081cc2a94fSBram Moolenaar if (di != NULL) 16091cc2a94fSBram Moolenaar { 16100b4c66c6SBram Moolenaar if (error_if_locked(di->di_tv.v_lock, 16110b4c66c6SBram Moolenaar e_cannot_change_dict_item)) 16120b4c66c6SBram Moolenaar goto failed; 1613e859312eSBram Moolenaar // overwrite existing value 16141cc2a94fSBram Moolenaar clear_tv(&di->di_tv); 16151cc2a94fSBram Moolenaar di->di_tv = *tv; 16161cc2a94fSBram Moolenaar } 16171cc2a94fSBram Moolenaar else 16181cc2a94fSBram Moolenaar { 16190b4c66c6SBram Moolenaar if (error_if_locked(dict->dv_lock, 16200b4c66c6SBram Moolenaar e_cannot_change_dict)) 16210b4c66c6SBram Moolenaar goto failed; 1622e859312eSBram Moolenaar // add to dict, only fails when out of memory 16231cc2a94fSBram Moolenaar if (dict_add_tv(dict, (char *)key, tv) == FAIL) 16241cc2a94fSBram Moolenaar goto failed; 16251cc2a94fSBram Moolenaar clear_tv(tv); 16261cc2a94fSBram Moolenaar } 16271cc2a94fSBram Moolenaar clear_tv(tv_key); 16281cc2a94fSBram Moolenaar clear_tv(tv_dict); 1629f163bd5eSBram Moolenaar ectx.ec_stack.ga_len -= 3; 16301cc2a94fSBram Moolenaar } 16311cc2a94fSBram Moolenaar break; 16321cc2a94fSBram Moolenaar 16338a7d6542SBram Moolenaar // push constant 16348a7d6542SBram Moolenaar case ISN_PUSHNR: 16358a7d6542SBram Moolenaar case ISN_PUSHBOOL: 16368a7d6542SBram Moolenaar case ISN_PUSHSPEC: 16378a7d6542SBram Moolenaar case ISN_PUSHF: 16388a7d6542SBram Moolenaar case ISN_PUSHS: 16398a7d6542SBram Moolenaar case ISN_PUSHBLOB: 164042a480bfSBram Moolenaar case ISN_PUSHFUNC: 164142a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 164242a480bfSBram Moolenaar case ISN_PUSHJOB: 1643270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 16448a7d6542SBram Moolenaar goto failed; 16458a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 16462f8ce0aeSBram Moolenaar tv->v_lock = 0; 16478a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 16488a7d6542SBram Moolenaar switch (iptr->isn_type) 16498a7d6542SBram Moolenaar { 16508a7d6542SBram Moolenaar case ISN_PUSHNR: 16518a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 16528a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 16538a7d6542SBram Moolenaar break; 16548a7d6542SBram Moolenaar case ISN_PUSHBOOL: 16558a7d6542SBram Moolenaar tv->v_type = VAR_BOOL; 16568a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 16578a7d6542SBram Moolenaar break; 16588a7d6542SBram Moolenaar case ISN_PUSHSPEC: 16598a7d6542SBram Moolenaar tv->v_type = VAR_SPECIAL; 16608a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 16618a7d6542SBram Moolenaar break; 16628a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 16638a7d6542SBram Moolenaar case ISN_PUSHF: 16648a7d6542SBram Moolenaar tv->v_type = VAR_FLOAT; 16658a7d6542SBram Moolenaar tv->vval.v_float = iptr->isn_arg.fnumber; 16668a7d6542SBram Moolenaar break; 16678a7d6542SBram Moolenaar #endif 16688a7d6542SBram Moolenaar case ISN_PUSHBLOB: 16698a7d6542SBram Moolenaar blob_copy(iptr->isn_arg.blob, tv); 16708a7d6542SBram Moolenaar break; 167142a480bfSBram Moolenaar case ISN_PUSHFUNC: 167242a480bfSBram Moolenaar tv->v_type = VAR_FUNC; 1673087d2e15SBram Moolenaar if (iptr->isn_arg.string == NULL) 1674087d2e15SBram Moolenaar tv->vval.v_string = NULL; 1675087d2e15SBram Moolenaar else 1676087d2e15SBram Moolenaar tv->vval.v_string = 1677087d2e15SBram Moolenaar vim_strsave(iptr->isn_arg.string); 167842a480bfSBram Moolenaar break; 167942a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 168042a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 168142a480bfSBram Moolenaar tv->v_type = VAR_CHANNEL; 168242a480bfSBram Moolenaar tv->vval.v_channel = iptr->isn_arg.channel; 168342a480bfSBram Moolenaar if (tv->vval.v_channel != NULL) 168442a480bfSBram Moolenaar ++tv->vval.v_channel->ch_refcount; 168542a480bfSBram Moolenaar #endif 168642a480bfSBram Moolenaar break; 168742a480bfSBram Moolenaar case ISN_PUSHJOB: 168842a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 168942a480bfSBram Moolenaar tv->v_type = VAR_JOB; 169042a480bfSBram Moolenaar tv->vval.v_job = iptr->isn_arg.job; 169142a480bfSBram Moolenaar if (tv->vval.v_job != NULL) 169242a480bfSBram Moolenaar ++tv->vval.v_job->jv_refcount; 169342a480bfSBram Moolenaar #endif 169442a480bfSBram Moolenaar break; 16958a7d6542SBram Moolenaar default: 16968a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 1697e69f6d04SBram Moolenaar tv->vval.v_string = vim_strsave( 1698e69f6d04SBram Moolenaar iptr->isn_arg.string == NULL 1699e69f6d04SBram Moolenaar ? (char_u *)"" : iptr->isn_arg.string); 17008a7d6542SBram Moolenaar } 17018a7d6542SBram Moolenaar break; 17028a7d6542SBram Moolenaar 1703d72c1bf0SBram Moolenaar case ISN_UNLET: 1704d72c1bf0SBram Moolenaar if (do_unlet(iptr->isn_arg.unlet.ul_name, 1705d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_forceit) == FAIL) 1706e859312eSBram Moolenaar goto on_error; 1707d72c1bf0SBram Moolenaar break; 17087bdaea6eSBram Moolenaar case ISN_UNLETENV: 17097bdaea6eSBram Moolenaar vim_unsetenv(iptr->isn_arg.unlet.ul_name); 17107bdaea6eSBram Moolenaar break; 1711d72c1bf0SBram Moolenaar 17120b4c66c6SBram Moolenaar case ISN_LOCKCONST: 17130b4c66c6SBram Moolenaar item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE); 17140b4c66c6SBram Moolenaar break; 17150b4c66c6SBram Moolenaar 17168a7d6542SBram Moolenaar // create a list from items on the stack; uses a single allocation 17178a7d6542SBram Moolenaar // for the list header and the items 17188a7d6542SBram Moolenaar case ISN_NEWLIST: 1719fe270817SBram Moolenaar if (exe_newlist(iptr->isn_arg.number, &ectx) == FAIL) 17208a7d6542SBram Moolenaar goto failed; 17218a7d6542SBram Moolenaar break; 17228a7d6542SBram Moolenaar 17238a7d6542SBram Moolenaar // create a dict from items on the stack 17248a7d6542SBram Moolenaar case ISN_NEWDICT: 17258a7d6542SBram Moolenaar { 17268a7d6542SBram Moolenaar int count = iptr->isn_arg.number; 17278a7d6542SBram Moolenaar dict_T *dict = dict_alloc(); 17288a7d6542SBram Moolenaar dictitem_T *item; 17298a7d6542SBram Moolenaar 17308a7d6542SBram Moolenaar if (dict == NULL) 17318a7d6542SBram Moolenaar goto failed; 17328a7d6542SBram Moolenaar for (idx = 0; idx < count; ++idx) 17338a7d6542SBram Moolenaar { 1734e859312eSBram Moolenaar // have already checked key type is VAR_STRING 17358a7d6542SBram Moolenaar tv = STACK_TV_BOT(2 * (idx - count)); 1736e859312eSBram Moolenaar // check key is unique 1737e859312eSBram Moolenaar item = dict_find(dict, tv->vval.v_string, -1); 1738e859312eSBram Moolenaar if (item != NULL) 1739e859312eSBram Moolenaar { 17407517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1741e859312eSBram Moolenaar semsg(_(e_duplicate_key), tv->vval.v_string); 1742e859312eSBram Moolenaar dict_unref(dict); 1743e859312eSBram Moolenaar goto on_error; 1744e859312eSBram Moolenaar } 17458a7d6542SBram Moolenaar item = dictitem_alloc(tv->vval.v_string); 17468a7d6542SBram Moolenaar clear_tv(tv); 17478a7d6542SBram Moolenaar if (item == NULL) 1748e859312eSBram Moolenaar { 1749e859312eSBram Moolenaar dict_unref(dict); 17508a7d6542SBram Moolenaar goto failed; 1751e859312eSBram Moolenaar } 17528a7d6542SBram Moolenaar item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); 17538a7d6542SBram Moolenaar item->di_tv.v_lock = 0; 17548a7d6542SBram Moolenaar if (dict_add(dict, item) == FAIL) 1755e859312eSBram Moolenaar { 1756d032f34aSBram Moolenaar // can this ever happen? 1757e859312eSBram Moolenaar dict_unref(dict); 17588a7d6542SBram Moolenaar goto failed; 17598a7d6542SBram Moolenaar } 1760e859312eSBram Moolenaar } 17618a7d6542SBram Moolenaar 17628a7d6542SBram Moolenaar if (count > 0) 17638a7d6542SBram Moolenaar ectx.ec_stack.ga_len -= 2 * count - 1; 1764270d0388SBram Moolenaar else if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 17658a7d6542SBram Moolenaar goto failed; 17668a7d6542SBram Moolenaar else 17678a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 17688a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 17698a7d6542SBram Moolenaar tv->v_type = VAR_DICT; 17702f8ce0aeSBram Moolenaar tv->v_lock = 0; 17718a7d6542SBram Moolenaar tv->vval.v_dict = dict; 17728a7d6542SBram Moolenaar ++dict->dv_refcount; 17738a7d6542SBram Moolenaar } 17748a7d6542SBram Moolenaar break; 17758a7d6542SBram Moolenaar 17768a7d6542SBram Moolenaar // call a :def function 17778a7d6542SBram Moolenaar case ISN_DCALL: 1778dfa3d552SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 17798a7d6542SBram Moolenaar if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx, 17808a7d6542SBram Moolenaar iptr->isn_arg.dfunc.cdf_argcount, 17818a7d6542SBram Moolenaar &ectx) == FAIL) 1782e859312eSBram Moolenaar goto on_error; 17838a7d6542SBram Moolenaar break; 17848a7d6542SBram Moolenaar 17858a7d6542SBram Moolenaar // call a builtin function 17868a7d6542SBram Moolenaar case ISN_BCALL: 17878a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 17888a7d6542SBram Moolenaar if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx, 17898a7d6542SBram Moolenaar iptr->isn_arg.bfunc.cbf_argcount, 17908a7d6542SBram Moolenaar &ectx) == FAIL) 1791d032f34aSBram Moolenaar goto on_error; 17928a7d6542SBram Moolenaar break; 17938a7d6542SBram Moolenaar 17948a7d6542SBram Moolenaar // call a funcref or partial 17958a7d6542SBram Moolenaar case ISN_PCALL: 17968a7d6542SBram Moolenaar { 17978a7d6542SBram Moolenaar cpfunc_T *pfunc = &iptr->isn_arg.pfunc; 17988a7d6542SBram Moolenaar int r; 17996f5b6dfbSBram Moolenaar typval_T partial_tv; 18008a7d6542SBram Moolenaar 18018a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 18028a7d6542SBram Moolenaar if (pfunc->cpf_top) 18038a7d6542SBram Moolenaar { 18048a7d6542SBram Moolenaar // funcref is above the arguments 18058a7d6542SBram Moolenaar tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1); 18068a7d6542SBram Moolenaar } 18078a7d6542SBram Moolenaar else 18088a7d6542SBram Moolenaar { 18098a7d6542SBram Moolenaar // Get the funcref from the stack. 18108a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 18116f5b6dfbSBram Moolenaar partial_tv = *STACK_TV_BOT(0); 18126f5b6dfbSBram Moolenaar tv = &partial_tv; 18138a7d6542SBram Moolenaar } 18148a7d6542SBram Moolenaar r = call_partial(tv, pfunc->cpf_argcount, &ectx); 18156f5b6dfbSBram Moolenaar if (tv == &partial_tv) 18166f5b6dfbSBram Moolenaar clear_tv(&partial_tv); 18178a7d6542SBram Moolenaar if (r == FAIL) 1818d032f34aSBram Moolenaar goto on_error; 1819bd5da371SBram Moolenaar } 1820bd5da371SBram Moolenaar break; 18218a7d6542SBram Moolenaar 1822bd5da371SBram Moolenaar case ISN_PCALL_END: 1823bd5da371SBram Moolenaar // PCALL finished, arguments have been consumed and replaced by 1824bd5da371SBram Moolenaar // the return value. Now clear the funcref from the stack, 1825bd5da371SBram Moolenaar // and move the return value in its place. 18268a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 1827bd5da371SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 18288a7d6542SBram Moolenaar *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); 18298a7d6542SBram Moolenaar break; 18308a7d6542SBram Moolenaar 18318a7d6542SBram Moolenaar // call a user defined function or funcref/partial 18328a7d6542SBram Moolenaar case ISN_UCALL: 18338a7d6542SBram Moolenaar { 18348a7d6542SBram Moolenaar cufunc_T *cufunc = &iptr->isn_arg.ufunc; 18358a7d6542SBram Moolenaar 18368a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 18378a7d6542SBram Moolenaar if (call_eval_func(cufunc->cuf_name, 18387eeefd4aSBram Moolenaar cufunc->cuf_argcount, &ectx, iptr) == FAIL) 1839d032f34aSBram Moolenaar goto on_error; 18408a7d6542SBram Moolenaar } 18418a7d6542SBram Moolenaar break; 18428a7d6542SBram Moolenaar 18438a7d6542SBram Moolenaar // return from a :def function call 18448a7d6542SBram Moolenaar case ISN_RETURN: 18458a7d6542SBram Moolenaar { 18468cbd6dfcSBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 184720431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 18488cbd6dfcSBram Moolenaar 18498cbd6dfcSBram Moolenaar if (trystack->ga_len > 0) 18508cbd6dfcSBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 18518cbd6dfcSBram Moolenaar + trystack->ga_len - 1; 1852bf67ea1aSBram Moolenaar if (trycmd != NULL 1853bf67ea1aSBram Moolenaar && trycmd->tcd_frame_idx == ectx.ec_frame_idx 18548a7d6542SBram Moolenaar && trycmd->tcd_finally_idx != 0) 18558a7d6542SBram Moolenaar { 18568a7d6542SBram Moolenaar // jump to ":finally" 18578a7d6542SBram Moolenaar ectx.ec_iidx = trycmd->tcd_finally_idx; 18588a7d6542SBram Moolenaar trycmd->tcd_return = TRUE; 18598a7d6542SBram Moolenaar } 18608a7d6542SBram Moolenaar else 1861d032f34aSBram Moolenaar goto func_return; 18628a7d6542SBram Moolenaar } 18638a7d6542SBram Moolenaar break; 18648a7d6542SBram Moolenaar 18658a7d6542SBram Moolenaar // push a function reference to a compiled function 18668a7d6542SBram Moolenaar case ISN_FUNCREF: 18678a7d6542SBram Moolenaar { 18688a7d6542SBram Moolenaar partial_T *pt = NULL; 1869bf67ea1aSBram Moolenaar dfunc_T *pt_dfunc; 18708a7d6542SBram Moolenaar 18718a7d6542SBram Moolenaar pt = ALLOC_CLEAR_ONE(partial_T); 18728a7d6542SBram Moolenaar if (pt == NULL) 18738a7d6542SBram Moolenaar goto failed; 1874270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 1875c8cd2b34SBram Moolenaar { 1876bf67ea1aSBram Moolenaar vim_free(pt); 1877bf67ea1aSBram Moolenaar goto failed; 1878bf67ea1aSBram Moolenaar } 1879bf67ea1aSBram Moolenaar pt_dfunc = ((dfunc_T *)def_functions.ga_data) 1880bf67ea1aSBram Moolenaar + iptr->isn_arg.funcref.fr_func; 1881bf67ea1aSBram Moolenaar pt->pt_func = pt_dfunc->df_ufunc; 1882bf67ea1aSBram Moolenaar pt->pt_refcount = 1; 1883bf67ea1aSBram Moolenaar 1884bf67ea1aSBram Moolenaar if (pt_dfunc->df_ufunc->uf_flags & FC_CLOSURE) 1885bf67ea1aSBram Moolenaar { 1886bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 1887bf67ea1aSBram Moolenaar + ectx.ec_dfunc_idx; 1888bf67ea1aSBram Moolenaar 1889bf67ea1aSBram Moolenaar // The closure needs to find arguments and local 1890bf67ea1aSBram Moolenaar // variables in the current stack. 1891f7779c63SBram Moolenaar pt->pt_ectx_stack = &ectx.ec_stack; 1892f7779c63SBram Moolenaar pt->pt_ectx_frame = ectx.ec_frame_idx; 1893bf67ea1aSBram Moolenaar 1894bf67ea1aSBram Moolenaar // If this function returns and the closure is still 1895148ce7aeSBram Moolenaar // being used, we need to make a copy of the context 1896bf67ea1aSBram Moolenaar // (arguments and local variables). Store a reference 1897bf67ea1aSBram Moolenaar // to the partial so we can handle that. 1898148ce7aeSBram Moolenaar if (ga_grow(&ectx.ec_funcrefs, 1) == FAIL) 1899bf67ea1aSBram Moolenaar { 1900dec07510SBram Moolenaar vim_free(pt); 1901bf67ea1aSBram Moolenaar goto failed; 1902bf67ea1aSBram Moolenaar } 1903148ce7aeSBram Moolenaar // Extra variable keeps the count of closures created 1904148ce7aeSBram Moolenaar // in the current function call. 1905148ce7aeSBram Moolenaar tv = STACK_TV_VAR(dfunc->df_varcount); 1906148ce7aeSBram Moolenaar ++tv->vval.v_number; 1907148ce7aeSBram Moolenaar 1908148ce7aeSBram Moolenaar ((partial_T **)ectx.ec_funcrefs.ga_data) 1909148ce7aeSBram Moolenaar [ectx.ec_funcrefs.ga_len] = pt; 1910148ce7aeSBram Moolenaar ++pt->pt_refcount; 1911148ce7aeSBram Moolenaar ++ectx.ec_funcrefs.ga_len; 1912c8cd2b34SBram Moolenaar } 1913148ce7aeSBram Moolenaar ++pt_dfunc->df_ufunc->uf_refcount; 1914c8cd2b34SBram Moolenaar 19158a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 19168a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 19178a7d6542SBram Moolenaar tv->vval.v_partial = pt; 19188a7d6542SBram Moolenaar tv->v_type = VAR_PARTIAL; 19192f8ce0aeSBram Moolenaar tv->v_lock = 0; 19208a7d6542SBram Moolenaar } 19218a7d6542SBram Moolenaar break; 19228a7d6542SBram Moolenaar 192338ddf333SBram Moolenaar // Create a global function from a lambda. 192438ddf333SBram Moolenaar case ISN_NEWFUNC: 192538ddf333SBram Moolenaar { 192638ddf333SBram Moolenaar newfunc_T *newfunc = &iptr->isn_arg.newfunc; 192738ddf333SBram Moolenaar 192838ddf333SBram Moolenaar copy_func(newfunc->nf_lambda, newfunc->nf_global); 192938ddf333SBram Moolenaar } 193038ddf333SBram Moolenaar break; 193138ddf333SBram Moolenaar 19328a7d6542SBram Moolenaar // jump if a condition is met 19338a7d6542SBram Moolenaar case ISN_JUMP: 19348a7d6542SBram Moolenaar { 19358a7d6542SBram Moolenaar jumpwhen_T when = iptr->isn_arg.jump.jump_when; 19362bb2658bSBram Moolenaar int error = FALSE; 19378a7d6542SBram Moolenaar int jump = TRUE; 19388a7d6542SBram Moolenaar 19398a7d6542SBram Moolenaar if (when != JUMP_ALWAYS) 19408a7d6542SBram Moolenaar { 19418a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 19422bb2658bSBram Moolenaar if (when == JUMP_IF_COND_FALSE 194313106605SBram Moolenaar || when == JUMP_IF_FALSE 19442bb2658bSBram Moolenaar || when == JUMP_IF_COND_TRUE) 19452bb2658bSBram Moolenaar { 19462bb2658bSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 19472bb2658bSBram Moolenaar jump = tv_get_bool_chk(tv, &error); 19482bb2658bSBram Moolenaar if (error) 19492bb2658bSBram Moolenaar goto on_error; 19502bb2658bSBram Moolenaar } 19512bb2658bSBram Moolenaar else 19528a7d6542SBram Moolenaar jump = tv2bool(tv); 19538a7d6542SBram Moolenaar if (when == JUMP_IF_FALSE 19542bb2658bSBram Moolenaar || when == JUMP_AND_KEEP_IF_FALSE 19552bb2658bSBram Moolenaar || when == JUMP_IF_COND_FALSE) 19568a7d6542SBram Moolenaar jump = !jump; 1957777770fbSBram Moolenaar if (when == JUMP_IF_FALSE || !jump) 19588a7d6542SBram Moolenaar { 19598a7d6542SBram Moolenaar // drop the value from the stack 19608a7d6542SBram Moolenaar clear_tv(tv); 19618a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 19628a7d6542SBram Moolenaar } 19638a7d6542SBram Moolenaar } 19648a7d6542SBram Moolenaar if (jump) 19658a7d6542SBram Moolenaar ectx.ec_iidx = iptr->isn_arg.jump.jump_where; 19668a7d6542SBram Moolenaar } 19678a7d6542SBram Moolenaar break; 19688a7d6542SBram Moolenaar 19698a7d6542SBram Moolenaar // top of a for loop 19708a7d6542SBram Moolenaar case ISN_FOR: 19718a7d6542SBram Moolenaar { 19728a7d6542SBram Moolenaar list_T *list = STACK_TV_BOT(-1)->vval.v_list; 19738a7d6542SBram Moolenaar typval_T *idxtv = 19748a7d6542SBram Moolenaar STACK_TV_VAR(iptr->isn_arg.forloop.for_idx); 19758a7d6542SBram Moolenaar 19768a7d6542SBram Moolenaar // push the next item from the list 1977270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 19788a7d6542SBram Moolenaar goto failed; 197977e5dcc3SBram Moolenaar ++idxtv->vval.v_number; 198077e5dcc3SBram Moolenaar if (list == NULL || idxtv->vval.v_number >= list->lv_len) 19818a7d6542SBram Moolenaar // past the end of the list, jump to "endfor" 19828a7d6542SBram Moolenaar ectx.ec_iidx = iptr->isn_arg.forloop.for_end; 19838a7d6542SBram Moolenaar else if (list->lv_first == &range_list_item) 19848a7d6542SBram Moolenaar { 19858a7d6542SBram Moolenaar // non-materialized range() list 19868a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 19878a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 19882f8ce0aeSBram Moolenaar tv->v_lock = 0; 19898a7d6542SBram Moolenaar tv->vval.v_number = list_find_nr( 19908a7d6542SBram Moolenaar list, idxtv->vval.v_number, NULL); 19918a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 19928a7d6542SBram Moolenaar } 19938a7d6542SBram Moolenaar else 19948a7d6542SBram Moolenaar { 19958a7d6542SBram Moolenaar listitem_T *li = list_find(list, idxtv->vval.v_number); 19968a7d6542SBram Moolenaar 19978a7d6542SBram Moolenaar copy_tv(&li->li_tv, STACK_TV_BOT(0)); 19988a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 19998a7d6542SBram Moolenaar } 20008a7d6542SBram Moolenaar } 20018a7d6542SBram Moolenaar break; 20028a7d6542SBram Moolenaar 20038a7d6542SBram Moolenaar // start of ":try" block 20048a7d6542SBram Moolenaar case ISN_TRY: 20058a7d6542SBram Moolenaar { 200620431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 200720431c9dSBram Moolenaar 2008270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_trystack, 1) == FAIL) 20098a7d6542SBram Moolenaar goto failed; 20108a7d6542SBram Moolenaar trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data) 20118a7d6542SBram Moolenaar + ectx.ec_trystack.ga_len; 20128a7d6542SBram Moolenaar ++ectx.ec_trystack.ga_len; 20138a7d6542SBram Moolenaar ++trylevel; 2014bf67ea1aSBram Moolenaar trycmd->tcd_frame_idx = ectx.ec_frame_idx; 20158a7d6542SBram Moolenaar trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch; 20168a7d6542SBram Moolenaar trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally; 2017f575adffSBram Moolenaar trycmd->tcd_caught = FALSE; 20189939f57bSBram Moolenaar trycmd->tcd_return = FALSE; 20198a7d6542SBram Moolenaar } 20208a7d6542SBram Moolenaar break; 20218a7d6542SBram Moolenaar 20228a7d6542SBram Moolenaar case ISN_PUSHEXC: 20238a7d6542SBram Moolenaar if (current_exception == NULL) 20248a7d6542SBram Moolenaar { 20257517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 20268a7d6542SBram Moolenaar iemsg("Evaluating catch while current_exception is NULL"); 20278a7d6542SBram Moolenaar goto failed; 20288a7d6542SBram Moolenaar } 2029270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 20308a7d6542SBram Moolenaar goto failed; 20318a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 20328a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 20338a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 20342f8ce0aeSBram Moolenaar tv->v_lock = 0; 20358a7d6542SBram Moolenaar tv->vval.v_string = vim_strsave( 20368a7d6542SBram Moolenaar (char_u *)current_exception->value); 20378a7d6542SBram Moolenaar break; 20388a7d6542SBram Moolenaar 20398a7d6542SBram Moolenaar case ISN_CATCH: 20408a7d6542SBram Moolenaar { 20418a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 20428a7d6542SBram Moolenaar 20438a7d6542SBram Moolenaar if (trystack->ga_len > 0) 20448a7d6542SBram Moolenaar { 204520431c9dSBram Moolenaar trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data) 20468a7d6542SBram Moolenaar + trystack->ga_len - 1; 20478a7d6542SBram Moolenaar trycmd->tcd_caught = TRUE; 20488a7d6542SBram Moolenaar } 20498a7d6542SBram Moolenaar did_emsg = got_int = did_throw = FALSE; 20508a7d6542SBram Moolenaar catch_exception(current_exception); 20518a7d6542SBram Moolenaar } 20528a7d6542SBram Moolenaar break; 20538a7d6542SBram Moolenaar 20548a7d6542SBram Moolenaar // end of ":try" block 20558a7d6542SBram Moolenaar case ISN_ENDTRY: 20568a7d6542SBram Moolenaar { 20578a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 20588a7d6542SBram Moolenaar 20598a7d6542SBram Moolenaar if (trystack->ga_len > 0) 20608a7d6542SBram Moolenaar { 206120431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 206220431c9dSBram Moolenaar 20638a7d6542SBram Moolenaar --trystack->ga_len; 20648a7d6542SBram Moolenaar --trylevel; 206568d130c6SBram Moolenaar ectx.ec_in_catch = FALSE; 20668a7d6542SBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 20678a7d6542SBram Moolenaar + trystack->ga_len; 2068f575adffSBram Moolenaar if (trycmd->tcd_caught && current_exception != NULL) 20698a7d6542SBram Moolenaar { 20708a7d6542SBram Moolenaar // discard the exception 20718a7d6542SBram Moolenaar if (caught_stack == current_exception) 20728a7d6542SBram Moolenaar caught_stack = caught_stack->caught; 20738a7d6542SBram Moolenaar discard_current_exception(); 20748a7d6542SBram Moolenaar } 20758a7d6542SBram Moolenaar 20768a7d6542SBram Moolenaar if (trycmd->tcd_return) 2077d032f34aSBram Moolenaar goto func_return; 20788a7d6542SBram Moolenaar } 20798a7d6542SBram Moolenaar } 20808a7d6542SBram Moolenaar break; 20818a7d6542SBram Moolenaar 20828a7d6542SBram Moolenaar case ISN_THROW: 20838a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 20848a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 20858a7d6542SBram Moolenaar if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL) 20868a7d6542SBram Moolenaar { 20878a7d6542SBram Moolenaar vim_free(tv->vval.v_string); 20888a7d6542SBram Moolenaar goto failed; 20898a7d6542SBram Moolenaar } 20908a7d6542SBram Moolenaar did_throw = TRUE; 20918a7d6542SBram Moolenaar break; 20928a7d6542SBram Moolenaar 20938a7d6542SBram Moolenaar // compare with special values 20948a7d6542SBram Moolenaar case ISN_COMPAREBOOL: 20958a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 20968a7d6542SBram Moolenaar { 20978a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 20988a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 20998a7d6542SBram Moolenaar varnumber_T arg1 = tv1->vval.v_number; 21008a7d6542SBram Moolenaar varnumber_T arg2 = tv2->vval.v_number; 21018a7d6542SBram Moolenaar int res; 21028a7d6542SBram Moolenaar 21038a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 21048a7d6542SBram Moolenaar { 21058a7d6542SBram Moolenaar case EXPR_EQUAL: res = arg1 == arg2; break; 21068a7d6542SBram Moolenaar case EXPR_NEQUAL: res = arg1 != arg2; break; 21078a7d6542SBram Moolenaar default: res = 0; break; 21088a7d6542SBram Moolenaar } 21098a7d6542SBram Moolenaar 21108a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 21118a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 21128a7d6542SBram Moolenaar tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; 21138a7d6542SBram Moolenaar } 21148a7d6542SBram Moolenaar break; 21158a7d6542SBram Moolenaar 21168a7d6542SBram Moolenaar // Operation with two number arguments 21178a7d6542SBram Moolenaar case ISN_OPNR: 21188a7d6542SBram Moolenaar case ISN_COMPARENR: 21198a7d6542SBram Moolenaar { 21208a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 21218a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 21228a7d6542SBram Moolenaar varnumber_T arg1 = tv1->vval.v_number; 21238a7d6542SBram Moolenaar varnumber_T arg2 = tv2->vval.v_number; 21248a7d6542SBram Moolenaar varnumber_T res; 21258a7d6542SBram Moolenaar 21268a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 21278a7d6542SBram Moolenaar { 21288a7d6542SBram Moolenaar case EXPR_MULT: res = arg1 * arg2; break; 21298a7d6542SBram Moolenaar case EXPR_DIV: res = arg1 / arg2; break; 21308a7d6542SBram Moolenaar case EXPR_REM: res = arg1 % arg2; break; 21318a7d6542SBram Moolenaar case EXPR_SUB: res = arg1 - arg2; break; 21328a7d6542SBram Moolenaar case EXPR_ADD: res = arg1 + arg2; break; 21338a7d6542SBram Moolenaar 21348a7d6542SBram Moolenaar case EXPR_EQUAL: res = arg1 == arg2; break; 21358a7d6542SBram Moolenaar case EXPR_NEQUAL: res = arg1 != arg2; break; 21368a7d6542SBram Moolenaar case EXPR_GREATER: res = arg1 > arg2; break; 21378a7d6542SBram Moolenaar case EXPR_GEQUAL: res = arg1 >= arg2; break; 21388a7d6542SBram Moolenaar case EXPR_SMALLER: res = arg1 < arg2; break; 21398a7d6542SBram Moolenaar case EXPR_SEQUAL: res = arg1 <= arg2; break; 21408a7d6542SBram Moolenaar default: res = 0; break; 21418a7d6542SBram Moolenaar } 21428a7d6542SBram Moolenaar 21438a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 21448a7d6542SBram Moolenaar if (iptr->isn_type == ISN_COMPARENR) 21458a7d6542SBram Moolenaar { 21468a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 21478a7d6542SBram Moolenaar tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; 21488a7d6542SBram Moolenaar } 21498a7d6542SBram Moolenaar else 21508a7d6542SBram Moolenaar tv1->vval.v_number = res; 21518a7d6542SBram Moolenaar } 21528a7d6542SBram Moolenaar break; 21538a7d6542SBram Moolenaar 21548a7d6542SBram Moolenaar // Computation with two float arguments 21558a7d6542SBram Moolenaar case ISN_OPFLOAT: 21568a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: 2157a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT 21588a7d6542SBram Moolenaar { 21598a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 21608a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 21618a7d6542SBram Moolenaar float_T arg1 = tv1->vval.v_float; 21628a7d6542SBram Moolenaar float_T arg2 = tv2->vval.v_float; 21638a7d6542SBram Moolenaar float_T res = 0; 21648a7d6542SBram Moolenaar int cmp = FALSE; 21658a7d6542SBram Moolenaar 21668a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 21678a7d6542SBram Moolenaar { 21688a7d6542SBram Moolenaar case EXPR_MULT: res = arg1 * arg2; break; 21698a7d6542SBram Moolenaar case EXPR_DIV: res = arg1 / arg2; break; 21708a7d6542SBram Moolenaar case EXPR_SUB: res = arg1 - arg2; break; 21718a7d6542SBram Moolenaar case EXPR_ADD: res = arg1 + arg2; break; 21728a7d6542SBram Moolenaar 21738a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = arg1 == arg2; break; 21748a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = arg1 != arg2; break; 21758a7d6542SBram Moolenaar case EXPR_GREATER: cmp = arg1 > arg2; break; 21768a7d6542SBram Moolenaar case EXPR_GEQUAL: cmp = arg1 >= arg2; break; 21778a7d6542SBram Moolenaar case EXPR_SMALLER: cmp = arg1 < arg2; break; 21788a7d6542SBram Moolenaar case EXPR_SEQUAL: cmp = arg1 <= arg2; break; 21798a7d6542SBram Moolenaar default: cmp = 0; break; 21808a7d6542SBram Moolenaar } 21818a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 21828a7d6542SBram Moolenaar if (iptr->isn_type == ISN_COMPAREFLOAT) 21838a7d6542SBram Moolenaar { 21848a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 21858a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 21868a7d6542SBram Moolenaar } 21878a7d6542SBram Moolenaar else 21888a7d6542SBram Moolenaar tv1->vval.v_float = res; 21898a7d6542SBram Moolenaar } 2190a5d5953dSBram Moolenaar #endif 21918a7d6542SBram Moolenaar break; 21928a7d6542SBram Moolenaar 21938a7d6542SBram Moolenaar case ISN_COMPARELIST: 21948a7d6542SBram Moolenaar { 21958a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 21968a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 21978a7d6542SBram Moolenaar list_T *arg1 = tv1->vval.v_list; 21988a7d6542SBram Moolenaar list_T *arg2 = tv2->vval.v_list; 21998a7d6542SBram Moolenaar int cmp = FALSE; 22008a7d6542SBram Moolenaar int ic = iptr->isn_arg.op.op_ic; 22018a7d6542SBram Moolenaar 22028a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 22038a7d6542SBram Moolenaar { 22048a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = 22058a7d6542SBram Moolenaar list_equal(arg1, arg2, ic, FALSE); break; 22068a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = 22078a7d6542SBram Moolenaar !list_equal(arg1, arg2, ic, FALSE); break; 22088a7d6542SBram Moolenaar case EXPR_IS: cmp = arg1 == arg2; break; 22098a7d6542SBram Moolenaar case EXPR_ISNOT: cmp = arg1 != arg2; break; 22108a7d6542SBram Moolenaar default: cmp = 0; break; 22118a7d6542SBram Moolenaar } 22128a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 22138a7d6542SBram Moolenaar clear_tv(tv1); 22148a7d6542SBram Moolenaar clear_tv(tv2); 22158a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 22168a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 22178a7d6542SBram Moolenaar } 22188a7d6542SBram Moolenaar break; 22198a7d6542SBram Moolenaar 22208a7d6542SBram Moolenaar case ISN_COMPAREBLOB: 22218a7d6542SBram Moolenaar { 22228a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 22238a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 22248a7d6542SBram Moolenaar blob_T *arg1 = tv1->vval.v_blob; 22258a7d6542SBram Moolenaar blob_T *arg2 = tv2->vval.v_blob; 22268a7d6542SBram Moolenaar int cmp = FALSE; 22278a7d6542SBram Moolenaar 22288a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 22298a7d6542SBram Moolenaar { 22308a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break; 22318a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break; 22328a7d6542SBram Moolenaar case EXPR_IS: cmp = arg1 == arg2; break; 22338a7d6542SBram Moolenaar case EXPR_ISNOT: cmp = arg1 != arg2; break; 22348a7d6542SBram Moolenaar default: cmp = 0; break; 22358a7d6542SBram Moolenaar } 22368a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 22378a7d6542SBram Moolenaar clear_tv(tv1); 22388a7d6542SBram Moolenaar clear_tv(tv2); 22398a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 22408a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 22418a7d6542SBram Moolenaar } 22428a7d6542SBram Moolenaar break; 22438a7d6542SBram Moolenaar 22448a7d6542SBram Moolenaar // TODO: handle separately 22458a7d6542SBram Moolenaar case ISN_COMPARESTRING: 22468a7d6542SBram Moolenaar case ISN_COMPAREDICT: 22478a7d6542SBram Moolenaar case ISN_COMPAREFUNC: 22488a7d6542SBram Moolenaar case ISN_COMPAREANY: 22498a7d6542SBram Moolenaar { 22508a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 22518a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 22528a7d6542SBram Moolenaar exptype_T exptype = iptr->isn_arg.op.op_type; 22538a7d6542SBram Moolenaar int ic = iptr->isn_arg.op.op_ic; 22548a7d6542SBram Moolenaar 2255eb26f433SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 22568a7d6542SBram Moolenaar typval_compare(tv1, tv2, exptype, ic); 22578a7d6542SBram Moolenaar clear_tv(tv2); 22588a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 22598a7d6542SBram Moolenaar } 22608a7d6542SBram Moolenaar break; 22618a7d6542SBram Moolenaar 22628a7d6542SBram Moolenaar case ISN_ADDLIST: 22638a7d6542SBram Moolenaar case ISN_ADDBLOB: 22648a7d6542SBram Moolenaar { 22658a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 22668a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 22678a7d6542SBram Moolenaar 22688a7d6542SBram Moolenaar if (iptr->isn_type == ISN_ADDLIST) 22698a7d6542SBram Moolenaar eval_addlist(tv1, tv2); 22708a7d6542SBram Moolenaar else 22718a7d6542SBram Moolenaar eval_addblob(tv1, tv2); 22728a7d6542SBram Moolenaar clear_tv(tv2); 22738a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 22748a7d6542SBram Moolenaar } 22758a7d6542SBram Moolenaar break; 22768a7d6542SBram Moolenaar 22778a7d6542SBram Moolenaar // Computation with two arguments of unknown type 22788a7d6542SBram Moolenaar case ISN_OPANY: 22798a7d6542SBram Moolenaar { 22808a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 22818a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 22828a7d6542SBram Moolenaar varnumber_T n1, n2; 22838a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 22848a7d6542SBram Moolenaar float_T f1 = 0, f2 = 0; 22858a7d6542SBram Moolenaar #endif 22868a7d6542SBram Moolenaar int error = FALSE; 22878a7d6542SBram Moolenaar 22888a7d6542SBram Moolenaar if (iptr->isn_arg.op.op_type == EXPR_ADD) 22898a7d6542SBram Moolenaar { 22908a7d6542SBram Moolenaar if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST) 22918a7d6542SBram Moolenaar { 22928a7d6542SBram Moolenaar eval_addlist(tv1, tv2); 22938a7d6542SBram Moolenaar clear_tv(tv2); 22948a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 22958a7d6542SBram Moolenaar break; 22968a7d6542SBram Moolenaar } 22978a7d6542SBram Moolenaar else if (tv1->v_type == VAR_BLOB 22988a7d6542SBram Moolenaar && tv2->v_type == VAR_BLOB) 22998a7d6542SBram Moolenaar { 23008a7d6542SBram Moolenaar eval_addblob(tv1, tv2); 23018a7d6542SBram Moolenaar clear_tv(tv2); 23028a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 23038a7d6542SBram Moolenaar break; 23048a7d6542SBram Moolenaar } 23058a7d6542SBram Moolenaar } 23068a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 23078a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT) 23088a7d6542SBram Moolenaar { 23098a7d6542SBram Moolenaar f1 = tv1->vval.v_float; 23108a7d6542SBram Moolenaar n1 = 0; 23118a7d6542SBram Moolenaar } 23128a7d6542SBram Moolenaar else 23138a7d6542SBram Moolenaar #endif 23148a7d6542SBram Moolenaar { 23158a7d6542SBram Moolenaar n1 = tv_get_number_chk(tv1, &error); 23168a7d6542SBram Moolenaar if (error) 2317d032f34aSBram Moolenaar goto on_error; 23188a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 23198a7d6542SBram Moolenaar if (tv2->v_type == VAR_FLOAT) 23208a7d6542SBram Moolenaar f1 = n1; 23218a7d6542SBram Moolenaar #endif 23228a7d6542SBram Moolenaar } 23238a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 23248a7d6542SBram Moolenaar if (tv2->v_type == VAR_FLOAT) 23258a7d6542SBram Moolenaar { 23268a7d6542SBram Moolenaar f2 = tv2->vval.v_float; 23278a7d6542SBram Moolenaar n2 = 0; 23288a7d6542SBram Moolenaar } 23298a7d6542SBram Moolenaar else 23308a7d6542SBram Moolenaar #endif 23318a7d6542SBram Moolenaar { 23328a7d6542SBram Moolenaar n2 = tv_get_number_chk(tv2, &error); 23338a7d6542SBram Moolenaar if (error) 2334d032f34aSBram Moolenaar goto on_error; 23358a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 23368a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT) 23378a7d6542SBram Moolenaar f2 = n2; 23388a7d6542SBram Moolenaar #endif 23398a7d6542SBram Moolenaar } 23408a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 23418a7d6542SBram Moolenaar // if there is a float on either side the result is a float 23428a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT) 23438a7d6542SBram Moolenaar { 23448a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 23458a7d6542SBram Moolenaar { 23468a7d6542SBram Moolenaar case EXPR_MULT: f1 = f1 * f2; break; 23478a7d6542SBram Moolenaar case EXPR_DIV: f1 = f1 / f2; break; 23488a7d6542SBram Moolenaar case EXPR_SUB: f1 = f1 - f2; break; 23498a7d6542SBram Moolenaar case EXPR_ADD: f1 = f1 + f2; break; 23507517ffdbSBram Moolenaar default: SOURCING_LNUM = iptr->isn_lnum; 23517517ffdbSBram Moolenaar emsg(_(e_modulus)); 2352f0b9f43cSBram Moolenaar goto on_error; 23538a7d6542SBram Moolenaar } 23548a7d6542SBram Moolenaar clear_tv(tv1); 23558a7d6542SBram Moolenaar clear_tv(tv2); 23568a7d6542SBram Moolenaar tv1->v_type = VAR_FLOAT; 23578a7d6542SBram Moolenaar tv1->vval.v_float = f1; 23588a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 23598a7d6542SBram Moolenaar } 23608a7d6542SBram Moolenaar else 23618a7d6542SBram Moolenaar #endif 23628a7d6542SBram Moolenaar { 23638a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 23648a7d6542SBram Moolenaar { 23658a7d6542SBram Moolenaar case EXPR_MULT: n1 = n1 * n2; break; 23668a7d6542SBram Moolenaar case EXPR_DIV: n1 = num_divide(n1, n2); break; 23678a7d6542SBram Moolenaar case EXPR_SUB: n1 = n1 - n2; break; 23688a7d6542SBram Moolenaar case EXPR_ADD: n1 = n1 + n2; break; 23698a7d6542SBram Moolenaar default: n1 = num_modulus(n1, n2); break; 23708a7d6542SBram Moolenaar } 23718a7d6542SBram Moolenaar clear_tv(tv1); 23728a7d6542SBram Moolenaar clear_tv(tv2); 23738a7d6542SBram Moolenaar tv1->v_type = VAR_NUMBER; 23748a7d6542SBram Moolenaar tv1->vval.v_number = n1; 23758a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 23768a7d6542SBram Moolenaar } 23778a7d6542SBram Moolenaar } 23788a7d6542SBram Moolenaar break; 23798a7d6542SBram Moolenaar 23808a7d6542SBram Moolenaar case ISN_CONCAT: 23818a7d6542SBram Moolenaar { 23828a7d6542SBram Moolenaar char_u *str1 = STACK_TV_BOT(-2)->vval.v_string; 23838a7d6542SBram Moolenaar char_u *str2 = STACK_TV_BOT(-1)->vval.v_string; 23848a7d6542SBram Moolenaar char_u *res; 23858a7d6542SBram Moolenaar 23868a7d6542SBram Moolenaar res = concat_str(str1, str2); 23878a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(-2)); 23888a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 23898a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 23908a7d6542SBram Moolenaar STACK_TV_BOT(-1)->vval.v_string = res; 23918a7d6542SBram Moolenaar } 23928a7d6542SBram Moolenaar break; 23938a7d6542SBram Moolenaar 2394bf9d8c37SBram Moolenaar case ISN_STRINDEX: 239511107babSBram Moolenaar case ISN_STRSLICE: 2396bf9d8c37SBram Moolenaar { 239711107babSBram Moolenaar int is_slice = iptr->isn_type == ISN_STRSLICE; 239811107babSBram Moolenaar varnumber_T n1 = 0, n2; 2399bf9d8c37SBram Moolenaar char_u *res; 2400bf9d8c37SBram Moolenaar 2401bf9d8c37SBram Moolenaar // string index: string is at stack-2, index at stack-1 240211107babSBram Moolenaar // string slice: string is at stack-3, first index at 240311107babSBram Moolenaar // stack-2, second index at stack-1 240411107babSBram Moolenaar if (is_slice) 240511107babSBram Moolenaar { 240611107babSBram Moolenaar tv = STACK_TV_BOT(-2); 240711107babSBram Moolenaar n1 = tv->vval.v_number; 240811107babSBram Moolenaar } 240911107babSBram Moolenaar 2410bf9d8c37SBram Moolenaar tv = STACK_TV_BOT(-1); 241111107babSBram Moolenaar n2 = tv->vval.v_number; 2412bf9d8c37SBram Moolenaar 241311107babSBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 2414bf9d8c37SBram Moolenaar tv = STACK_TV_BOT(-1); 241511107babSBram Moolenaar if (is_slice) 241611107babSBram Moolenaar // Slice: Select the characters from the string 241711107babSBram Moolenaar res = string_slice(tv->vval.v_string, n1, n2); 241811107babSBram Moolenaar else 241911107babSBram Moolenaar // Index: The resulting variable is a string of a 242011107babSBram Moolenaar // single character. If the index is too big or 242111107babSBram Moolenaar // negative the result is empty. 242211107babSBram Moolenaar res = char_from_string(tv->vval.v_string, n2); 2423bf9d8c37SBram Moolenaar vim_free(tv->vval.v_string); 2424bf9d8c37SBram Moolenaar tv->vval.v_string = res; 2425bf9d8c37SBram Moolenaar } 2426bf9d8c37SBram Moolenaar break; 2427bf9d8c37SBram Moolenaar 2428bf9d8c37SBram Moolenaar case ISN_LISTINDEX: 2429ed591877SBram Moolenaar case ISN_LISTSLICE: 24308a7d6542SBram Moolenaar { 2431ed591877SBram Moolenaar int is_slice = iptr->isn_type == ISN_LISTSLICE; 24328a7d6542SBram Moolenaar list_T *list; 2433ed591877SBram Moolenaar varnumber_T n1, n2; 24348a7d6542SBram Moolenaar 24358a7d6542SBram Moolenaar // list index: list is at stack-2, index at stack-1 2436ed591877SBram Moolenaar // list slice: list is at stack-3, indexes at stack-2 and 2437ed591877SBram Moolenaar // stack-1 2438ed591877SBram Moolenaar tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); 24398a7d6542SBram Moolenaar list = tv->vval.v_list; 24408a7d6542SBram Moolenaar 24418a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 2442ed591877SBram Moolenaar n1 = n2 = tv->vval.v_number; 24438a7d6542SBram Moolenaar clear_tv(tv); 2444ed591877SBram Moolenaar 2445ed591877SBram Moolenaar if (is_slice) 2446ed591877SBram Moolenaar { 2447ed591877SBram Moolenaar tv = STACK_TV_BOT(-2); 2448ed591877SBram Moolenaar n1 = tv->vval.v_number; 2449ed591877SBram Moolenaar clear_tv(tv); 2450ed591877SBram Moolenaar } 2451ed591877SBram Moolenaar 2452ed591877SBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 2453435d8978SBram Moolenaar tv = STACK_TV_BOT(-1); 24541d634542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2455ed591877SBram Moolenaar if (list_slice_or_index(list, is_slice, n1, n2, tv, TRUE) 2456ed591877SBram Moolenaar == FAIL) 2457ed591877SBram Moolenaar goto on_error; 24588a7d6542SBram Moolenaar } 24598a7d6542SBram Moolenaar break; 24608a7d6542SBram Moolenaar 2461cc673e74SBram Moolenaar case ISN_ANYINDEX: 2462cc673e74SBram Moolenaar case ISN_ANYSLICE: 2463cc673e74SBram Moolenaar { 2464cc673e74SBram Moolenaar int is_slice = iptr->isn_type == ISN_ANYSLICE; 2465cc673e74SBram Moolenaar typval_T *var1, *var2; 2466cc673e74SBram Moolenaar int res; 2467cc673e74SBram Moolenaar 2468cc673e74SBram Moolenaar // index: composite is at stack-2, index at stack-1 2469cc673e74SBram Moolenaar // slice: composite is at stack-3, indexes at stack-2 and 2470cc673e74SBram Moolenaar // stack-1 2471cc673e74SBram Moolenaar tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); 24723affe7a6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2473cc673e74SBram Moolenaar if (check_can_index(tv, TRUE, TRUE) == FAIL) 2474cc673e74SBram Moolenaar goto on_error; 2475cc673e74SBram Moolenaar var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1); 2476cc673e74SBram Moolenaar var2 = is_slice ? STACK_TV_BOT(-1) : NULL; 2477cc673e74SBram Moolenaar res = eval_index_inner(tv, is_slice, 2478cc673e74SBram Moolenaar var1, var2, NULL, -1, TRUE); 2479cc673e74SBram Moolenaar clear_tv(var1); 2480cc673e74SBram Moolenaar if (is_slice) 2481cc673e74SBram Moolenaar clear_tv(var2); 2482cc673e74SBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 2483cc673e74SBram Moolenaar if (res == FAIL) 2484cc673e74SBram Moolenaar goto on_error; 2485cc673e74SBram Moolenaar } 2486cc673e74SBram Moolenaar break; 2487cc673e74SBram Moolenaar 24889af78769SBram Moolenaar case ISN_SLICE: 24899af78769SBram Moolenaar { 24909af78769SBram Moolenaar list_T *list; 24919af78769SBram Moolenaar int count = iptr->isn_arg.number; 24929af78769SBram Moolenaar 2493c5b1c20bSBram Moolenaar // type will have been checked to be a list 24949af78769SBram Moolenaar tv = STACK_TV_BOT(-1); 24959af78769SBram Moolenaar list = tv->vval.v_list; 24969af78769SBram Moolenaar 24979af78769SBram Moolenaar // no error for short list, expect it to be checked earlier 24989af78769SBram Moolenaar if (list != NULL && list->lv_len >= count) 24999af78769SBram Moolenaar { 25009af78769SBram Moolenaar list_T *newlist = list_slice(list, 25019af78769SBram Moolenaar count, list->lv_len - 1); 25029af78769SBram Moolenaar 25039af78769SBram Moolenaar if (newlist != NULL) 25049af78769SBram Moolenaar { 25059af78769SBram Moolenaar list_unref(list); 25069af78769SBram Moolenaar tv->vval.v_list = newlist; 25079af78769SBram Moolenaar ++newlist->lv_refcount; 25089af78769SBram Moolenaar } 25099af78769SBram Moolenaar } 25109af78769SBram Moolenaar } 25119af78769SBram Moolenaar break; 25129af78769SBram Moolenaar 251347a519a9SBram Moolenaar case ISN_GETITEM: 251447a519a9SBram Moolenaar { 251547a519a9SBram Moolenaar listitem_T *li; 251647a519a9SBram Moolenaar int index = iptr->isn_arg.number; 251747a519a9SBram Moolenaar 2518c785b9a7SBram Moolenaar // Get list item: list is at stack-1, push item. 2519c785b9a7SBram Moolenaar // List type and length is checked for when compiling. 252047a519a9SBram Moolenaar tv = STACK_TV_BOT(-1); 2521c785b9a7SBram Moolenaar li = list_find(tv->vval.v_list, index); 252247a519a9SBram Moolenaar 252347a519a9SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 252447a519a9SBram Moolenaar goto failed; 252547a519a9SBram Moolenaar ++ectx.ec_stack.ga_len; 252647a519a9SBram Moolenaar copy_tv(&li->li_tv, STACK_TV_BOT(-1)); 252747a519a9SBram Moolenaar } 252847a519a9SBram Moolenaar break; 252947a519a9SBram Moolenaar 25308a7d6542SBram Moolenaar case ISN_MEMBER: 25318a7d6542SBram Moolenaar { 25328a7d6542SBram Moolenaar dict_T *dict; 25331cc2a94fSBram Moolenaar char_u *key; 25341cc2a94fSBram Moolenaar dictitem_T *di; 253550788ef3SBram Moolenaar typval_T temp_tv; 25361cc2a94fSBram Moolenaar 25371cc2a94fSBram Moolenaar // dict member: dict is at stack-2, key at stack-1 25381cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-2); 25394dac32caSBram Moolenaar // no need to check for VAR_DICT, CHECKTYPE will check. 25401cc2a94fSBram Moolenaar dict = tv->vval.v_dict; 25411cc2a94fSBram Moolenaar 25421cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-1); 25434dac32caSBram Moolenaar // no need to check for VAR_STRING, 2STRING will check. 25441cc2a94fSBram Moolenaar key = tv->vval.v_string; 25454dac32caSBram Moolenaar 25461cc2a94fSBram Moolenaar if ((di = dict_find(dict, key, -1)) == NULL) 25471cc2a94fSBram Moolenaar { 25487517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 25491cc2a94fSBram Moolenaar semsg(_(e_dictkey), key); 2550f0b9f43cSBram Moolenaar goto on_error; 25511cc2a94fSBram Moolenaar } 25521cc2a94fSBram Moolenaar clear_tv(tv); 255350788ef3SBram Moolenaar --ectx.ec_stack.ga_len; 255450788ef3SBram Moolenaar // Clear the dict after getting the item, to avoid that it 255550788ef3SBram Moolenaar // make the item invalid. 255650788ef3SBram Moolenaar tv = STACK_TV_BOT(-1); 255750788ef3SBram Moolenaar temp_tv = *tv; 255850788ef3SBram Moolenaar copy_tv(&di->di_tv, tv); 255950788ef3SBram Moolenaar clear_tv(&temp_tv); 25601cc2a94fSBram Moolenaar } 25611cc2a94fSBram Moolenaar break; 25621cc2a94fSBram Moolenaar 25631cc2a94fSBram Moolenaar // dict member with string key 25641cc2a94fSBram Moolenaar case ISN_STRINGMEMBER: 25651cc2a94fSBram Moolenaar { 25661cc2a94fSBram Moolenaar dict_T *dict; 25678a7d6542SBram Moolenaar dictitem_T *di; 2568fb9d5c51SBram Moolenaar typval_T temp_tv; 25698a7d6542SBram Moolenaar 25708a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 25718a7d6542SBram Moolenaar if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) 25728a7d6542SBram Moolenaar { 25737517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 25748a7d6542SBram Moolenaar emsg(_(e_dictreq)); 2575d032f34aSBram Moolenaar goto on_error; 25768a7d6542SBram Moolenaar } 25778a7d6542SBram Moolenaar dict = tv->vval.v_dict; 25788a7d6542SBram Moolenaar 25798a7d6542SBram Moolenaar if ((di = dict_find(dict, iptr->isn_arg.string, -1)) 25808a7d6542SBram Moolenaar == NULL) 25818a7d6542SBram Moolenaar { 25827517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 25838a7d6542SBram Moolenaar semsg(_(e_dictkey), iptr->isn_arg.string); 2584d032f34aSBram Moolenaar goto on_error; 25858a7d6542SBram Moolenaar } 2586fb9d5c51SBram Moolenaar // Clear the dict after getting the item, to avoid that it 2587fb9d5c51SBram Moolenaar // make the item invalid. 2588fb9d5c51SBram Moolenaar temp_tv = *tv; 25898a7d6542SBram Moolenaar copy_tv(&di->di_tv, tv); 2590fb9d5c51SBram Moolenaar clear_tv(&temp_tv); 25918a7d6542SBram Moolenaar } 25928a7d6542SBram Moolenaar break; 25938a7d6542SBram Moolenaar 25948a7d6542SBram Moolenaar case ISN_NEGATENR: 25958a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 2596c58164c5SBram Moolenaar if (tv->v_type != VAR_NUMBER 2597c58164c5SBram Moolenaar #ifdef FEAT_FLOAT 2598c58164c5SBram Moolenaar && tv->v_type != VAR_FLOAT 2599c58164c5SBram Moolenaar #endif 2600c58164c5SBram Moolenaar ) 2601c58164c5SBram Moolenaar { 26027517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2603c58164c5SBram Moolenaar emsg(_(e_number_exp)); 2604f0b9f43cSBram Moolenaar goto on_error; 2605c58164c5SBram Moolenaar } 2606c58164c5SBram Moolenaar #ifdef FEAT_FLOAT 2607c58164c5SBram Moolenaar if (tv->v_type == VAR_FLOAT) 2608c58164c5SBram Moolenaar tv->vval.v_float = -tv->vval.v_float; 2609c58164c5SBram Moolenaar else 2610c58164c5SBram Moolenaar #endif 26118a7d6542SBram Moolenaar tv->vval.v_number = -tv->vval.v_number; 26128a7d6542SBram Moolenaar break; 26138a7d6542SBram Moolenaar 26148a7d6542SBram Moolenaar case ISN_CHECKNR: 26158a7d6542SBram Moolenaar { 26168a7d6542SBram Moolenaar int error = FALSE; 26178a7d6542SBram Moolenaar 26188a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 26193affe7a6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 26208a7d6542SBram Moolenaar if (check_not_string(tv) == FAIL) 2621f0b9f43cSBram Moolenaar goto on_error; 26228a7d6542SBram Moolenaar (void)tv_get_number_chk(tv, &error); 26238a7d6542SBram Moolenaar if (error) 2624f0b9f43cSBram Moolenaar goto on_error; 26258a7d6542SBram Moolenaar } 26268a7d6542SBram Moolenaar break; 26278a7d6542SBram Moolenaar 26288a7d6542SBram Moolenaar case ISN_CHECKTYPE: 26298a7d6542SBram Moolenaar { 26308a7d6542SBram Moolenaar checktype_T *ct = &iptr->isn_arg.type; 26318a7d6542SBram Moolenaar 26328a7d6542SBram Moolenaar tv = STACK_TV_BOT(ct->ct_off); 26335e654230SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 26345e654230SBram Moolenaar if (check_typval_type(ct->ct_type, tv, 0) == FAIL) 26355e654230SBram Moolenaar goto on_error; 26365e654230SBram Moolenaar 26375e654230SBram Moolenaar // number 0 is FALSE, number 1 is TRUE 26385e654230SBram Moolenaar if (tv->v_type == VAR_NUMBER 26395e654230SBram Moolenaar && ct->ct_type->tt_type == VAR_BOOL 2640dadaddd5SBram Moolenaar && (tv->vval.v_number == 0 2641dadaddd5SBram Moolenaar || tv->vval.v_number == 1)) 2642dadaddd5SBram Moolenaar { 2643dadaddd5SBram Moolenaar tv->v_type = VAR_BOOL; 2644dadaddd5SBram Moolenaar tv->vval.v_number = tv->vval.v_number 2645dadaddd5SBram Moolenaar ? VVAL_TRUE : VVAL_FALSE; 2646dadaddd5SBram Moolenaar } 2647dadaddd5SBram Moolenaar } 26488a7d6542SBram Moolenaar break; 26498a7d6542SBram Moolenaar 26509af78769SBram Moolenaar case ISN_CHECKLEN: 26519af78769SBram Moolenaar { 26529af78769SBram Moolenaar int min_len = iptr->isn_arg.checklen.cl_min_len; 26539af78769SBram Moolenaar list_T *list = NULL; 26549af78769SBram Moolenaar 26559af78769SBram Moolenaar tv = STACK_TV_BOT(-1); 26569af78769SBram Moolenaar if (tv->v_type == VAR_LIST) 26579af78769SBram Moolenaar list = tv->vval.v_list; 26589af78769SBram Moolenaar if (list == NULL || list->lv_len < min_len 26599af78769SBram Moolenaar || (list->lv_len > min_len 26609af78769SBram Moolenaar && !iptr->isn_arg.checklen.cl_more_OK)) 26619af78769SBram Moolenaar { 26627517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2663451c2e35SBram Moolenaar semsg(_(e_expected_nr_items_but_got_nr), 26649af78769SBram Moolenaar min_len, list == NULL ? 0 : list->lv_len); 2665f0b9f43cSBram Moolenaar goto on_error; 26669af78769SBram Moolenaar } 26679af78769SBram Moolenaar } 26689af78769SBram Moolenaar break; 26699af78769SBram Moolenaar 26708a7d6542SBram Moolenaar case ISN_2BOOL: 26712bb2658bSBram Moolenaar case ISN_COND2BOOL: 26728a7d6542SBram Moolenaar { 26738a7d6542SBram Moolenaar int n; 26742bb2658bSBram Moolenaar int error = FALSE; 26758a7d6542SBram Moolenaar 26768a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 26772bb2658bSBram Moolenaar if (iptr->isn_type == ISN_2BOOL) 26782bb2658bSBram Moolenaar { 26798a7d6542SBram Moolenaar n = tv2bool(tv); 26808a7d6542SBram Moolenaar if (iptr->isn_arg.number) // invert 26818a7d6542SBram Moolenaar n = !n; 26822bb2658bSBram Moolenaar } 26832bb2658bSBram Moolenaar else 26842bb2658bSBram Moolenaar { 26852bb2658bSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 26862bb2658bSBram Moolenaar n = tv_get_bool_chk(tv, &error); 26872bb2658bSBram Moolenaar if (error) 26882bb2658bSBram Moolenaar goto on_error; 26892bb2658bSBram Moolenaar } 26908a7d6542SBram Moolenaar clear_tv(tv); 26918a7d6542SBram Moolenaar tv->v_type = VAR_BOOL; 26928a7d6542SBram Moolenaar tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE; 26938a7d6542SBram Moolenaar } 26948a7d6542SBram Moolenaar break; 26958a7d6542SBram Moolenaar 26968a7d6542SBram Moolenaar case ISN_2STRING: 2697418f1df5SBram Moolenaar case ISN_2STRING_ANY: 26988a7d6542SBram Moolenaar { 26998a7d6542SBram Moolenaar char_u *str; 27008a7d6542SBram Moolenaar 27018a7d6542SBram Moolenaar tv = STACK_TV_BOT(iptr->isn_arg.number); 27028a7d6542SBram Moolenaar if (tv->v_type != VAR_STRING) 27038a7d6542SBram Moolenaar { 2704418f1df5SBram Moolenaar if (iptr->isn_type == ISN_2STRING_ANY) 2705418f1df5SBram Moolenaar { 2706418f1df5SBram Moolenaar switch (tv->v_type) 2707418f1df5SBram Moolenaar { 2708418f1df5SBram Moolenaar case VAR_SPECIAL: 2709418f1df5SBram Moolenaar case VAR_BOOL: 2710418f1df5SBram Moolenaar case VAR_NUMBER: 2711418f1df5SBram Moolenaar case VAR_FLOAT: 2712418f1df5SBram Moolenaar case VAR_BLOB: break; 2713418f1df5SBram Moolenaar default: to_string_error(tv->v_type); 2714418f1df5SBram Moolenaar goto on_error; 2715418f1df5SBram Moolenaar } 2716418f1df5SBram Moolenaar } 27178a7d6542SBram Moolenaar str = typval_tostring(tv); 27188a7d6542SBram Moolenaar clear_tv(tv); 27198a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 27208a7d6542SBram Moolenaar tv->vval.v_string = str; 27218a7d6542SBram Moolenaar } 27228a7d6542SBram Moolenaar } 27238a7d6542SBram Moolenaar break; 27248a7d6542SBram Moolenaar 2725c3516f7eSBram Moolenaar case ISN_PUT: 2726c3516f7eSBram Moolenaar { 2727c3516f7eSBram Moolenaar int regname = iptr->isn_arg.put.put_regname; 2728c3516f7eSBram Moolenaar linenr_T lnum = iptr->isn_arg.put.put_lnum; 2729c3516f7eSBram Moolenaar char_u *expr = NULL; 2730c3516f7eSBram Moolenaar int dir = FORWARD; 2731c3516f7eSBram Moolenaar 2732c3516f7eSBram Moolenaar if (regname == '=') 2733c3516f7eSBram Moolenaar { 2734c3516f7eSBram Moolenaar tv = STACK_TV_BOT(-1); 2735c3516f7eSBram Moolenaar if (tv->v_type == VAR_STRING) 2736c3516f7eSBram Moolenaar expr = tv->vval.v_string; 2737c3516f7eSBram Moolenaar else 2738c3516f7eSBram Moolenaar { 2739c3516f7eSBram Moolenaar expr = typval_tostring(tv); // allocates value 2740c3516f7eSBram Moolenaar clear_tv(tv); 2741c3516f7eSBram Moolenaar } 2742c3516f7eSBram Moolenaar --ectx.ec_stack.ga_len; 2743c3516f7eSBram Moolenaar } 2744c3516f7eSBram Moolenaar if (lnum == -2) 2745c3516f7eSBram Moolenaar // :put! above cursor 2746c3516f7eSBram Moolenaar dir = BACKWARD; 2747c3516f7eSBram Moolenaar else if (lnum >= 0) 2748c3516f7eSBram Moolenaar curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum; 2749c3516f7eSBram Moolenaar check_cursor(); 2750c3516f7eSBram Moolenaar do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE); 2751c3516f7eSBram Moolenaar vim_free(expr); 2752c3516f7eSBram Moolenaar } 2753c3516f7eSBram Moolenaar break; 2754c3516f7eSBram Moolenaar 2755389df259SBram Moolenaar case ISN_SHUFFLE: 2756389df259SBram Moolenaar { 2757389df259SBram Moolenaar typval_T tmp_tv; 2758389df259SBram Moolenaar int item = iptr->isn_arg.shuffle.shfl_item; 2759389df259SBram Moolenaar int up = iptr->isn_arg.shuffle.shfl_up; 2760389df259SBram Moolenaar 2761389df259SBram Moolenaar tmp_tv = *STACK_TV_BOT(-item); 2762389df259SBram Moolenaar for ( ; up > 0 && item > 1; --up) 2763389df259SBram Moolenaar { 2764389df259SBram Moolenaar *STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1); 2765389df259SBram Moolenaar --item; 2766389df259SBram Moolenaar } 2767389df259SBram Moolenaar *STACK_TV_BOT(-item) = tmp_tv; 2768389df259SBram Moolenaar } 2769389df259SBram Moolenaar break; 2770389df259SBram Moolenaar 27718a7d6542SBram Moolenaar case ISN_DROP: 27728a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 27738a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(0)); 27748a7d6542SBram Moolenaar break; 27758a7d6542SBram Moolenaar } 2776f0b9f43cSBram Moolenaar continue; 2777f0b9f43cSBram Moolenaar 2778d032f34aSBram Moolenaar func_return: 27797cbfaa51SBram Moolenaar // Restore previous function. If the frame pointer is where we started 27807cbfaa51SBram Moolenaar // then there is none and we are done. 2781d032f34aSBram Moolenaar if (ectx.ec_frame_idx == initial_frame_idx) 2782d032f34aSBram Moolenaar goto done; 27837cbfaa51SBram Moolenaar 2784d032f34aSBram Moolenaar if (func_return(&ectx) == FAIL) 2785d032f34aSBram Moolenaar // only fails when out of memory 2786d032f34aSBram Moolenaar goto failed; 2787c7db5778SBram Moolenaar continue; 2788d032f34aSBram Moolenaar 2789f0b9f43cSBram Moolenaar on_error: 2790f0b9f43cSBram Moolenaar if (trylevel == 0) 2791f0b9f43cSBram Moolenaar goto failed; 27928a7d6542SBram Moolenaar } 27938a7d6542SBram Moolenaar 27948a7d6542SBram Moolenaar done: 27958a7d6542SBram Moolenaar // function finished, get result from the stack. 27968a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 27978a7d6542SBram Moolenaar *rettv = *tv; 27988a7d6542SBram Moolenaar tv->v_type = VAR_UNKNOWN; 27998a7d6542SBram Moolenaar ret = OK; 28008a7d6542SBram Moolenaar 28018a7d6542SBram Moolenaar failed: 28027eeefd4aSBram Moolenaar // When failed need to unwind the call stack. 2803bf67ea1aSBram Moolenaar while (ectx.ec_frame_idx != initial_frame_idx) 28047eeefd4aSBram Moolenaar func_return(&ectx); 2805bf67ea1aSBram Moolenaar 2806c70bdab0SBram Moolenaar // Deal with any remaining closures, they may be in use somewhere. 2807c70bdab0SBram Moolenaar if (ectx.ec_funcrefs.ga_len > 0) 2808c70bdab0SBram Moolenaar handle_closure_in_use(&ectx, FALSE); 2809c70bdab0SBram Moolenaar 2810ee8580e5SBram Moolenaar estack_pop(); 2811ee8580e5SBram Moolenaar current_sctx = save_current_sctx; 2812ee8580e5SBram Moolenaar 2813ee8580e5SBram Moolenaar failed_early: 2814bf67ea1aSBram Moolenaar // Free all local variables, but not arguments. 28158a7d6542SBram Moolenaar for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx) 28168a7d6542SBram Moolenaar clear_tv(STACK_TV(idx)); 2817bf67ea1aSBram Moolenaar 28188a7d6542SBram Moolenaar vim_free(ectx.ec_stack.ga_data); 281920431c9dSBram Moolenaar vim_free(ectx.ec_trystack.ga_data); 2820682d0a15SBram Moolenaar 282177e5dcc3SBram Moolenaar // Not sure if this is necessary. 282277e5dcc3SBram Moolenaar suppress_errthrow = save_suppress_errthrow; 282377e5dcc3SBram Moolenaar 2824682d0a15SBram Moolenaar if (ret != OK && called_emsg == called_emsg_before) 2825451c2e35SBram Moolenaar semsg(_(e_unknown_error_while_executing_str), 2826682d0a15SBram Moolenaar printable_func_name(ufunc)); 28278a7d6542SBram Moolenaar return ret; 28288a7d6542SBram Moolenaar } 28298a7d6542SBram Moolenaar 28308a7d6542SBram Moolenaar /* 28318a7d6542SBram Moolenaar * ":dissassemble". 2832777770fbSBram Moolenaar * We don't really need this at runtime, but we do have tests that require it, 2833777770fbSBram Moolenaar * so always include this. 28348a7d6542SBram Moolenaar */ 28358a7d6542SBram Moolenaar void 28368a7d6542SBram Moolenaar ex_disassemble(exarg_T *eap) 28378a7d6542SBram Moolenaar { 283821456cdcSBram Moolenaar char_u *arg = eap->arg; 28390f18b6d1SBram Moolenaar char_u *fname; 28400f18b6d1SBram Moolenaar ufunc_T *ufunc; 28418a7d6542SBram Moolenaar dfunc_T *dfunc; 28428a7d6542SBram Moolenaar isn_T *instr; 28438a7d6542SBram Moolenaar int current; 28448a7d6542SBram Moolenaar int line_idx = 0; 28458a7d6542SBram Moolenaar int prev_current = 0; 28464c17ad94SBram Moolenaar int is_global = FALSE; 28478a7d6542SBram Moolenaar 2848bfd65589SBram Moolenaar if (STRNCMP(arg, "<lambda>", 8) == 0) 2849bfd65589SBram Moolenaar { 2850bfd65589SBram Moolenaar arg += 8; 2851bfd65589SBram Moolenaar (void)getdigits(&arg); 2852bfd65589SBram Moolenaar fname = vim_strnsave(eap->arg, arg - eap->arg); 2853bfd65589SBram Moolenaar } 2854bfd65589SBram Moolenaar else 28554c17ad94SBram Moolenaar fname = trans_function_name(&arg, &is_global, FALSE, 2856b68b346eSBram Moolenaar TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL); 285721456cdcSBram Moolenaar if (fname == NULL) 285821456cdcSBram Moolenaar { 285921456cdcSBram Moolenaar semsg(_(e_invarg2), eap->arg); 286021456cdcSBram Moolenaar return; 286121456cdcSBram Moolenaar } 286221456cdcSBram Moolenaar 28634c17ad94SBram Moolenaar ufunc = find_func(fname, is_global, NULL); 2864a26b9700SBram Moolenaar if (ufunc == NULL) 2865a26b9700SBram Moolenaar { 2866a26b9700SBram Moolenaar char_u *p = untrans_function_name(fname); 2867a26b9700SBram Moolenaar 2868a26b9700SBram Moolenaar if (p != NULL) 2869a26b9700SBram Moolenaar // Try again without making it script-local. 28704c17ad94SBram Moolenaar ufunc = find_func(p, FALSE, NULL); 2871a26b9700SBram Moolenaar } 28720f18b6d1SBram Moolenaar vim_free(fname); 28738a7d6542SBram Moolenaar if (ufunc == NULL) 28748a7d6542SBram Moolenaar { 2875451c2e35SBram Moolenaar semsg(_(e_cannot_find_function_str), eap->arg); 28768a7d6542SBram Moolenaar return; 28778a7d6542SBram Moolenaar } 28780cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_TO_BE_COMPILED 2879822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL) 2880822ba247SBram Moolenaar return; 28810cb5bcf5SBram Moolenaar if (ufunc->uf_def_status != UF_COMPILED) 28828a7d6542SBram Moolenaar { 2883451c2e35SBram Moolenaar semsg(_(e_function_is_not_compiled_str), eap->arg); 28848a7d6542SBram Moolenaar return; 28858a7d6542SBram Moolenaar } 28868a7d6542SBram Moolenaar if (ufunc->uf_name_exp != NULL) 28878a7d6542SBram Moolenaar msg((char *)ufunc->uf_name_exp); 28888a7d6542SBram Moolenaar else 28898a7d6542SBram Moolenaar msg((char *)ufunc->uf_name); 28908a7d6542SBram Moolenaar 28918a7d6542SBram Moolenaar dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; 28928a7d6542SBram Moolenaar instr = dfunc->df_instr; 28938a7d6542SBram Moolenaar for (current = 0; current < dfunc->df_instr_count; ++current) 28948a7d6542SBram Moolenaar { 28958a7d6542SBram Moolenaar isn_T *iptr = &instr[current]; 2896f2460a3aSBram Moolenaar char *line; 28978a7d6542SBram Moolenaar 28988a7d6542SBram Moolenaar while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len) 28998a7d6542SBram Moolenaar { 29008a7d6542SBram Moolenaar if (current > prev_current) 29018a7d6542SBram Moolenaar { 29028a7d6542SBram Moolenaar msg_puts("\n\n"); 29038a7d6542SBram Moolenaar prev_current = current; 29048a7d6542SBram Moolenaar } 2905f2460a3aSBram Moolenaar line = ((char **)ufunc->uf_lines.ga_data)[line_idx++]; 2906f2460a3aSBram Moolenaar if (line != NULL) 2907f2460a3aSBram Moolenaar msg(line); 29088a7d6542SBram Moolenaar } 29098a7d6542SBram Moolenaar 29108a7d6542SBram Moolenaar switch (iptr->isn_type) 29118a7d6542SBram Moolenaar { 29128a7d6542SBram Moolenaar case ISN_EXEC: 29138a7d6542SBram Moolenaar smsg("%4d EXEC %s", current, iptr->isn_arg.string); 29148a7d6542SBram Moolenaar break; 2915cfe435d7SBram Moolenaar case ISN_EXECCONCAT: 2916cfe435d7SBram Moolenaar smsg("%4d EXECCONCAT %lld", current, 2917cfe435d7SBram Moolenaar (long long)iptr->isn_arg.number); 2918cfe435d7SBram Moolenaar break; 29198a7d6542SBram Moolenaar case ISN_ECHO: 29208a7d6542SBram Moolenaar { 29218a7d6542SBram Moolenaar echo_T *echo = &iptr->isn_arg.echo; 29228a7d6542SBram Moolenaar 29238a7d6542SBram Moolenaar smsg("%4d %s %d", current, 29248a7d6542SBram Moolenaar echo->echo_with_white ? "ECHO" : "ECHON", 29258a7d6542SBram Moolenaar echo->echo_count); 29268a7d6542SBram Moolenaar } 29278a7d6542SBram Moolenaar break; 2928ad39c094SBram Moolenaar case ISN_EXECUTE: 29291082772fSBram Moolenaar smsg("%4d EXECUTE %lld", current, 29301082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 2931ad39c094SBram Moolenaar break; 2932f93c7feaSBram Moolenaar case ISN_ECHOMSG: 2933f93c7feaSBram Moolenaar smsg("%4d ECHOMSG %lld", current, 2934f93c7feaSBram Moolenaar (long long)(iptr->isn_arg.number)); 2935f93c7feaSBram Moolenaar break; 2936f93c7feaSBram Moolenaar case ISN_ECHOERR: 2937f93c7feaSBram Moolenaar smsg("%4d ECHOERR %lld", current, 2938f93c7feaSBram Moolenaar (long long)(iptr->isn_arg.number)); 2939f93c7feaSBram Moolenaar break; 29408a7d6542SBram Moolenaar case ISN_LOAD: 2941c8cd2b34SBram Moolenaar case ISN_LOADOUTER: 2942c8cd2b34SBram Moolenaar { 2943c8cd2b34SBram Moolenaar char *add = iptr->isn_type == ISN_LOAD ? "" : "OUTER"; 2944c8cd2b34SBram Moolenaar 29458a7d6542SBram Moolenaar if (iptr->isn_arg.number < 0) 2946c8cd2b34SBram Moolenaar smsg("%4d LOAD%s arg[%lld]", current, add, 2947c8cd2b34SBram Moolenaar (long long)(iptr->isn_arg.number 2948c8cd2b34SBram Moolenaar + STACK_FRAME_SIZE)); 29498a7d6542SBram Moolenaar else 2950c8cd2b34SBram Moolenaar smsg("%4d LOAD%s $%lld", current, add, 29511082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 2952c8cd2b34SBram Moolenaar } 29538a7d6542SBram Moolenaar break; 29548a7d6542SBram Moolenaar case ISN_LOADV: 29558a7d6542SBram Moolenaar smsg("%4d LOADV v:%s", current, 29568a7d6542SBram Moolenaar get_vim_var_name(iptr->isn_arg.number)); 29578a7d6542SBram Moolenaar break; 29588a7d6542SBram Moolenaar case ISN_LOADSCRIPT: 29598a7d6542SBram Moolenaar { 29608a7d6542SBram Moolenaar scriptitem_T *si = 296121b9e977SBram Moolenaar SCRIPT_ITEM(iptr->isn_arg.script.script_sid); 29628a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 29638a7d6542SBram Moolenaar + iptr->isn_arg.script.script_idx; 29648a7d6542SBram Moolenaar 2965*fbbcd003SBram Moolenaar smsg("%4d LOADSCRIPT %s-%d from %s", current, 2966*fbbcd003SBram Moolenaar sv->sv_name, 2967*fbbcd003SBram Moolenaar iptr->isn_arg.script.script_idx, 2968*fbbcd003SBram Moolenaar si->sn_name); 29698a7d6542SBram Moolenaar } 29708a7d6542SBram Moolenaar break; 29718a7d6542SBram Moolenaar case ISN_LOADS: 29728a7d6542SBram Moolenaar { 2973b283a8a6SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 2974b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 29758a7d6542SBram Moolenaar 29768a7d6542SBram Moolenaar smsg("%4d LOADS s:%s from %s", current, 29775deeb3f1SBram Moolenaar iptr->isn_arg.loadstore.ls_name, si->sn_name); 29788a7d6542SBram Moolenaar } 29798a7d6542SBram Moolenaar break; 29808a7d6542SBram Moolenaar case ISN_LOADG: 29818a7d6542SBram Moolenaar smsg("%4d LOADG g:%s", current, iptr->isn_arg.string); 29828a7d6542SBram Moolenaar break; 2983d3aac291SBram Moolenaar case ISN_LOADB: 2984d3aac291SBram Moolenaar smsg("%4d LOADB b:%s", current, iptr->isn_arg.string); 2985d3aac291SBram Moolenaar break; 2986d3aac291SBram Moolenaar case ISN_LOADW: 2987d3aac291SBram Moolenaar smsg("%4d LOADW w:%s", current, iptr->isn_arg.string); 2988d3aac291SBram Moolenaar break; 2989d3aac291SBram Moolenaar case ISN_LOADT: 2990d3aac291SBram Moolenaar smsg("%4d LOADT t:%s", current, iptr->isn_arg.string); 2991d3aac291SBram Moolenaar break; 29922f8ce0aeSBram Moolenaar case ISN_LOADGDICT: 29932f8ce0aeSBram Moolenaar smsg("%4d LOAD g:", current); 29942f8ce0aeSBram Moolenaar break; 29952f8ce0aeSBram Moolenaar case ISN_LOADBDICT: 29962f8ce0aeSBram Moolenaar smsg("%4d LOAD b:", current); 29972f8ce0aeSBram Moolenaar break; 29982f8ce0aeSBram Moolenaar case ISN_LOADWDICT: 29992f8ce0aeSBram Moolenaar smsg("%4d LOAD w:", current); 30002f8ce0aeSBram Moolenaar break; 30012f8ce0aeSBram Moolenaar case ISN_LOADTDICT: 30022f8ce0aeSBram Moolenaar smsg("%4d LOAD t:", current); 30032f8ce0aeSBram Moolenaar break; 30048a7d6542SBram Moolenaar case ISN_LOADOPT: 30058a7d6542SBram Moolenaar smsg("%4d LOADOPT %s", current, iptr->isn_arg.string); 30068a7d6542SBram Moolenaar break; 30078a7d6542SBram Moolenaar case ISN_LOADENV: 30088a7d6542SBram Moolenaar smsg("%4d LOADENV %s", current, iptr->isn_arg.string); 30098a7d6542SBram Moolenaar break; 30108a7d6542SBram Moolenaar case ISN_LOADREG: 30111082772fSBram Moolenaar smsg("%4d LOADREG @%c", current, (int)(iptr->isn_arg.number)); 30128a7d6542SBram Moolenaar break; 30138a7d6542SBram Moolenaar 30148a7d6542SBram Moolenaar case ISN_STORE: 3015b68b346eSBram Moolenaar case ISN_STOREOUTER: 3016b68b346eSBram Moolenaar { 3017b68b346eSBram Moolenaar char *add = iptr->isn_type == ISN_STORE ? "" : "OUTER"; 3018b68b346eSBram Moolenaar 3019170fcfcfSBram Moolenaar if (iptr->isn_arg.number < 0) 3020b68b346eSBram Moolenaar smsg("%4d STORE%s arg[%lld]", current, add, 3021db99f9f2SBram Moolenaar (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE)); 3022170fcfcfSBram Moolenaar else 3023b68b346eSBram Moolenaar smsg("%4d STORE%s $%lld", current, add, 30241082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 3025b68b346eSBram Moolenaar } 30268a7d6542SBram Moolenaar break; 3027b283a8a6SBram Moolenaar case ISN_STOREV: 3028b283a8a6SBram Moolenaar smsg("%4d STOREV v:%s", current, 3029b283a8a6SBram Moolenaar get_vim_var_name(iptr->isn_arg.number)); 3030b283a8a6SBram Moolenaar break; 30318a7d6542SBram Moolenaar case ISN_STOREG: 3032b283a8a6SBram Moolenaar smsg("%4d STOREG %s", current, iptr->isn_arg.string); 3033b283a8a6SBram Moolenaar break; 3034d3aac291SBram Moolenaar case ISN_STOREB: 3035d3aac291SBram Moolenaar smsg("%4d STOREB %s", current, iptr->isn_arg.string); 3036d3aac291SBram Moolenaar break; 3037d3aac291SBram Moolenaar case ISN_STOREW: 3038d3aac291SBram Moolenaar smsg("%4d STOREW %s", current, iptr->isn_arg.string); 3039d3aac291SBram Moolenaar break; 3040d3aac291SBram Moolenaar case ISN_STORET: 3041d3aac291SBram Moolenaar smsg("%4d STORET %s", current, iptr->isn_arg.string); 3042d3aac291SBram Moolenaar break; 3043b283a8a6SBram Moolenaar case ISN_STORES: 3044b283a8a6SBram Moolenaar { 3045b283a8a6SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 3046b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 3047b283a8a6SBram Moolenaar 30480bbf722aSBram Moolenaar smsg("%4d STORES %s in %s", current, 30495deeb3f1SBram Moolenaar iptr->isn_arg.loadstore.ls_name, si->sn_name); 3050b283a8a6SBram Moolenaar } 30518a7d6542SBram Moolenaar break; 30528a7d6542SBram Moolenaar case ISN_STORESCRIPT: 30538a7d6542SBram Moolenaar { 30548a7d6542SBram Moolenaar scriptitem_T *si = 305521b9e977SBram Moolenaar SCRIPT_ITEM(iptr->isn_arg.script.script_sid); 30568a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 30578a7d6542SBram Moolenaar + iptr->isn_arg.script.script_idx; 30588a7d6542SBram Moolenaar 3059*fbbcd003SBram Moolenaar smsg("%4d STORESCRIPT %s-%d in %s", current, 3060*fbbcd003SBram Moolenaar sv->sv_name, 3061*fbbcd003SBram Moolenaar iptr->isn_arg.script.script_idx, 3062*fbbcd003SBram Moolenaar si->sn_name); 30638a7d6542SBram Moolenaar } 30648a7d6542SBram Moolenaar break; 30658a7d6542SBram Moolenaar case ISN_STOREOPT: 30668a7d6542SBram Moolenaar smsg("%4d STOREOPT &%s", current, 30678a7d6542SBram Moolenaar iptr->isn_arg.storeopt.so_name); 30688a7d6542SBram Moolenaar break; 3069b283a8a6SBram Moolenaar case ISN_STOREENV: 3070b283a8a6SBram Moolenaar smsg("%4d STOREENV $%s", current, iptr->isn_arg.string); 3071b283a8a6SBram Moolenaar break; 3072b283a8a6SBram Moolenaar case ISN_STOREREG: 30731082772fSBram Moolenaar smsg("%4d STOREREG @%c", current, (int)iptr->isn_arg.number); 3074b283a8a6SBram Moolenaar break; 30758a7d6542SBram Moolenaar case ISN_STORENR: 30768a7d6542SBram Moolenaar smsg("%4d STORE %lld in $%d", current, 3077a471eeaeSBram Moolenaar iptr->isn_arg.storenr.stnr_val, 3078a471eeaeSBram Moolenaar iptr->isn_arg.storenr.stnr_idx); 30798a7d6542SBram Moolenaar break; 30808a7d6542SBram Moolenaar 30811cc2a94fSBram Moolenaar case ISN_STORELIST: 30821cc2a94fSBram Moolenaar smsg("%4d STORELIST", current); 30831cc2a94fSBram Moolenaar break; 30841cc2a94fSBram Moolenaar 30851cc2a94fSBram Moolenaar case ISN_STOREDICT: 30861cc2a94fSBram Moolenaar smsg("%4d STOREDICT", current); 30871cc2a94fSBram Moolenaar break; 30881cc2a94fSBram Moolenaar 30898a7d6542SBram Moolenaar // constants 30908a7d6542SBram Moolenaar case ISN_PUSHNR: 30911082772fSBram Moolenaar smsg("%4d PUSHNR %lld", current, 30921082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 30938a7d6542SBram Moolenaar break; 30948a7d6542SBram Moolenaar case ISN_PUSHBOOL: 30958a7d6542SBram Moolenaar case ISN_PUSHSPEC: 30968a7d6542SBram Moolenaar smsg("%4d PUSH %s", current, 30978a7d6542SBram Moolenaar get_var_special_name(iptr->isn_arg.number)); 30988a7d6542SBram Moolenaar break; 30998a7d6542SBram Moolenaar case ISN_PUSHF: 3100a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT 31018a7d6542SBram Moolenaar smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber); 3102a5d5953dSBram Moolenaar #endif 31038a7d6542SBram Moolenaar break; 31048a7d6542SBram Moolenaar case ISN_PUSHS: 31058a7d6542SBram Moolenaar smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string); 31068a7d6542SBram Moolenaar break; 31078a7d6542SBram Moolenaar case ISN_PUSHBLOB: 31088a7d6542SBram Moolenaar { 31098a7d6542SBram Moolenaar char_u *r; 31108a7d6542SBram Moolenaar char_u numbuf[NUMBUFLEN]; 31118a7d6542SBram Moolenaar char_u *tofree; 31128a7d6542SBram Moolenaar 31138a7d6542SBram Moolenaar r = blob2string(iptr->isn_arg.blob, &tofree, numbuf); 3114ff80cb68SBram Moolenaar smsg("%4d PUSHBLOB %s", current, r); 31158a7d6542SBram Moolenaar vim_free(tofree); 31168a7d6542SBram Moolenaar } 31178a7d6542SBram Moolenaar break; 311842a480bfSBram Moolenaar case ISN_PUSHFUNC: 3119087d2e15SBram Moolenaar { 3120087d2e15SBram Moolenaar char *name = (char *)iptr->isn_arg.string; 3121087d2e15SBram Moolenaar 3122087d2e15SBram Moolenaar smsg("%4d PUSHFUNC \"%s\"", current, 3123087d2e15SBram Moolenaar name == NULL ? "[none]" : name); 3124087d2e15SBram Moolenaar } 312542a480bfSBram Moolenaar break; 312642a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 312742a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 312842a480bfSBram Moolenaar { 312942a480bfSBram Moolenaar channel_T *channel = iptr->isn_arg.channel; 313042a480bfSBram Moolenaar 313142a480bfSBram Moolenaar smsg("%4d PUSHCHANNEL %d", current, 313242a480bfSBram Moolenaar channel == NULL ? 0 : channel->ch_id); 313342a480bfSBram Moolenaar } 313442a480bfSBram Moolenaar #endif 313542a480bfSBram Moolenaar break; 313642a480bfSBram Moolenaar case ISN_PUSHJOB: 313742a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 313842a480bfSBram Moolenaar { 313942a480bfSBram Moolenaar typval_T tv; 314042a480bfSBram Moolenaar char_u *name; 314142a480bfSBram Moolenaar 314242a480bfSBram Moolenaar tv.v_type = VAR_JOB; 314342a480bfSBram Moolenaar tv.vval.v_job = iptr->isn_arg.job; 314442a480bfSBram Moolenaar name = tv_get_string(&tv); 3145f51cb4e0SBram Moolenaar smsg("%4d PUSHJOB \"%s\"", current, name); 314642a480bfSBram Moolenaar } 314742a480bfSBram Moolenaar #endif 314842a480bfSBram Moolenaar break; 31498a7d6542SBram Moolenaar case ISN_PUSHEXC: 31508a7d6542SBram Moolenaar smsg("%4d PUSH v:exception", current); 31518a7d6542SBram Moolenaar break; 3152d72c1bf0SBram Moolenaar case ISN_UNLET: 3153d72c1bf0SBram Moolenaar smsg("%4d UNLET%s %s", current, 3154d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_forceit ? "!" : "", 3155d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_name); 3156d72c1bf0SBram Moolenaar break; 31577bdaea6eSBram Moolenaar case ISN_UNLETENV: 31587bdaea6eSBram Moolenaar smsg("%4d UNLETENV%s $%s", current, 31597bdaea6eSBram Moolenaar iptr->isn_arg.unlet.ul_forceit ? "!" : "", 31607bdaea6eSBram Moolenaar iptr->isn_arg.unlet.ul_name); 31617bdaea6eSBram Moolenaar break; 31620b4c66c6SBram Moolenaar case ISN_LOCKCONST: 31630b4c66c6SBram Moolenaar smsg("%4d LOCKCONST", current); 31640b4c66c6SBram Moolenaar break; 31658a7d6542SBram Moolenaar case ISN_NEWLIST: 31661082772fSBram Moolenaar smsg("%4d NEWLIST size %lld", current, 31671082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 31688a7d6542SBram Moolenaar break; 31698a7d6542SBram Moolenaar case ISN_NEWDICT: 31701082772fSBram Moolenaar smsg("%4d NEWDICT size %lld", current, 31711082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 31728a7d6542SBram Moolenaar break; 31738a7d6542SBram Moolenaar 31748a7d6542SBram Moolenaar // function call 31758a7d6542SBram Moolenaar case ISN_BCALL: 31768a7d6542SBram Moolenaar { 31778a7d6542SBram Moolenaar cbfunc_T *cbfunc = &iptr->isn_arg.bfunc; 31788a7d6542SBram Moolenaar 31798a7d6542SBram Moolenaar smsg("%4d BCALL %s(argc %d)", current, 31808a7d6542SBram Moolenaar internal_func_name(cbfunc->cbf_idx), 31818a7d6542SBram Moolenaar cbfunc->cbf_argcount); 31828a7d6542SBram Moolenaar } 31838a7d6542SBram Moolenaar break; 31848a7d6542SBram Moolenaar case ISN_DCALL: 31858a7d6542SBram Moolenaar { 31868a7d6542SBram Moolenaar cdfunc_T *cdfunc = &iptr->isn_arg.dfunc; 31878a7d6542SBram Moolenaar dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 31888a7d6542SBram Moolenaar + cdfunc->cdf_idx; 31898a7d6542SBram Moolenaar 31908a7d6542SBram Moolenaar smsg("%4d DCALL %s(argc %d)", current, 31918a7d6542SBram Moolenaar df->df_ufunc->uf_name_exp != NULL 31928a7d6542SBram Moolenaar ? df->df_ufunc->uf_name_exp 31938a7d6542SBram Moolenaar : df->df_ufunc->uf_name, cdfunc->cdf_argcount); 31948a7d6542SBram Moolenaar } 31958a7d6542SBram Moolenaar break; 31968a7d6542SBram Moolenaar case ISN_UCALL: 31978a7d6542SBram Moolenaar { 31988a7d6542SBram Moolenaar cufunc_T *cufunc = &iptr->isn_arg.ufunc; 31998a7d6542SBram Moolenaar 32008a7d6542SBram Moolenaar smsg("%4d UCALL %s(argc %d)", current, 32018a7d6542SBram Moolenaar cufunc->cuf_name, cufunc->cuf_argcount); 32028a7d6542SBram Moolenaar } 32038a7d6542SBram Moolenaar break; 32048a7d6542SBram Moolenaar case ISN_PCALL: 32058a7d6542SBram Moolenaar { 32068a7d6542SBram Moolenaar cpfunc_T *cpfunc = &iptr->isn_arg.pfunc; 32078a7d6542SBram Moolenaar 32088a7d6542SBram Moolenaar smsg("%4d PCALL%s (argc %d)", current, 32098a7d6542SBram Moolenaar cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); 32108a7d6542SBram Moolenaar } 32118a7d6542SBram Moolenaar break; 3212bd5da371SBram Moolenaar case ISN_PCALL_END: 3213bd5da371SBram Moolenaar smsg("%4d PCALL end", current); 3214bd5da371SBram Moolenaar break; 32158a7d6542SBram Moolenaar case ISN_RETURN: 32168a7d6542SBram Moolenaar smsg("%4d RETURN", current); 32178a7d6542SBram Moolenaar break; 32188a7d6542SBram Moolenaar case ISN_FUNCREF: 32198a7d6542SBram Moolenaar { 32205adc55cbSBram Moolenaar funcref_T *funcref = &iptr->isn_arg.funcref; 32218a7d6542SBram Moolenaar dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 32225adc55cbSBram Moolenaar + funcref->fr_func; 32238a7d6542SBram Moolenaar 3224148ce7aeSBram Moolenaar smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name); 32258a7d6542SBram Moolenaar } 32268a7d6542SBram Moolenaar break; 32278a7d6542SBram Moolenaar 322838ddf333SBram Moolenaar case ISN_NEWFUNC: 322938ddf333SBram Moolenaar { 323038ddf333SBram Moolenaar newfunc_T *newfunc = &iptr->isn_arg.newfunc; 323138ddf333SBram Moolenaar 323238ddf333SBram Moolenaar smsg("%4d NEWFUNC %s %s", current, 323338ddf333SBram Moolenaar newfunc->nf_lambda, newfunc->nf_global); 323438ddf333SBram Moolenaar } 323538ddf333SBram Moolenaar break; 323638ddf333SBram Moolenaar 32378a7d6542SBram Moolenaar case ISN_JUMP: 32388a7d6542SBram Moolenaar { 32398a7d6542SBram Moolenaar char *when = "?"; 32408a7d6542SBram Moolenaar 32418a7d6542SBram Moolenaar switch (iptr->isn_arg.jump.jump_when) 32428a7d6542SBram Moolenaar { 32438a7d6542SBram Moolenaar case JUMP_ALWAYS: 32448a7d6542SBram Moolenaar when = "JUMP"; 32458a7d6542SBram Moolenaar break; 32468a7d6542SBram Moolenaar case JUMP_AND_KEEP_IF_TRUE: 32478a7d6542SBram Moolenaar when = "JUMP_AND_KEEP_IF_TRUE"; 32488a7d6542SBram Moolenaar break; 32498a7d6542SBram Moolenaar case JUMP_IF_FALSE: 32508a7d6542SBram Moolenaar when = "JUMP_IF_FALSE"; 32518a7d6542SBram Moolenaar break; 32528a7d6542SBram Moolenaar case JUMP_AND_KEEP_IF_FALSE: 32538a7d6542SBram Moolenaar when = "JUMP_AND_KEEP_IF_FALSE"; 32548a7d6542SBram Moolenaar break; 32552bb2658bSBram Moolenaar case JUMP_IF_COND_FALSE: 32562bb2658bSBram Moolenaar when = "JUMP_IF_COND_FALSE"; 32572bb2658bSBram Moolenaar break; 32582bb2658bSBram Moolenaar case JUMP_IF_COND_TRUE: 32592bb2658bSBram Moolenaar when = "JUMP_IF_COND_TRUE"; 32602bb2658bSBram Moolenaar break; 32618a7d6542SBram Moolenaar } 32628a677a37SBram Moolenaar smsg("%4d %s -> %d", current, when, 32638a7d6542SBram Moolenaar iptr->isn_arg.jump.jump_where); 32648a7d6542SBram Moolenaar } 32658a7d6542SBram Moolenaar break; 32668a7d6542SBram Moolenaar 32678a7d6542SBram Moolenaar case ISN_FOR: 32688a7d6542SBram Moolenaar { 32698a7d6542SBram Moolenaar forloop_T *forloop = &iptr->isn_arg.forloop; 32708a7d6542SBram Moolenaar 32718a7d6542SBram Moolenaar smsg("%4d FOR $%d -> %d", current, 32728a7d6542SBram Moolenaar forloop->for_idx, forloop->for_end); 32738a7d6542SBram Moolenaar } 32748a7d6542SBram Moolenaar break; 32758a7d6542SBram Moolenaar 32768a7d6542SBram Moolenaar case ISN_TRY: 32778a7d6542SBram Moolenaar { 32788a7d6542SBram Moolenaar try_T *try = &iptr->isn_arg.try; 32798a7d6542SBram Moolenaar 32808a7d6542SBram Moolenaar smsg("%4d TRY catch -> %d, finally -> %d", current, 32818a7d6542SBram Moolenaar try->try_catch, try->try_finally); 32828a7d6542SBram Moolenaar } 32838a7d6542SBram Moolenaar break; 32848a7d6542SBram Moolenaar case ISN_CATCH: 32858a7d6542SBram Moolenaar // TODO 32868a7d6542SBram Moolenaar smsg("%4d CATCH", current); 32878a7d6542SBram Moolenaar break; 32888a7d6542SBram Moolenaar case ISN_ENDTRY: 32898a7d6542SBram Moolenaar smsg("%4d ENDTRY", current); 32908a7d6542SBram Moolenaar break; 32918a7d6542SBram Moolenaar case ISN_THROW: 32928a7d6542SBram Moolenaar smsg("%4d THROW", current); 32938a7d6542SBram Moolenaar break; 32948a7d6542SBram Moolenaar 32958a7d6542SBram Moolenaar // expression operations on number 32968a7d6542SBram Moolenaar case ISN_OPNR: 32978a7d6542SBram Moolenaar case ISN_OPFLOAT: 32988a7d6542SBram Moolenaar case ISN_OPANY: 32998a7d6542SBram Moolenaar { 33008a7d6542SBram Moolenaar char *what; 33018a7d6542SBram Moolenaar char *ins; 33028a7d6542SBram Moolenaar 33038a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 33048a7d6542SBram Moolenaar { 33058a7d6542SBram Moolenaar case EXPR_MULT: what = "*"; break; 33068a7d6542SBram Moolenaar case EXPR_DIV: what = "/"; break; 33078a7d6542SBram Moolenaar case EXPR_REM: what = "%"; break; 33088a7d6542SBram Moolenaar case EXPR_SUB: what = "-"; break; 33098a7d6542SBram Moolenaar case EXPR_ADD: what = "+"; break; 33108a7d6542SBram Moolenaar default: what = "???"; break; 33118a7d6542SBram Moolenaar } 33128a7d6542SBram Moolenaar switch (iptr->isn_type) 33138a7d6542SBram Moolenaar { 33148a7d6542SBram Moolenaar case ISN_OPNR: ins = "OPNR"; break; 33158a7d6542SBram Moolenaar case ISN_OPFLOAT: ins = "OPFLOAT"; break; 33168a7d6542SBram Moolenaar case ISN_OPANY: ins = "OPANY"; break; 33178a7d6542SBram Moolenaar default: ins = "???"; break; 33188a7d6542SBram Moolenaar } 33198a7d6542SBram Moolenaar smsg("%4d %s %s", current, ins, what); 33208a7d6542SBram Moolenaar } 33218a7d6542SBram Moolenaar break; 33228a7d6542SBram Moolenaar 33238a7d6542SBram Moolenaar case ISN_COMPAREBOOL: 33248a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 33258a7d6542SBram Moolenaar case ISN_COMPARENR: 33268a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: 33278a7d6542SBram Moolenaar case ISN_COMPARESTRING: 33288a7d6542SBram Moolenaar case ISN_COMPAREBLOB: 33298a7d6542SBram Moolenaar case ISN_COMPARELIST: 33308a7d6542SBram Moolenaar case ISN_COMPAREDICT: 33318a7d6542SBram Moolenaar case ISN_COMPAREFUNC: 33328a7d6542SBram Moolenaar case ISN_COMPAREANY: 33338a7d6542SBram Moolenaar { 33348a7d6542SBram Moolenaar char *p; 33358a7d6542SBram Moolenaar char buf[10]; 33368a7d6542SBram Moolenaar char *type; 33378a7d6542SBram Moolenaar 33388a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 33398a7d6542SBram Moolenaar { 33408a7d6542SBram Moolenaar case EXPR_EQUAL: p = "=="; break; 33418a7d6542SBram Moolenaar case EXPR_NEQUAL: p = "!="; break; 33428a7d6542SBram Moolenaar case EXPR_GREATER: p = ">"; break; 33438a7d6542SBram Moolenaar case EXPR_GEQUAL: p = ">="; break; 33448a7d6542SBram Moolenaar case EXPR_SMALLER: p = "<"; break; 33458a7d6542SBram Moolenaar case EXPR_SEQUAL: p = "<="; break; 33468a7d6542SBram Moolenaar case EXPR_MATCH: p = "=~"; break; 33478a7d6542SBram Moolenaar case EXPR_IS: p = "is"; break; 33488a7d6542SBram Moolenaar case EXPR_ISNOT: p = "isnot"; break; 33498a7d6542SBram Moolenaar case EXPR_NOMATCH: p = "!~"; break; 33508a7d6542SBram Moolenaar default: p = "???"; break; 33518a7d6542SBram Moolenaar } 33528a7d6542SBram Moolenaar STRCPY(buf, p); 33538a7d6542SBram Moolenaar if (iptr->isn_arg.op.op_ic == TRUE) 33548a7d6542SBram Moolenaar strcat(buf, "?"); 33558a7d6542SBram Moolenaar switch(iptr->isn_type) 33568a7d6542SBram Moolenaar { 33578a7d6542SBram Moolenaar case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break; 33588a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 33598a7d6542SBram Moolenaar type = "COMPARESPECIAL"; break; 33608a7d6542SBram Moolenaar case ISN_COMPARENR: type = "COMPARENR"; break; 33618a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break; 33628a7d6542SBram Moolenaar case ISN_COMPARESTRING: 33638a7d6542SBram Moolenaar type = "COMPARESTRING"; break; 33648a7d6542SBram Moolenaar case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break; 33658a7d6542SBram Moolenaar case ISN_COMPARELIST: type = "COMPARELIST"; break; 33668a7d6542SBram Moolenaar case ISN_COMPAREDICT: type = "COMPAREDICT"; break; 33678a7d6542SBram Moolenaar case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break; 33688a7d6542SBram Moolenaar case ISN_COMPAREANY: type = "COMPAREANY"; break; 33698a7d6542SBram Moolenaar default: type = "???"; break; 33708a7d6542SBram Moolenaar } 33718a7d6542SBram Moolenaar 33728a7d6542SBram Moolenaar smsg("%4d %s %s", current, type, buf); 33738a7d6542SBram Moolenaar } 33748a7d6542SBram Moolenaar break; 33758a7d6542SBram Moolenaar 33768a7d6542SBram Moolenaar case ISN_ADDLIST: smsg("%4d ADDLIST", current); break; 33778a7d6542SBram Moolenaar case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break; 33788a7d6542SBram Moolenaar 33798a7d6542SBram Moolenaar // expression operations 33808a7d6542SBram Moolenaar case ISN_CONCAT: smsg("%4d CONCAT", current); break; 3381bf9d8c37SBram Moolenaar case ISN_STRINDEX: smsg("%4d STRINDEX", current); break; 338211107babSBram Moolenaar case ISN_STRSLICE: smsg("%4d STRSLICE", current); break; 3383bf9d8c37SBram Moolenaar case ISN_LISTINDEX: smsg("%4d LISTINDEX", current); break; 3384ed591877SBram Moolenaar case ISN_LISTSLICE: smsg("%4d LISTSLICE", current); break; 3385cc673e74SBram Moolenaar case ISN_ANYINDEX: smsg("%4d ANYINDEX", current); break; 3386cc673e74SBram Moolenaar case ISN_ANYSLICE: smsg("%4d ANYSLICE", current); break; 33879af78769SBram Moolenaar case ISN_SLICE: smsg("%4d SLICE %lld", 33889af78769SBram Moolenaar current, iptr->isn_arg.number); break; 338947a519a9SBram Moolenaar case ISN_GETITEM: smsg("%4d ITEM %lld", 339047a519a9SBram Moolenaar current, iptr->isn_arg.number); break; 33911cc2a94fSBram Moolenaar case ISN_MEMBER: smsg("%4d MEMBER", current); break; 33921cc2a94fSBram Moolenaar case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current, 33938a7d6542SBram Moolenaar iptr->isn_arg.string); break; 33948a7d6542SBram Moolenaar case ISN_NEGATENR: smsg("%4d NEGATENR", current); break; 33958a7d6542SBram Moolenaar 33968a7d6542SBram Moolenaar case ISN_CHECKNR: smsg("%4d CHECKNR", current); break; 33975e654230SBram Moolenaar case ISN_CHECKTYPE: 33985e654230SBram Moolenaar { 33995e654230SBram Moolenaar char *tofree; 34005e654230SBram Moolenaar 34015e654230SBram Moolenaar smsg("%4d CHECKTYPE %s stack[%d]", current, 34025e654230SBram Moolenaar type_name(iptr->isn_arg.type.ct_type, &tofree), 34038a7d6542SBram Moolenaar iptr->isn_arg.type.ct_off); 34045e654230SBram Moolenaar vim_free(tofree); 34058a7d6542SBram Moolenaar break; 34065e654230SBram Moolenaar } 34079af78769SBram Moolenaar case ISN_CHECKLEN: smsg("%4d CHECKLEN %s%d", current, 34089af78769SBram Moolenaar iptr->isn_arg.checklen.cl_more_OK ? ">= " : "", 34099af78769SBram Moolenaar iptr->isn_arg.checklen.cl_min_len); 34109af78769SBram Moolenaar break; 34112bb2658bSBram Moolenaar case ISN_COND2BOOL: smsg("%4d COND2BOOL", current); break; 34128a7d6542SBram Moolenaar case ISN_2BOOL: if (iptr->isn_arg.number) 34138a7d6542SBram Moolenaar smsg("%4d INVERT (!val)", current); 34148a7d6542SBram Moolenaar else 34158a7d6542SBram Moolenaar smsg("%4d 2BOOL (!!val)", current); 34168a7d6542SBram Moolenaar break; 3417db99f9f2SBram Moolenaar case ISN_2STRING: smsg("%4d 2STRING stack[%lld]", current, 3418db99f9f2SBram Moolenaar (long long)(iptr->isn_arg.number)); 34198a7d6542SBram Moolenaar break; 3420418f1df5SBram Moolenaar case ISN_2STRING_ANY: smsg("%4d 2STRING_ANY stack[%lld]", current, 3421418f1df5SBram Moolenaar (long long)(iptr->isn_arg.number)); 3422418f1df5SBram Moolenaar break; 3423c3516f7eSBram Moolenaar case ISN_PUT: 3424c3516f7eSBram Moolenaar smsg("%4d PUT %c %ld", current, iptr->isn_arg.put.put_regname, 3425c3516f7eSBram Moolenaar (long)iptr->isn_arg.put.put_lnum); 3426c3516f7eSBram Moolenaar break; 34278a7d6542SBram Moolenaar 3428389df259SBram Moolenaar case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current, 3429389df259SBram Moolenaar iptr->isn_arg.shuffle.shfl_item, 3430389df259SBram Moolenaar iptr->isn_arg.shuffle.shfl_up); 3431389df259SBram Moolenaar break; 34328a7d6542SBram Moolenaar case ISN_DROP: smsg("%4d DROP", current); break; 34338a7d6542SBram Moolenaar } 3434793dcc54SBram Moolenaar 3435793dcc54SBram Moolenaar out_flush(); // output one line at a time 3436793dcc54SBram Moolenaar ui_breakcheck(); 3437793dcc54SBram Moolenaar if (got_int) 3438793dcc54SBram Moolenaar break; 34398a7d6542SBram Moolenaar } 34408a7d6542SBram Moolenaar } 34418a7d6542SBram Moolenaar 34428a7d6542SBram Moolenaar /* 344313106605SBram Moolenaar * Return TRUE when "tv" is not falsy: non-zero, non-empty string, non-empty 34448a7d6542SBram Moolenaar * list, etc. Mostly like what JavaScript does, except that empty list and 34458a7d6542SBram Moolenaar * empty dictionary are FALSE. 34468a7d6542SBram Moolenaar */ 34478a7d6542SBram Moolenaar int 34488a7d6542SBram Moolenaar tv2bool(typval_T *tv) 34498a7d6542SBram Moolenaar { 34508a7d6542SBram Moolenaar switch (tv->v_type) 34518a7d6542SBram Moolenaar { 34528a7d6542SBram Moolenaar case VAR_NUMBER: 34538a7d6542SBram Moolenaar return tv->vval.v_number != 0; 34548a7d6542SBram Moolenaar case VAR_FLOAT: 34558a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 34568a7d6542SBram Moolenaar return tv->vval.v_float != 0.0; 34578a7d6542SBram Moolenaar #else 34588a7d6542SBram Moolenaar break; 34598a7d6542SBram Moolenaar #endif 34608a7d6542SBram Moolenaar case VAR_PARTIAL: 34618a7d6542SBram Moolenaar return tv->vval.v_partial != NULL; 34628a7d6542SBram Moolenaar case VAR_FUNC: 34638a7d6542SBram Moolenaar case VAR_STRING: 34648a7d6542SBram Moolenaar return tv->vval.v_string != NULL && *tv->vval.v_string != NUL; 34658a7d6542SBram Moolenaar case VAR_LIST: 34668a7d6542SBram Moolenaar return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0; 34678a7d6542SBram Moolenaar case VAR_DICT: 34688a7d6542SBram Moolenaar return tv->vval.v_dict != NULL 34698a7d6542SBram Moolenaar && tv->vval.v_dict->dv_hashtab.ht_used > 0; 34708a7d6542SBram Moolenaar case VAR_BOOL: 34718a7d6542SBram Moolenaar case VAR_SPECIAL: 34728a7d6542SBram Moolenaar return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE; 34738a7d6542SBram Moolenaar case VAR_JOB: 34748a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL 34758a7d6542SBram Moolenaar return tv->vval.v_job != NULL; 34768a7d6542SBram Moolenaar #else 34778a7d6542SBram Moolenaar break; 34788a7d6542SBram Moolenaar #endif 34798a7d6542SBram Moolenaar case VAR_CHANNEL: 34808a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL 34818a7d6542SBram Moolenaar return tv->vval.v_channel != NULL; 34828a7d6542SBram Moolenaar #else 34838a7d6542SBram Moolenaar break; 34848a7d6542SBram Moolenaar #endif 34858a7d6542SBram Moolenaar case VAR_BLOB: 34868a7d6542SBram Moolenaar return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0; 34878a7d6542SBram Moolenaar case VAR_UNKNOWN: 34884c683750SBram Moolenaar case VAR_ANY: 34898a7d6542SBram Moolenaar case VAR_VOID: 34908a7d6542SBram Moolenaar break; 34918a7d6542SBram Moolenaar } 34928a7d6542SBram Moolenaar return FALSE; 34938a7d6542SBram Moolenaar } 34948a7d6542SBram Moolenaar 34958a7d6542SBram Moolenaar /* 34968a7d6542SBram Moolenaar * If "tv" is a string give an error and return FAIL. 34978a7d6542SBram Moolenaar */ 34988a7d6542SBram Moolenaar int 34998a7d6542SBram Moolenaar check_not_string(typval_T *tv) 35008a7d6542SBram Moolenaar { 35018a7d6542SBram Moolenaar if (tv->v_type == VAR_STRING) 35028a7d6542SBram Moolenaar { 3503451c2e35SBram Moolenaar emsg(_(e_using_string_as_number)); 35048a7d6542SBram Moolenaar clear_tv(tv); 35058a7d6542SBram Moolenaar return FAIL; 35068a7d6542SBram Moolenaar } 35078a7d6542SBram Moolenaar return OK; 35088a7d6542SBram Moolenaar } 35098a7d6542SBram Moolenaar 35108a7d6542SBram Moolenaar 35118a7d6542SBram Moolenaar #endif // FEAT_EVAL 3512