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 708a7d6542SBram Moolenaar } ectx_T; 718a7d6542SBram Moolenaar 728a7d6542SBram Moolenaar // Get pointer to item relative to the bottom of the stack, -1 is the last one. 738a7d6542SBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx) 748a7d6542SBram Moolenaar 758a7d6542SBram Moolenaar /* 76170fcfcfSBram Moolenaar * Return the number of arguments, including optional arguments and any vararg. 778a7d6542SBram Moolenaar */ 788a7d6542SBram Moolenaar static int 798a7d6542SBram Moolenaar ufunc_argcount(ufunc_T *ufunc) 808a7d6542SBram Moolenaar { 818a7d6542SBram Moolenaar return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0); 828a7d6542SBram Moolenaar } 838a7d6542SBram Moolenaar 848a7d6542SBram Moolenaar /* 85170fcfcfSBram Moolenaar * Set the instruction index, depending on omitted arguments, where the default 86170fcfcfSBram Moolenaar * values are to be computed. If all optional arguments are present, start 87170fcfcfSBram Moolenaar * with the function body. 88170fcfcfSBram Moolenaar * The expression evaluation is at the start of the instructions: 89170fcfcfSBram Moolenaar * 0 -> EVAL default1 90170fcfcfSBram Moolenaar * STORE arg[-2] 91170fcfcfSBram Moolenaar * 1 -> EVAL default2 92170fcfcfSBram Moolenaar * STORE arg[-1] 93170fcfcfSBram Moolenaar * 2 -> function body 94170fcfcfSBram Moolenaar */ 95170fcfcfSBram Moolenaar static void 96170fcfcfSBram Moolenaar init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx) 97170fcfcfSBram Moolenaar { 98170fcfcfSBram Moolenaar if (ufunc->uf_def_args.ga_len == 0) 99170fcfcfSBram Moolenaar ectx->ec_iidx = 0; 100170fcfcfSBram Moolenaar else 101170fcfcfSBram Moolenaar { 102170fcfcfSBram Moolenaar int defcount = ufunc->uf_args.ga_len - argcount; 103170fcfcfSBram Moolenaar 104170fcfcfSBram Moolenaar // If there is a varargs argument defcount can be negative, no defaults 105170fcfcfSBram Moolenaar // to evaluate then. 106170fcfcfSBram Moolenaar if (defcount < 0) 107170fcfcfSBram Moolenaar defcount = 0; 108170fcfcfSBram Moolenaar ectx->ec_iidx = ufunc->uf_def_arg_idx[ 109170fcfcfSBram Moolenaar ufunc->uf_def_args.ga_len - defcount]; 110170fcfcfSBram Moolenaar } 111170fcfcfSBram Moolenaar } 112170fcfcfSBram Moolenaar 113170fcfcfSBram Moolenaar /* 114fe270817SBram Moolenaar * Create a new list from "count" items at the bottom of the stack. 115fe270817SBram Moolenaar * When "count" is zero an empty list is added to the stack. 116fe270817SBram Moolenaar */ 117fe270817SBram Moolenaar static int 118fe270817SBram Moolenaar exe_newlist(int count, ectx_T *ectx) 119fe270817SBram Moolenaar { 120fe270817SBram Moolenaar list_T *list = list_alloc_with_items(count); 121fe270817SBram Moolenaar int idx; 122fe270817SBram Moolenaar typval_T *tv; 123fe270817SBram Moolenaar 124fe270817SBram Moolenaar if (list == NULL) 125fe270817SBram Moolenaar return FAIL; 126fe270817SBram Moolenaar for (idx = 0; idx < count; ++idx) 127fe270817SBram Moolenaar list_set_item(list, idx, STACK_TV_BOT(idx - count)); 128fe270817SBram Moolenaar 129fe270817SBram Moolenaar if (count > 0) 130fe270817SBram Moolenaar ectx->ec_stack.ga_len -= count - 1; 131270d0388SBram Moolenaar else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) 132fe270817SBram Moolenaar return FAIL; 133fe270817SBram Moolenaar else 134fe270817SBram Moolenaar ++ectx->ec_stack.ga_len; 135fe270817SBram Moolenaar tv = STACK_TV_BOT(-1); 136fe270817SBram Moolenaar tv->v_type = VAR_LIST; 137fe270817SBram Moolenaar tv->vval.v_list = list; 138fe270817SBram Moolenaar ++list->lv_refcount; 139fe270817SBram Moolenaar return OK; 140fe270817SBram Moolenaar } 141fe270817SBram Moolenaar 142fe270817SBram Moolenaar /* 1438a7d6542SBram Moolenaar * Call compiled function "cdf_idx" from compiled code. 1448a7d6542SBram Moolenaar * 1458a7d6542SBram Moolenaar * Stack has: 1468a7d6542SBram Moolenaar * - current arguments (already there) 1478a7d6542SBram Moolenaar * - omitted optional argument (default values) added here 1488a7d6542SBram Moolenaar * - stack frame: 1498a7d6542SBram Moolenaar * - pointer to calling function 1508a7d6542SBram Moolenaar * - Index of next instruction in calling function 1518a7d6542SBram Moolenaar * - previous frame pointer 1528a7d6542SBram Moolenaar * - reserved space for local variables 1538a7d6542SBram Moolenaar */ 1548a7d6542SBram Moolenaar static int 1551378fbc4SBram Moolenaar call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx) 1568a7d6542SBram Moolenaar { 1571378fbc4SBram Moolenaar int argcount = argcount_arg; 1588a7d6542SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx; 1598a7d6542SBram Moolenaar ufunc_T *ufunc = dfunc->df_ufunc; 1601378fbc4SBram Moolenaar int arg_to_add; 1611378fbc4SBram Moolenaar int vararg_count = 0; 1628a7d6542SBram Moolenaar int idx; 163c620c055SBram Moolenaar estack_T *entry; 1648a7d6542SBram Moolenaar 1658a7d6542SBram Moolenaar if (dfunc->df_deleted) 1668a7d6542SBram Moolenaar { 1678a7d6542SBram Moolenaar emsg_funcname(e_func_deleted, ufunc->uf_name); 1688a7d6542SBram Moolenaar return FAIL; 1698a7d6542SBram Moolenaar } 1708a7d6542SBram Moolenaar 1711378fbc4SBram Moolenaar if (ufunc->uf_va_name != NULL) 1721378fbc4SBram Moolenaar { 173fe270817SBram Moolenaar // Need to make a list out of the vararg arguments. 1741378fbc4SBram Moolenaar // Stack at time of call with 2 varargs: 1751378fbc4SBram Moolenaar // normal_arg 1761378fbc4SBram Moolenaar // optional_arg 1771378fbc4SBram Moolenaar // vararg_1 1781378fbc4SBram Moolenaar // vararg_2 179fe270817SBram Moolenaar // After creating the list: 1801378fbc4SBram Moolenaar // normal_arg 1811378fbc4SBram Moolenaar // optional_arg 182fe270817SBram Moolenaar // vararg-list 183fe270817SBram Moolenaar // With missing optional arguments we get: 184fe270817SBram Moolenaar // normal_arg 185fe270817SBram Moolenaar // After creating the list 186fe270817SBram Moolenaar // normal_arg 187fe270817SBram Moolenaar // (space for optional_arg) 188fe270817SBram Moolenaar // vararg-list 1891378fbc4SBram Moolenaar vararg_count = argcount - ufunc->uf_args.ga_len; 1901378fbc4SBram Moolenaar if (vararg_count < 0) 1911378fbc4SBram Moolenaar vararg_count = 0; 1921378fbc4SBram Moolenaar else 1931378fbc4SBram Moolenaar argcount -= vararg_count; 194fe270817SBram Moolenaar if (exe_newlist(vararg_count, ectx) == FAIL) 1951378fbc4SBram Moolenaar return FAIL; 196fe270817SBram Moolenaar 197fe270817SBram Moolenaar vararg_count = 1; 1981378fbc4SBram Moolenaar } 1991378fbc4SBram Moolenaar 200fe270817SBram Moolenaar arg_to_add = ufunc->uf_args.ga_len - argcount; 2011378fbc4SBram Moolenaar if (arg_to_add < 0) 2021378fbc4SBram Moolenaar { 2031378fbc4SBram Moolenaar iemsg("Argument count wrong?"); 2041378fbc4SBram Moolenaar return FAIL; 2051378fbc4SBram Moolenaar } 206bf67ea1aSBram Moolenaar if (ga_grow(&ectx->ec_stack, arg_to_add + 3 207bf67ea1aSBram Moolenaar + dfunc->df_varcount + dfunc->df_closure_count) == FAIL) 2088a7d6542SBram Moolenaar return FAIL; 2098a7d6542SBram Moolenaar 210fe270817SBram Moolenaar // Move the vararg-list to below the missing optional arguments. 211fe270817SBram Moolenaar if (vararg_count > 0 && arg_to_add > 0) 212fe270817SBram Moolenaar *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1); 213170fcfcfSBram Moolenaar 214170fcfcfSBram Moolenaar // Reserve space for omitted optional arguments, filled in soon. 2151378fbc4SBram Moolenaar for (idx = 0; idx < arg_to_add; ++idx) 216fe270817SBram Moolenaar STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN; 2171378fbc4SBram Moolenaar ectx->ec_stack.ga_len += arg_to_add; 2188a7d6542SBram Moolenaar 2198a7d6542SBram Moolenaar // Store current execution state in stack frame for ISN_RETURN. 2208a7d6542SBram Moolenaar STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx; 2218a7d6542SBram Moolenaar STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx; 222bf67ea1aSBram Moolenaar STACK_TV_BOT(2)->vval.v_number = ectx->ec_frame_idx; 223bf67ea1aSBram Moolenaar ectx->ec_frame_idx = ectx->ec_stack.ga_len; 2248a7d6542SBram Moolenaar 2258a7d6542SBram Moolenaar // Initialize local variables 226bf67ea1aSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount + dfunc->df_closure_count; ++idx) 2278a7d6542SBram Moolenaar STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN; 228bf67ea1aSBram Moolenaar ectx->ec_stack.ga_len += STACK_FRAME_SIZE 229bf67ea1aSBram Moolenaar + dfunc->df_varcount + dfunc->df_closure_count; 2308a7d6542SBram Moolenaar 2318a7d6542SBram Moolenaar // Set execution state to the start of the called function. 2328a7d6542SBram Moolenaar ectx->ec_dfunc_idx = cdf_idx; 2338a7d6542SBram Moolenaar ectx->ec_instr = dfunc->df_instr; 234c620c055SBram Moolenaar entry = estack_push_ufunc(dfunc->df_ufunc, 1); 235c620c055SBram Moolenaar if (entry != NULL) 236c620c055SBram Moolenaar { 237c620c055SBram Moolenaar // Set the script context to the script where the function was defined. 238c620c055SBram Moolenaar // TODO: save more than the SID? 239c620c055SBram Moolenaar entry->es_save_sid = current_sctx.sc_sid; 240c620c055SBram Moolenaar current_sctx.sc_sid = ufunc->uf_script_ctx.sc_sid; 241c620c055SBram Moolenaar } 242170fcfcfSBram Moolenaar 243170fcfcfSBram Moolenaar // Decide where to start execution, handles optional arguments. 244170fcfcfSBram Moolenaar init_instr_idx(ufunc, argcount, ectx); 2458a7d6542SBram Moolenaar 2468a7d6542SBram Moolenaar return OK; 2478a7d6542SBram Moolenaar } 2488a7d6542SBram Moolenaar 2498a7d6542SBram Moolenaar // Get pointer to item in the stack. 2508a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx) 2518a7d6542SBram Moolenaar 2528a7d6542SBram Moolenaar /* 253bf67ea1aSBram Moolenaar * Used when returning from a function: Check if any closure is still 254bf67ea1aSBram Moolenaar * referenced. If so then move the arguments and variables to a separate piece 255bf67ea1aSBram Moolenaar * of stack to be used when the closure is called. 256bf67ea1aSBram Moolenaar * When "free_arguments" is TRUE the arguments are to be freed. 257bf67ea1aSBram Moolenaar * Returns FAIL when out of memory. 258bf67ea1aSBram Moolenaar */ 259bf67ea1aSBram Moolenaar static int 260bf67ea1aSBram Moolenaar handle_closure_in_use(ectx_T *ectx, int free_arguments) 261bf67ea1aSBram Moolenaar { 262bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 263bf67ea1aSBram Moolenaar + ectx->ec_dfunc_idx; 264bf67ea1aSBram Moolenaar int argcount = ufunc_argcount(dfunc->df_ufunc); 265bf67ea1aSBram Moolenaar int top = ectx->ec_frame_idx - argcount; 266bf67ea1aSBram Moolenaar int idx; 267bf67ea1aSBram Moolenaar typval_T *tv; 268bf67ea1aSBram Moolenaar int closure_in_use = FALSE; 269bf67ea1aSBram Moolenaar 270bf67ea1aSBram Moolenaar // Check if any created closure is still in use. 271bf67ea1aSBram Moolenaar for (idx = 0; idx < dfunc->df_closure_count; ++idx) 272bf67ea1aSBram Moolenaar { 273bf67ea1aSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE 274bf67ea1aSBram Moolenaar + dfunc->df_varcount + idx); 275221fcc74SBram Moolenaar if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL 276221fcc74SBram Moolenaar && tv->vval.v_partial->pt_refcount > 1) 277221fcc74SBram Moolenaar { 278221fcc74SBram Moolenaar int refcount = tv->vval.v_partial->pt_refcount; 279221fcc74SBram Moolenaar int i; 280221fcc74SBram Moolenaar 281f821ddaaSBram Moolenaar // A Reference in a local variables doesn't count, it gets 282221fcc74SBram Moolenaar // unreferenced on return. 283221fcc74SBram Moolenaar for (i = 0; i < dfunc->df_varcount; ++i) 284221fcc74SBram Moolenaar { 285221fcc74SBram Moolenaar typval_T *stv = STACK_TV(ectx->ec_frame_idx 286221fcc74SBram Moolenaar + STACK_FRAME_SIZE + i); 287221fcc74SBram Moolenaar if (stv->v_type == VAR_PARTIAL 288221fcc74SBram Moolenaar && tv->vval.v_partial == stv->vval.v_partial) 289221fcc74SBram Moolenaar --refcount; 290221fcc74SBram Moolenaar } 291221fcc74SBram Moolenaar if (refcount > 1) 292f7779c63SBram Moolenaar { 293bf67ea1aSBram Moolenaar closure_in_use = TRUE; 294f7779c63SBram Moolenaar break; 295f7779c63SBram Moolenaar } 296bf67ea1aSBram Moolenaar } 297221fcc74SBram Moolenaar } 298bf67ea1aSBram Moolenaar 299bf67ea1aSBram Moolenaar if (closure_in_use) 300bf67ea1aSBram Moolenaar { 301bf67ea1aSBram Moolenaar funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T); 302bf67ea1aSBram Moolenaar typval_T *stack; 303bf67ea1aSBram Moolenaar 304bf67ea1aSBram Moolenaar // A closure is using the arguments and/or local variables. 305bf67ea1aSBram Moolenaar // Move them to the called function. 306bf67ea1aSBram Moolenaar if (funcstack == NULL) 307bf67ea1aSBram Moolenaar return FAIL; 308bf67ea1aSBram Moolenaar funcstack->fs_ga.ga_len = argcount + STACK_FRAME_SIZE 309bf67ea1aSBram Moolenaar + dfunc->df_varcount; 310bf67ea1aSBram Moolenaar stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len); 311bf67ea1aSBram Moolenaar funcstack->fs_ga.ga_data = stack; 312bf67ea1aSBram Moolenaar if (stack == NULL) 313bf67ea1aSBram Moolenaar { 314bf67ea1aSBram Moolenaar vim_free(funcstack); 315bf67ea1aSBram Moolenaar return FAIL; 316bf67ea1aSBram Moolenaar } 317bf67ea1aSBram Moolenaar 318bf67ea1aSBram Moolenaar // Move or copy the arguments. 319bf67ea1aSBram Moolenaar for (idx = 0; idx < argcount; ++idx) 320bf67ea1aSBram Moolenaar { 321bf67ea1aSBram Moolenaar tv = STACK_TV(top + idx); 322bf67ea1aSBram Moolenaar if (free_arguments) 323bf67ea1aSBram Moolenaar { 324bf67ea1aSBram Moolenaar *(stack + idx) = *tv; 325bf67ea1aSBram Moolenaar tv->v_type = VAR_UNKNOWN; 326bf67ea1aSBram Moolenaar } 327bf67ea1aSBram Moolenaar else 328bf67ea1aSBram Moolenaar copy_tv(tv, stack + idx); 329bf67ea1aSBram Moolenaar } 330bf67ea1aSBram Moolenaar // Move the local variables. 331bf67ea1aSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 332bf67ea1aSBram Moolenaar { 333bf67ea1aSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx); 334f821ddaaSBram Moolenaar 335f821ddaaSBram Moolenaar // Do not copy a partial created for a local function. 336f821ddaaSBram Moolenaar // TODO: this won't work if the closure actually uses it. But when 337f821ddaaSBram Moolenaar // keeping it it gets complicated: it will create a reference cycle 338f821ddaaSBram Moolenaar // inside the partial, thus needs special handling for garbage 339f821ddaaSBram Moolenaar // collection. 340f821ddaaSBram Moolenaar if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) 341f821ddaaSBram Moolenaar { 342f821ddaaSBram Moolenaar int i; 343f821ddaaSBram Moolenaar typval_T *ctv; 344f821ddaaSBram Moolenaar 345f821ddaaSBram Moolenaar for (i = 0; i < dfunc->df_closure_count; ++i) 346f821ddaaSBram Moolenaar { 347f821ddaaSBram Moolenaar ctv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE 348f821ddaaSBram Moolenaar + dfunc->df_varcount + i); 349f821ddaaSBram Moolenaar if (tv->vval.v_partial == ctv->vval.v_partial) 350f821ddaaSBram Moolenaar break; 351f821ddaaSBram Moolenaar } 352f821ddaaSBram Moolenaar if (i < dfunc->df_closure_count) 353f821ddaaSBram Moolenaar { 354f821ddaaSBram Moolenaar (stack + argcount + STACK_FRAME_SIZE + idx)->v_type = 355f821ddaaSBram Moolenaar VAR_UNKNOWN; 356f821ddaaSBram Moolenaar continue; 357f821ddaaSBram Moolenaar } 358f821ddaaSBram Moolenaar } 359f821ddaaSBram Moolenaar 360bf67ea1aSBram Moolenaar *(stack + argcount + STACK_FRAME_SIZE + idx) = *tv; 361bf67ea1aSBram Moolenaar tv->v_type = VAR_UNKNOWN; 362bf67ea1aSBram Moolenaar } 363bf67ea1aSBram Moolenaar 364bf67ea1aSBram Moolenaar for (idx = 0; idx < dfunc->df_closure_count; ++idx) 365bf67ea1aSBram Moolenaar { 366bf67ea1aSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE 367bf67ea1aSBram Moolenaar + dfunc->df_varcount + idx); 368f7779c63SBram Moolenaar if (tv->v_type == VAR_PARTIAL) 369bf67ea1aSBram Moolenaar { 370f7779c63SBram Moolenaar partial_T *partial = tv->vval.v_partial; 371f7779c63SBram Moolenaar 372f7779c63SBram Moolenaar if (partial->pt_refcount > 1) 373f7779c63SBram Moolenaar { 374bf67ea1aSBram Moolenaar ++funcstack->fs_refcount; 375f7779c63SBram Moolenaar partial->pt_funcstack = funcstack; 376f7779c63SBram Moolenaar partial->pt_ectx_stack = &funcstack->fs_ga; 377f7779c63SBram Moolenaar partial->pt_ectx_frame = ectx->ec_frame_idx - top; 378f7779c63SBram Moolenaar } 379bf67ea1aSBram Moolenaar } 380bf67ea1aSBram Moolenaar } 381bf67ea1aSBram Moolenaar } 382bf67ea1aSBram Moolenaar 383bf67ea1aSBram Moolenaar return OK; 384bf67ea1aSBram Moolenaar } 385bf67ea1aSBram Moolenaar 386bf67ea1aSBram Moolenaar /* 3878a7d6542SBram Moolenaar * Return from the current function. 3888a7d6542SBram Moolenaar */ 389bf67ea1aSBram Moolenaar static int 3908a7d6542SBram Moolenaar func_return(ectx_T *ectx) 3918a7d6542SBram Moolenaar { 3928a7d6542SBram Moolenaar int idx; 393bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 394bf67ea1aSBram Moolenaar + ectx->ec_dfunc_idx; 395bf67ea1aSBram Moolenaar int argcount = ufunc_argcount(dfunc->df_ufunc); 396bf67ea1aSBram Moolenaar int top = ectx->ec_frame_idx - argcount; 397c620c055SBram Moolenaar estack_T *entry; 3988a7d6542SBram Moolenaar 3998a7d6542SBram Moolenaar // execution context goes one level up 400c620c055SBram Moolenaar entry = estack_pop(); 401c620c055SBram Moolenaar if (entry != NULL) 402c620c055SBram Moolenaar current_sctx.sc_sid = entry->es_save_sid; 4038a7d6542SBram Moolenaar 404bf67ea1aSBram Moolenaar if (handle_closure_in_use(ectx, TRUE) == FAIL) 405bf67ea1aSBram Moolenaar return FAIL; 406bf67ea1aSBram Moolenaar 407bf67ea1aSBram Moolenaar // Clear the arguments. 408bf67ea1aSBram Moolenaar for (idx = top; idx < ectx->ec_frame_idx; ++idx) 409bf67ea1aSBram Moolenaar clear_tv(STACK_TV(idx)); 410bf67ea1aSBram Moolenaar 411bf67ea1aSBram Moolenaar // Clear local variables and temp values, but not the return value. 412bf67ea1aSBram Moolenaar for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE; 4138a7d6542SBram Moolenaar idx < ectx->ec_stack.ga_len - 1; ++idx) 4148a7d6542SBram Moolenaar clear_tv(STACK_TV(idx)); 415170fcfcfSBram Moolenaar 416170fcfcfSBram Moolenaar // Restore the previous frame. 417bf67ea1aSBram Moolenaar ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame_idx)->vval.v_number; 418bf67ea1aSBram Moolenaar ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx + 1)->vval.v_number; 419bf67ea1aSBram Moolenaar ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx + 2)->vval.v_number; 4208a7d6542SBram Moolenaar dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; 4218a7d6542SBram Moolenaar ectx->ec_instr = dfunc->df_instr; 422170fcfcfSBram Moolenaar 423170fcfcfSBram Moolenaar // Reset the stack to the position before the call, move the return value 424170fcfcfSBram Moolenaar // to the top of the stack. 425170fcfcfSBram Moolenaar idx = ectx->ec_stack.ga_len - 1; 426170fcfcfSBram Moolenaar ectx->ec_stack.ga_len = top + 1; 427170fcfcfSBram Moolenaar *STACK_TV_BOT(-1) = *STACK_TV(idx); 428bf67ea1aSBram Moolenaar 429bf67ea1aSBram Moolenaar return OK; 4308a7d6542SBram Moolenaar } 4318a7d6542SBram Moolenaar 4328a7d6542SBram Moolenaar #undef STACK_TV 4338a7d6542SBram Moolenaar 4348a7d6542SBram Moolenaar /* 4358a7d6542SBram Moolenaar * Prepare arguments and rettv for calling a builtin or user function. 4368a7d6542SBram Moolenaar */ 4378a7d6542SBram Moolenaar static int 4388a7d6542SBram Moolenaar call_prepare(int argcount, typval_T *argvars, ectx_T *ectx) 4398a7d6542SBram Moolenaar { 4408a7d6542SBram Moolenaar int idx; 4418a7d6542SBram Moolenaar typval_T *tv; 4428a7d6542SBram Moolenaar 4438a7d6542SBram Moolenaar // Move arguments from bottom of the stack to argvars[] and add terminator. 4448a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 4458a7d6542SBram Moolenaar argvars[idx] = *STACK_TV_BOT(idx - argcount); 4468a7d6542SBram Moolenaar argvars[argcount].v_type = VAR_UNKNOWN; 4478a7d6542SBram Moolenaar 4488a7d6542SBram Moolenaar // Result replaces the arguments on the stack. 4498a7d6542SBram Moolenaar if (argcount > 0) 4508a7d6542SBram Moolenaar ectx->ec_stack.ga_len -= argcount - 1; 451270d0388SBram Moolenaar else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) 4528a7d6542SBram Moolenaar return FAIL; 4538a7d6542SBram Moolenaar else 4548a7d6542SBram Moolenaar ++ectx->ec_stack.ga_len; 4558a7d6542SBram Moolenaar 4568a7d6542SBram Moolenaar // Default return value is zero. 4578a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 4588a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 4598a7d6542SBram Moolenaar tv->vval.v_number = 0; 4608a7d6542SBram Moolenaar 4618a7d6542SBram Moolenaar return OK; 4628a7d6542SBram Moolenaar } 4638a7d6542SBram Moolenaar 46408f7a41bSBram Moolenaar // Ugly global to avoid passing the execution context around through many 46508f7a41bSBram Moolenaar // layers. 46608f7a41bSBram Moolenaar static ectx_T *current_ectx = NULL; 46708f7a41bSBram Moolenaar 4688a7d6542SBram Moolenaar /* 4698a7d6542SBram Moolenaar * Call a builtin function by index. 4708a7d6542SBram Moolenaar */ 4718a7d6542SBram Moolenaar static int 4728a7d6542SBram Moolenaar call_bfunc(int func_idx, int argcount, ectx_T *ectx) 4738a7d6542SBram Moolenaar { 4748a7d6542SBram Moolenaar typval_T argvars[MAX_FUNC_ARGS]; 4758a7d6542SBram Moolenaar int idx; 4768a1c1013SBram Moolenaar int did_emsg_before = did_emsg; 47708f7a41bSBram Moolenaar ectx_T *prev_ectx = current_ectx; 4788a7d6542SBram Moolenaar 4798a7d6542SBram Moolenaar if (call_prepare(argcount, argvars, ectx) == FAIL) 4808a7d6542SBram Moolenaar return FAIL; 4818a7d6542SBram Moolenaar 48208f7a41bSBram Moolenaar // Call the builtin function. Set "current_ectx" so that when it 48308f7a41bSBram Moolenaar // recursively invokes call_def_function() a closure context can be set. 48408f7a41bSBram Moolenaar current_ectx = ectx; 4858a7d6542SBram Moolenaar call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1)); 48608f7a41bSBram Moolenaar current_ectx = prev_ectx; 4878a7d6542SBram Moolenaar 4888a7d6542SBram Moolenaar // Clear the arguments. 4898a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 4908a7d6542SBram Moolenaar clear_tv(&argvars[idx]); 491015f4267SBram Moolenaar 4928a1c1013SBram Moolenaar if (did_emsg != did_emsg_before) 493015f4267SBram Moolenaar return FAIL; 4948a7d6542SBram Moolenaar return OK; 4958a7d6542SBram Moolenaar } 4968a7d6542SBram Moolenaar 4978a7d6542SBram Moolenaar /* 4988a7d6542SBram Moolenaar * Execute a user defined function. 4997eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 5008a7d6542SBram Moolenaar */ 5018a7d6542SBram Moolenaar static int 5027eeefd4aSBram Moolenaar call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr) 5038a7d6542SBram Moolenaar { 5048a7d6542SBram Moolenaar typval_T argvars[MAX_FUNC_ARGS]; 5058a7d6542SBram Moolenaar funcexe_T funcexe; 5068a7d6542SBram Moolenaar int error; 5078a7d6542SBram Moolenaar int idx; 5088a7d6542SBram Moolenaar 5090cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_TO_BE_COMPILED 510822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL) 511822ba247SBram Moolenaar return FAIL; 5120cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_COMPILED) 5137eeefd4aSBram Moolenaar { 5147eeefd4aSBram Moolenaar // The function has been compiled, can call it quickly. For a function 5157eeefd4aSBram Moolenaar // that was defined later: we can call it directly next time. 5167eeefd4aSBram Moolenaar if (iptr != NULL) 5177eeefd4aSBram Moolenaar { 51820431c9dSBram Moolenaar delete_instr(iptr); 5197eeefd4aSBram Moolenaar iptr->isn_type = ISN_DCALL; 5207eeefd4aSBram Moolenaar iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx; 5217eeefd4aSBram Moolenaar iptr->isn_arg.dfunc.cdf_argcount = argcount; 5227eeefd4aSBram Moolenaar } 5238a7d6542SBram Moolenaar return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx); 5247eeefd4aSBram Moolenaar } 5258a7d6542SBram Moolenaar 5268a7d6542SBram Moolenaar if (call_prepare(argcount, argvars, ectx) == FAIL) 5278a7d6542SBram Moolenaar return FAIL; 528a80faa89SBram Moolenaar CLEAR_FIELD(funcexe); 5298a7d6542SBram Moolenaar funcexe.evaluate = TRUE; 5308a7d6542SBram Moolenaar 5318a7d6542SBram Moolenaar // Call the user function. Result goes in last position on the stack. 5328a7d6542SBram Moolenaar // TODO: add selfdict if there is one 5338a7d6542SBram Moolenaar error = call_user_func_check(ufunc, argcount, argvars, 5348a7d6542SBram Moolenaar STACK_TV_BOT(-1), &funcexe, NULL); 5358a7d6542SBram Moolenaar 5368a7d6542SBram Moolenaar // Clear the arguments. 5378a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 5388a7d6542SBram Moolenaar clear_tv(&argvars[idx]); 5398a7d6542SBram Moolenaar 5408a7d6542SBram Moolenaar if (error != FCERR_NONE) 5418a7d6542SBram Moolenaar { 5428a7d6542SBram Moolenaar user_func_error(error, ufunc->uf_name); 5438a7d6542SBram Moolenaar return FAIL; 5448a7d6542SBram Moolenaar } 5458a7d6542SBram Moolenaar return OK; 5468a7d6542SBram Moolenaar } 5478a7d6542SBram Moolenaar 5488a7d6542SBram Moolenaar /* 5498a7d6542SBram Moolenaar * Execute a function by "name". 5508a7d6542SBram Moolenaar * This can be a builtin function or a user function. 5517eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 5528a7d6542SBram Moolenaar * Returns FAIL if not found without an error message. 5538a7d6542SBram Moolenaar */ 5548a7d6542SBram Moolenaar static int 5557eeefd4aSBram Moolenaar call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) 5568a7d6542SBram Moolenaar { 5578a7d6542SBram Moolenaar ufunc_T *ufunc; 5588a7d6542SBram Moolenaar 5598a7d6542SBram Moolenaar if (builtin_function(name, -1)) 5608a7d6542SBram Moolenaar { 5618a7d6542SBram Moolenaar int func_idx = find_internal_func(name); 5628a7d6542SBram Moolenaar 5638a7d6542SBram Moolenaar if (func_idx < 0) 5648a7d6542SBram Moolenaar return FAIL; 565389df259SBram Moolenaar if (check_internal_func(func_idx, argcount) < 0) 5668a7d6542SBram Moolenaar return FAIL; 5678a7d6542SBram Moolenaar return call_bfunc(func_idx, argcount, ectx); 5688a7d6542SBram Moolenaar } 5698a7d6542SBram Moolenaar 5704c17ad94SBram Moolenaar ufunc = find_func(name, FALSE, NULL); 5718a7d6542SBram Moolenaar if (ufunc != NULL) 5727eeefd4aSBram Moolenaar return call_ufunc(ufunc, argcount, ectx, iptr); 5738a7d6542SBram Moolenaar 5748a7d6542SBram Moolenaar return FAIL; 5758a7d6542SBram Moolenaar } 5768a7d6542SBram Moolenaar 5778a7d6542SBram Moolenaar static int 578a90afb9aSBram Moolenaar call_partial(typval_T *tv, int argcount_arg, ectx_T *ectx) 5798a7d6542SBram Moolenaar { 580a90afb9aSBram Moolenaar int argcount = argcount_arg; 581bd5da371SBram Moolenaar char_u *name = NULL; 5828a7d6542SBram Moolenaar int called_emsg_before = called_emsg; 5838a7d6542SBram Moolenaar 5848a7d6542SBram Moolenaar if (tv->v_type == VAR_PARTIAL) 5858a7d6542SBram Moolenaar { 5868a7d6542SBram Moolenaar partial_T *pt = tv->vval.v_partial; 587a90afb9aSBram Moolenaar int i; 588a90afb9aSBram Moolenaar 589a90afb9aSBram Moolenaar if (pt->pt_argc > 0) 590a90afb9aSBram Moolenaar { 591a90afb9aSBram Moolenaar // Make space for arguments from the partial, shift the "argcount" 592a90afb9aSBram Moolenaar // arguments up. 593a90afb9aSBram Moolenaar if (ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL) 594a90afb9aSBram Moolenaar return FAIL; 595a90afb9aSBram Moolenaar for (i = 1; i <= argcount; ++i) 596a90afb9aSBram Moolenaar *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i); 597a90afb9aSBram Moolenaar ectx->ec_stack.ga_len += pt->pt_argc; 598a90afb9aSBram Moolenaar argcount += pt->pt_argc; 599a90afb9aSBram Moolenaar 600a90afb9aSBram Moolenaar // copy the arguments from the partial onto the stack 601a90afb9aSBram Moolenaar for (i = 0; i < pt->pt_argc; ++i) 602a90afb9aSBram Moolenaar copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i)); 603a90afb9aSBram Moolenaar } 6048a7d6542SBram Moolenaar 6058a7d6542SBram Moolenaar if (pt->pt_func != NULL) 606f7779c63SBram Moolenaar { 607f7779c63SBram Moolenaar int ret = call_ufunc(pt->pt_func, argcount, ectx, NULL); 608f7779c63SBram Moolenaar 609f7779c63SBram Moolenaar // closure may need the function context where it was defined 610f7779c63SBram Moolenaar ectx->ec_outer_stack = pt->pt_ectx_stack; 611f7779c63SBram Moolenaar ectx->ec_outer_frame = pt->pt_ectx_frame; 612f7779c63SBram Moolenaar 613f7779c63SBram Moolenaar return ret; 614f7779c63SBram Moolenaar } 6158a7d6542SBram Moolenaar name = pt->pt_name; 6168a7d6542SBram Moolenaar } 617bd5da371SBram Moolenaar else if (tv->v_type == VAR_FUNC) 6188a7d6542SBram Moolenaar name = tv->vval.v_string; 619bd5da371SBram Moolenaar if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL) 6208a7d6542SBram Moolenaar { 6218a7d6542SBram Moolenaar if (called_emsg == called_emsg_before) 622015f4267SBram Moolenaar semsg(_(e_unknownfunc), 623015f4267SBram Moolenaar name == NULL ? (char_u *)"[unknown]" : name); 6248a7d6542SBram Moolenaar return FAIL; 6258a7d6542SBram Moolenaar } 6268a7d6542SBram Moolenaar return OK; 6278a7d6542SBram Moolenaar } 6288a7d6542SBram Moolenaar 6298a7d6542SBram Moolenaar /* 6300bbf722aSBram Moolenaar * Store "tv" in variable "name". 6310bbf722aSBram Moolenaar * This is for s: and g: variables. 6320bbf722aSBram Moolenaar */ 6330bbf722aSBram Moolenaar static void 6340bbf722aSBram Moolenaar store_var(char_u *name, typval_T *tv) 6350bbf722aSBram Moolenaar { 6360bbf722aSBram Moolenaar funccal_entry_T entry; 6370bbf722aSBram Moolenaar 6380bbf722aSBram Moolenaar save_funccal(&entry); 6395deeb3f1SBram Moolenaar set_var_const(name, NULL, tv, FALSE, LET_NO_COMMAND); 6400bbf722aSBram Moolenaar restore_funccal(); 6410bbf722aSBram Moolenaar } 6420bbf722aSBram Moolenaar 643d3aac291SBram Moolenaar 6440bbf722aSBram Moolenaar /* 6458a7d6542SBram Moolenaar * Execute a function by "name". 6468a7d6542SBram Moolenaar * This can be a builtin function, user function or a funcref. 6477eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 6488a7d6542SBram Moolenaar */ 6498a7d6542SBram Moolenaar static int 6507eeefd4aSBram Moolenaar call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) 6518a7d6542SBram Moolenaar { 6528a7d6542SBram Moolenaar int called_emsg_before = called_emsg; 6538a7d6542SBram Moolenaar 6547eeefd4aSBram Moolenaar if (call_by_name(name, argcount, ectx, iptr) == FAIL 6558a7d6542SBram Moolenaar && called_emsg == called_emsg_before) 6568a7d6542SBram Moolenaar { 6571df8b3fbSBram Moolenaar dictitem_T *v; 6581df8b3fbSBram Moolenaar 6591df8b3fbSBram Moolenaar v = find_var(name, NULL, FALSE); 6601df8b3fbSBram Moolenaar if (v == NULL) 6611df8b3fbSBram Moolenaar { 6621df8b3fbSBram Moolenaar semsg(_(e_unknownfunc), name); 6638a7d6542SBram Moolenaar return FAIL; 6648a7d6542SBram Moolenaar } 6651df8b3fbSBram Moolenaar if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC) 6661df8b3fbSBram Moolenaar { 6671df8b3fbSBram Moolenaar semsg(_(e_unknownfunc), name); 6681df8b3fbSBram Moolenaar return FAIL; 6691df8b3fbSBram Moolenaar } 6701df8b3fbSBram Moolenaar return call_partial(&v->di_tv, argcount, ectx); 6711df8b3fbSBram Moolenaar } 6728a7d6542SBram Moolenaar return OK; 6738a7d6542SBram Moolenaar } 6748a7d6542SBram Moolenaar 6758a7d6542SBram Moolenaar /* 6768a7d6542SBram Moolenaar * Call a "def" function from old Vim script. 6778a7d6542SBram Moolenaar * Return OK or FAIL. 6788a7d6542SBram Moolenaar */ 6798a7d6542SBram Moolenaar int 6808a7d6542SBram Moolenaar call_def_function( 6818a7d6542SBram Moolenaar ufunc_T *ufunc, 68223e03252SBram Moolenaar int argc_arg, // nr of arguments 6838a7d6542SBram Moolenaar typval_T *argv, // arguments 6846f5b6dfbSBram Moolenaar partial_T *partial, // optional partial for context 6858a7d6542SBram Moolenaar typval_T *rettv) // return value 6868a7d6542SBram Moolenaar { 6878a7d6542SBram Moolenaar ectx_T ectx; // execution context 68823e03252SBram Moolenaar int argc = argc_arg; 689bf67ea1aSBram Moolenaar int initial_frame_idx; 6908a7d6542SBram Moolenaar typval_T *tv; 6918a7d6542SBram Moolenaar int idx; 6928a7d6542SBram Moolenaar int ret = FAIL; 693170fcfcfSBram Moolenaar int defcount = ufunc->uf_args.ga_len - argc; 694a26b9700SBram Moolenaar int save_sc_version = current_sctx.sc_version; 695270d0388SBram Moolenaar int breakcheck_count = 0; 69625e0f586SBram Moolenaar int called_emsg_before = called_emsg; 6978a7d6542SBram Moolenaar 6988a7d6542SBram Moolenaar // Get pointer to item in the stack. 6998a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) 7008a7d6542SBram Moolenaar 7018a7d6542SBram Moolenaar // Get pointer to item at the bottom of the stack, -1 is the bottom. 7028a7d6542SBram Moolenaar #undef STACK_TV_BOT 7038a7d6542SBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx) 7048a7d6542SBram Moolenaar 7051378fbc4SBram Moolenaar // Get pointer to a local variable on the stack. Negative for arguments. 706bf67ea1aSBram Moolenaar #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx) 7078a7d6542SBram Moolenaar 708c8cd2b34SBram Moolenaar // Like STACK_TV_VAR but use the outer scope 709c8cd2b34SBram Moolenaar #define STACK_OUT_TV_VAR(idx) (((typval_T *)ectx.ec_outer_stack->ga_data) + ectx.ec_outer_frame + STACK_FRAME_SIZE + idx) 710c8cd2b34SBram Moolenaar 7110cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_NOT_COMPILED 7120cb5bcf5SBram Moolenaar || (ufunc->uf_def_status == UF_TO_BE_COMPILED 713822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL)) 71425e0f586SBram Moolenaar { 71525e0f586SBram Moolenaar if (called_emsg == called_emsg_before) 71625e0f586SBram Moolenaar semsg(_("E1091: Function is not compiled: %s"), 71725e0f586SBram Moolenaar ufunc->uf_name_exp == NULL 71825e0f586SBram Moolenaar ? ufunc->uf_name : ufunc->uf_name_exp); 719822ba247SBram Moolenaar return FAIL; 72025e0f586SBram Moolenaar } 721822ba247SBram Moolenaar 72209689a02SBram Moolenaar { 723822ba247SBram Moolenaar // Check the function was really compiled. 72409689a02SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 72509689a02SBram Moolenaar + ufunc->uf_dfunc_idx; 72609689a02SBram Moolenaar if (dfunc->df_instr == NULL) 72709689a02SBram Moolenaar return FAIL; 72809689a02SBram Moolenaar } 7298a7d6542SBram Moolenaar 7303b6a6eb7SBram Moolenaar CLEAR_FIELD(ectx); 7313b6a6eb7SBram Moolenaar ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; 7323b6a6eb7SBram Moolenaar ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); 7333b6a6eb7SBram Moolenaar if (ga_grow(&ectx.ec_stack, 20) == FAIL) 7343b6a6eb7SBram Moolenaar return FAIL; 7358a7d6542SBram Moolenaar ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); 7368a7d6542SBram Moolenaar 7378a7d6542SBram Moolenaar // Put arguments on the stack. 7388a7d6542SBram Moolenaar for (idx = 0; idx < argc; ++idx) 7398a7d6542SBram Moolenaar { 740*65b9545fSBram Moolenaar if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len 741*65b9545fSBram Moolenaar && check_argtype(ufunc->uf_arg_types[idx], &argv[idx]) == FAIL) 742*65b9545fSBram Moolenaar goto failed_early; 7438a7d6542SBram Moolenaar copy_tv(&argv[idx], STACK_TV_BOT(0)); 7448a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 7458a7d6542SBram Moolenaar } 74623e03252SBram Moolenaar 74723e03252SBram Moolenaar // Turn varargs into a list. Empty list if no args. 74823e03252SBram Moolenaar if (ufunc->uf_va_name != NULL) 74923e03252SBram Moolenaar { 75023e03252SBram Moolenaar int vararg_count = argc - ufunc->uf_args.ga_len; 75123e03252SBram Moolenaar 75223e03252SBram Moolenaar if (vararg_count < 0) 75323e03252SBram Moolenaar vararg_count = 0; 75423e03252SBram Moolenaar else 75523e03252SBram Moolenaar argc -= vararg_count; 75623e03252SBram Moolenaar if (exe_newlist(vararg_count, &ectx) == FAIL) 7571a2f4bf6SBram Moolenaar goto failed_early; 75823e03252SBram Moolenaar if (defcount > 0) 75923e03252SBram Moolenaar // Move varargs list to below missing default arguments. 76023e03252SBram Moolenaar *STACK_TV_BOT(defcount- 1) = *STACK_TV_BOT(-1); 76123e03252SBram Moolenaar --ectx.ec_stack.ga_len; 76223e03252SBram Moolenaar } 76323e03252SBram Moolenaar 764170fcfcfSBram Moolenaar // Make space for omitted arguments, will store default value below. 76523e03252SBram Moolenaar // Any varargs list goes after them. 766170fcfcfSBram Moolenaar if (defcount > 0) 767170fcfcfSBram Moolenaar for (idx = 0; idx < defcount; ++idx) 768170fcfcfSBram Moolenaar { 769170fcfcfSBram Moolenaar STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; 770170fcfcfSBram Moolenaar ++ectx.ec_stack.ga_len; 771170fcfcfSBram Moolenaar } 77223e03252SBram Moolenaar if (ufunc->uf_va_name != NULL) 77323e03252SBram Moolenaar ++ectx.ec_stack.ga_len; 7748a7d6542SBram Moolenaar 7758a7d6542SBram Moolenaar // Frame pointer points to just after arguments. 776bf67ea1aSBram Moolenaar ectx.ec_frame_idx = ectx.ec_stack.ga_len; 777bf67ea1aSBram Moolenaar initial_frame_idx = ectx.ec_frame_idx; 7788a7d6542SBram Moolenaar 7796f5b6dfbSBram Moolenaar if (partial != NULL) 7806f5b6dfbSBram Moolenaar { 78108f7a41bSBram Moolenaar if (partial->pt_ectx_stack == NULL && current_ectx != NULL) 78208f7a41bSBram Moolenaar { 78308f7a41bSBram Moolenaar // TODO: is this always the right way? 78408f7a41bSBram Moolenaar ectx.ec_outer_stack = ¤t_ectx->ec_stack; 78508f7a41bSBram Moolenaar ectx.ec_outer_frame = current_ectx->ec_frame_idx; 78608f7a41bSBram Moolenaar } 78708f7a41bSBram Moolenaar else 78808f7a41bSBram Moolenaar { 7896f5b6dfbSBram Moolenaar ectx.ec_outer_stack = partial->pt_ectx_stack; 7906f5b6dfbSBram Moolenaar ectx.ec_outer_frame = partial->pt_ectx_frame; 7916f5b6dfbSBram Moolenaar } 79208f7a41bSBram Moolenaar } 7936f5b6dfbSBram Moolenaar 7948a7d6542SBram Moolenaar // dummy frame entries 7958a7d6542SBram Moolenaar for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) 7968a7d6542SBram Moolenaar { 7978a7d6542SBram Moolenaar STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; 7988a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 7998a7d6542SBram Moolenaar } 8008a7d6542SBram Moolenaar 801bd5da371SBram Moolenaar { 802bf67ea1aSBram Moolenaar // Reserve space for local variables and closure references. 803bd5da371SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 804bd5da371SBram Moolenaar + ufunc->uf_dfunc_idx; 805bf67ea1aSBram Moolenaar int count = dfunc->df_varcount + dfunc->df_closure_count; 806bd5da371SBram Moolenaar 807bf67ea1aSBram Moolenaar for (idx = 0; idx < count; ++idx) 8088a7d6542SBram Moolenaar STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; 809bf67ea1aSBram Moolenaar ectx.ec_stack.ga_len += count; 8108a7d6542SBram Moolenaar 8118a7d6542SBram Moolenaar ectx.ec_instr = dfunc->df_instr; 812bd5da371SBram Moolenaar } 813170fcfcfSBram Moolenaar 814a26b9700SBram Moolenaar // Commands behave like vim9script. 815a26b9700SBram Moolenaar current_sctx.sc_version = SCRIPT_VERSION_VIM9; 816a26b9700SBram Moolenaar 817170fcfcfSBram Moolenaar // Decide where to start execution, handles optional arguments. 818170fcfcfSBram Moolenaar init_instr_idx(ufunc, argc, &ectx); 819170fcfcfSBram Moolenaar 8208a7d6542SBram Moolenaar for (;;) 8218a7d6542SBram Moolenaar { 8228a7d6542SBram Moolenaar isn_T *iptr; 82320431c9dSBram Moolenaar 824270d0388SBram Moolenaar if (++breakcheck_count >= 100) 825270d0388SBram Moolenaar { 826270d0388SBram Moolenaar line_breakcheck(); 827270d0388SBram Moolenaar breakcheck_count = 0; 828270d0388SBram Moolenaar } 82920431c9dSBram Moolenaar if (got_int) 83020431c9dSBram Moolenaar { 83120431c9dSBram Moolenaar // Turn CTRL-C into an exception. 83220431c9dSBram Moolenaar got_int = FALSE; 83397acfc78SBram Moolenaar if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL) 83420431c9dSBram Moolenaar goto failed; 83520431c9dSBram Moolenaar did_throw = TRUE; 83620431c9dSBram Moolenaar } 8378a7d6542SBram Moolenaar 838a26b9700SBram Moolenaar if (did_emsg && msg_list != NULL && *msg_list != NULL) 839a26b9700SBram Moolenaar { 840a26b9700SBram Moolenaar // Turn an error message into an exception. 841a26b9700SBram Moolenaar did_emsg = FALSE; 842a26b9700SBram Moolenaar if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL) 843a26b9700SBram Moolenaar goto failed; 844a26b9700SBram Moolenaar did_throw = TRUE; 845a26b9700SBram Moolenaar *msg_list = NULL; 846a26b9700SBram Moolenaar } 847a26b9700SBram Moolenaar 8488a7d6542SBram Moolenaar if (did_throw && !ectx.ec_in_catch) 8498a7d6542SBram Moolenaar { 8508a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 85120431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 8528a7d6542SBram Moolenaar 8538a7d6542SBram Moolenaar // An exception jumps to the first catch, finally, or returns from 8548a7d6542SBram Moolenaar // the current function. 8558a7d6542SBram Moolenaar if (trystack->ga_len > 0) 8568a7d6542SBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; 857bf67ea1aSBram Moolenaar if (trycmd != NULL && trycmd->tcd_frame_idx == ectx.ec_frame_idx) 8588a7d6542SBram Moolenaar { 8598a7d6542SBram Moolenaar // jump to ":catch" or ":finally" 8608a7d6542SBram Moolenaar ectx.ec_in_catch = TRUE; 8618a7d6542SBram Moolenaar ectx.ec_iidx = trycmd->tcd_catch_idx; 8628a7d6542SBram Moolenaar } 8638a7d6542SBram Moolenaar else 8648a7d6542SBram Moolenaar { 8658a7d6542SBram Moolenaar // not inside try or need to return from current functions. 866bf67ea1aSBram Moolenaar if (ectx.ec_frame_idx == initial_frame_idx) 8678a7d6542SBram Moolenaar { 8688a7d6542SBram Moolenaar // At the toplevel we are done. Push a dummy return value. 869270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 8708a7d6542SBram Moolenaar goto failed; 8718a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 8728a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 8738a7d6542SBram Moolenaar tv->vval.v_number = 0; 8748a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 875257cc5eeSBram Moolenaar need_rethrow = TRUE; 876bf67ea1aSBram Moolenaar if (handle_closure_in_use(&ectx, FALSE) == FAIL) 877bf67ea1aSBram Moolenaar goto failed; 8788a7d6542SBram Moolenaar goto done; 8798a7d6542SBram Moolenaar } 8808a7d6542SBram Moolenaar 881bf67ea1aSBram Moolenaar if (func_return(&ectx) == FAIL) 882bf67ea1aSBram Moolenaar goto failed; 8838a7d6542SBram Moolenaar } 8848a7d6542SBram Moolenaar continue; 8858a7d6542SBram Moolenaar } 8868a7d6542SBram Moolenaar 8878a7d6542SBram Moolenaar iptr = &ectx.ec_instr[ectx.ec_iidx++]; 8888a7d6542SBram Moolenaar switch (iptr->isn_type) 8898a7d6542SBram Moolenaar { 8908a7d6542SBram Moolenaar // execute Ex command line 8918a7d6542SBram Moolenaar case ISN_EXEC: 8926378c4feSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 8938a7d6542SBram Moolenaar do_cmdline_cmd(iptr->isn_arg.string); 8948a7d6542SBram Moolenaar break; 8958a7d6542SBram Moolenaar 896cfe435d7SBram Moolenaar // execute Ex command from pieces on the stack 897cfe435d7SBram Moolenaar case ISN_EXECCONCAT: 898cfe435d7SBram Moolenaar { 899cfe435d7SBram Moolenaar int count = iptr->isn_arg.number; 9007f6f56f4SBram Moolenaar size_t len = 0; 901cfe435d7SBram Moolenaar int pass; 902cfe435d7SBram Moolenaar int i; 903cfe435d7SBram Moolenaar char_u *cmd = NULL; 904cfe435d7SBram Moolenaar char_u *str; 905cfe435d7SBram Moolenaar 906cfe435d7SBram Moolenaar for (pass = 1; pass <= 2; ++pass) 907cfe435d7SBram Moolenaar { 908cfe435d7SBram Moolenaar for (i = 0; i < count; ++i) 909cfe435d7SBram Moolenaar { 910cfe435d7SBram Moolenaar tv = STACK_TV_BOT(i - count); 911cfe435d7SBram Moolenaar str = tv->vval.v_string; 912cfe435d7SBram Moolenaar if (str != NULL && *str != NUL) 913cfe435d7SBram Moolenaar { 914cfe435d7SBram Moolenaar if (pass == 2) 915cfe435d7SBram Moolenaar STRCPY(cmd + len, str); 916cfe435d7SBram Moolenaar len += STRLEN(str); 917cfe435d7SBram Moolenaar } 918cfe435d7SBram Moolenaar if (pass == 2) 919cfe435d7SBram Moolenaar clear_tv(tv); 920cfe435d7SBram Moolenaar } 921cfe435d7SBram Moolenaar if (pass == 1) 922cfe435d7SBram Moolenaar { 923cfe435d7SBram Moolenaar cmd = alloc(len + 1); 924cfe435d7SBram Moolenaar if (cmd == NULL) 925cfe435d7SBram Moolenaar goto failed; 926cfe435d7SBram Moolenaar len = 0; 927cfe435d7SBram Moolenaar } 928cfe435d7SBram Moolenaar } 929cfe435d7SBram Moolenaar 9306378c4feSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 931cfe435d7SBram Moolenaar do_cmdline_cmd(cmd); 932cfe435d7SBram Moolenaar vim_free(cmd); 933cfe435d7SBram Moolenaar } 934cfe435d7SBram Moolenaar break; 935cfe435d7SBram Moolenaar 9368a7d6542SBram Moolenaar // execute :echo {string} ... 9378a7d6542SBram Moolenaar case ISN_ECHO: 9388a7d6542SBram Moolenaar { 9398a7d6542SBram Moolenaar int count = iptr->isn_arg.echo.echo_count; 9408a7d6542SBram Moolenaar int atstart = TRUE; 9418a7d6542SBram Moolenaar int needclr = TRUE; 9428a7d6542SBram Moolenaar 9438a7d6542SBram Moolenaar for (idx = 0; idx < count; ++idx) 9448a7d6542SBram Moolenaar { 9458a7d6542SBram Moolenaar tv = STACK_TV_BOT(idx - count); 9468a7d6542SBram Moolenaar echo_one(tv, iptr->isn_arg.echo.echo_with_white, 9478a7d6542SBram Moolenaar &atstart, &needclr); 9488a7d6542SBram Moolenaar clear_tv(tv); 9498a7d6542SBram Moolenaar } 950e0807ea4SBram Moolenaar if (needclr) 951e0807ea4SBram Moolenaar msg_clr_eos(); 9528a7d6542SBram Moolenaar ectx.ec_stack.ga_len -= count; 9538a7d6542SBram Moolenaar } 9548a7d6542SBram Moolenaar break; 9558a7d6542SBram Moolenaar 956f93c7feaSBram Moolenaar // :execute {string} ... 957f93c7feaSBram Moolenaar // :echomsg {string} ... 958f93c7feaSBram Moolenaar // :echoerr {string} ... 959ad39c094SBram Moolenaar case ISN_EXECUTE: 960f93c7feaSBram Moolenaar case ISN_ECHOMSG: 961f93c7feaSBram Moolenaar case ISN_ECHOERR: 962ad39c094SBram Moolenaar { 963ad39c094SBram Moolenaar int count = iptr->isn_arg.number; 964ad39c094SBram Moolenaar garray_T ga; 965ad39c094SBram Moolenaar char_u buf[NUMBUFLEN]; 966ad39c094SBram Moolenaar char_u *p; 967ad39c094SBram Moolenaar int len; 968ad39c094SBram Moolenaar int failed = FALSE; 969ad39c094SBram Moolenaar 970ad39c094SBram Moolenaar ga_init2(&ga, 1, 80); 971ad39c094SBram Moolenaar for (idx = 0; idx < count; ++idx) 972ad39c094SBram Moolenaar { 973ad39c094SBram Moolenaar tv = STACK_TV_BOT(idx - count); 974ad39c094SBram Moolenaar if (tv->v_type == VAR_CHANNEL || tv->v_type == VAR_JOB) 975ad39c094SBram Moolenaar { 976ad39c094SBram Moolenaar emsg(_(e_inval_string)); 977ad39c094SBram Moolenaar break; 978ad39c094SBram Moolenaar } 979ad39c094SBram Moolenaar else 980ad39c094SBram Moolenaar p = tv_get_string_buf(tv, buf); 981ad39c094SBram Moolenaar 982ad39c094SBram Moolenaar len = (int)STRLEN(p); 983ad39c094SBram Moolenaar if (ga_grow(&ga, len + 2) == FAIL) 984ad39c094SBram Moolenaar failed = TRUE; 985ad39c094SBram Moolenaar else 986ad39c094SBram Moolenaar { 987ad39c094SBram Moolenaar if (ga.ga_len > 0) 988ad39c094SBram Moolenaar ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; 989ad39c094SBram Moolenaar STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); 990ad39c094SBram Moolenaar ga.ga_len += len; 991ad39c094SBram Moolenaar } 992ad39c094SBram Moolenaar clear_tv(tv); 993ad39c094SBram Moolenaar } 994ad39c094SBram Moolenaar ectx.ec_stack.ga_len -= count; 995ad39c094SBram Moolenaar 996ad39c094SBram Moolenaar if (!failed && ga.ga_data != NULL) 997f93c7feaSBram Moolenaar { 998f93c7feaSBram Moolenaar if (iptr->isn_type == ISN_EXECUTE) 999ad39c094SBram Moolenaar do_cmdline_cmd((char_u *)ga.ga_data); 1000f93c7feaSBram Moolenaar else 1001f93c7feaSBram Moolenaar { 1002f93c7feaSBram Moolenaar msg_sb_eol(); 1003f93c7feaSBram Moolenaar if (iptr->isn_type == ISN_ECHOMSG) 1004f93c7feaSBram Moolenaar { 1005f93c7feaSBram Moolenaar msg_attr(ga.ga_data, echo_attr); 1006f93c7feaSBram Moolenaar out_flush(); 1007f93c7feaSBram Moolenaar } 1008f93c7feaSBram Moolenaar else 1009f93c7feaSBram Moolenaar { 1010f93c7feaSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1011f93c7feaSBram Moolenaar emsg(ga.ga_data); 1012f93c7feaSBram Moolenaar } 1013f93c7feaSBram Moolenaar } 1014f93c7feaSBram Moolenaar } 1015ad39c094SBram Moolenaar ga_clear(&ga); 1016ad39c094SBram Moolenaar } 1017ad39c094SBram Moolenaar break; 1018ad39c094SBram Moolenaar 10198a7d6542SBram Moolenaar // load local variable or argument 10208a7d6542SBram Moolenaar case ISN_LOAD: 1021270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 10228a7d6542SBram Moolenaar goto failed; 10238a7d6542SBram Moolenaar copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); 10248a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 10258a7d6542SBram Moolenaar break; 10268a7d6542SBram Moolenaar 1027c8cd2b34SBram Moolenaar // load variable or argument from outer scope 1028c8cd2b34SBram Moolenaar case ISN_LOADOUTER: 1029270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 1030c8cd2b34SBram Moolenaar goto failed; 1031c8cd2b34SBram Moolenaar copy_tv(STACK_OUT_TV_VAR(iptr->isn_arg.number), 1032c8cd2b34SBram Moolenaar STACK_TV_BOT(0)); 1033c8cd2b34SBram Moolenaar ++ectx.ec_stack.ga_len; 1034c8cd2b34SBram Moolenaar break; 1035c8cd2b34SBram Moolenaar 10368a7d6542SBram Moolenaar // load v: variable 10378a7d6542SBram Moolenaar case ISN_LOADV: 1038270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 10398a7d6542SBram Moolenaar goto failed; 10408a7d6542SBram Moolenaar copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0)); 10418a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 10428a7d6542SBram Moolenaar break; 10438a7d6542SBram Moolenaar 1044b283a8a6SBram Moolenaar // load s: variable in Vim9 script 10458a7d6542SBram Moolenaar case ISN_LOADSCRIPT: 10468a7d6542SBram Moolenaar { 10478a7d6542SBram Moolenaar scriptitem_T *si = 104821b9e977SBram Moolenaar SCRIPT_ITEM(iptr->isn_arg.script.script_sid); 10498a7d6542SBram Moolenaar svar_T *sv; 10508a7d6542SBram Moolenaar 10518a7d6542SBram Moolenaar sv = ((svar_T *)si->sn_var_vals.ga_data) 10528a7d6542SBram Moolenaar + iptr->isn_arg.script.script_idx; 1053270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 10548a7d6542SBram Moolenaar goto failed; 10558a7d6542SBram Moolenaar copy_tv(sv->sv_tv, STACK_TV_BOT(0)); 10568a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 10578a7d6542SBram Moolenaar } 10588a7d6542SBram Moolenaar break; 10598a7d6542SBram Moolenaar 10608a7d6542SBram Moolenaar // load s: variable in old script 10618a7d6542SBram Moolenaar case ISN_LOADS: 10628a7d6542SBram Moolenaar { 1063b283a8a6SBram Moolenaar hashtab_T *ht = &SCRIPT_VARS( 1064b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 1065b283a8a6SBram Moolenaar char_u *name = iptr->isn_arg.loadstore.ls_name; 10668a7d6542SBram Moolenaar dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE); 10670bbf722aSBram Moolenaar 10688a7d6542SBram Moolenaar if (di == NULL) 10698a7d6542SBram Moolenaar { 1070b283a8a6SBram Moolenaar semsg(_(e_undefvar), name); 1071f0b9f43cSBram Moolenaar goto on_error; 10728a7d6542SBram Moolenaar } 10738a7d6542SBram Moolenaar else 10748a7d6542SBram Moolenaar { 1075270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 10768a7d6542SBram Moolenaar goto failed; 10778a7d6542SBram Moolenaar copy_tv(&di->di_tv, STACK_TV_BOT(0)); 10788a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 10798a7d6542SBram Moolenaar } 10808a7d6542SBram Moolenaar } 10818a7d6542SBram Moolenaar break; 10828a7d6542SBram Moolenaar 1083d3aac291SBram Moolenaar // load g:/b:/w:/t: variable 10848a7d6542SBram Moolenaar case ISN_LOADG: 1085d3aac291SBram Moolenaar case ISN_LOADB: 1086d3aac291SBram Moolenaar case ISN_LOADW: 1087d3aac291SBram Moolenaar case ISN_LOADT: 10888a7d6542SBram Moolenaar { 1089d3aac291SBram Moolenaar dictitem_T *di = NULL; 1090d3aac291SBram Moolenaar hashtab_T *ht = NULL; 1091d3aac291SBram Moolenaar char namespace; 1092d3aac291SBram Moolenaar switch (iptr->isn_type) 1093d3aac291SBram Moolenaar { 1094d3aac291SBram Moolenaar case ISN_LOADG: 1095d3aac291SBram Moolenaar ht = get_globvar_ht(); 1096d3aac291SBram Moolenaar namespace = 'g'; 1097d3aac291SBram Moolenaar break; 1098d3aac291SBram Moolenaar case ISN_LOADB: 1099d3aac291SBram Moolenaar ht = &curbuf->b_vars->dv_hashtab; 1100d3aac291SBram Moolenaar namespace = 'b'; 1101d3aac291SBram Moolenaar break; 1102d3aac291SBram Moolenaar case ISN_LOADW: 1103d3aac291SBram Moolenaar ht = &curwin->w_vars->dv_hashtab; 1104d3aac291SBram Moolenaar namespace = 'w'; 1105d3aac291SBram Moolenaar break; 1106d3aac291SBram Moolenaar case ISN_LOADT: 1107d3aac291SBram Moolenaar ht = &curtab->tp_vars->dv_hashtab; 1108d3aac291SBram Moolenaar namespace = 't'; 1109d3aac291SBram Moolenaar break; 1110d3aac291SBram Moolenaar default: // Cannot reach here 1111d3aac291SBram Moolenaar goto failed; 1112d3aac291SBram Moolenaar } 1113d3aac291SBram Moolenaar di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE); 11140bbf722aSBram Moolenaar 11158a7d6542SBram Moolenaar if (di == NULL) 11168a7d6542SBram Moolenaar { 1117d3aac291SBram Moolenaar semsg(_("E121: Undefined variable: %c:%s"), 1118d3aac291SBram Moolenaar namespace, iptr->isn_arg.string); 1119f0b9f43cSBram Moolenaar goto on_error; 11208a7d6542SBram Moolenaar } 11218a7d6542SBram Moolenaar else 11228a7d6542SBram Moolenaar { 1123270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 11248a7d6542SBram Moolenaar goto failed; 11258a7d6542SBram Moolenaar copy_tv(&di->di_tv, STACK_TV_BOT(0)); 11268a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 11278a7d6542SBram Moolenaar } 11288a7d6542SBram Moolenaar } 11298a7d6542SBram Moolenaar break; 11308a7d6542SBram Moolenaar 11318a7d6542SBram Moolenaar // load &option 11328a7d6542SBram Moolenaar case ISN_LOADOPT: 11338a7d6542SBram Moolenaar { 11348a7d6542SBram Moolenaar typval_T optval; 11358a7d6542SBram Moolenaar char_u *name = iptr->isn_arg.string; 11368a7d6542SBram Moolenaar 1137a8c17704SBram Moolenaar // This is not expected to fail, name is checked during 1138a8c17704SBram Moolenaar // compilation: don't set SOURCING_LNUM. 1139270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 11408a7d6542SBram Moolenaar goto failed; 11419a78e6dfSBram Moolenaar if (eval_option(&name, &optval, TRUE) == FAIL) 114258ceca5cSBram Moolenaar goto failed; 11438a7d6542SBram Moolenaar *STACK_TV_BOT(0) = optval; 11448a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 11458a7d6542SBram Moolenaar } 11468a7d6542SBram Moolenaar break; 11478a7d6542SBram Moolenaar 11488a7d6542SBram Moolenaar // load $ENV 11498a7d6542SBram Moolenaar case ISN_LOADENV: 11508a7d6542SBram Moolenaar { 11518a7d6542SBram Moolenaar typval_T optval; 11528a7d6542SBram Moolenaar char_u *name = iptr->isn_arg.string; 11538a7d6542SBram Moolenaar 1154270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 11558a7d6542SBram Moolenaar goto failed; 11560bbf722aSBram Moolenaar // name is always valid, checked when compiling 11579a78e6dfSBram Moolenaar (void)eval_env_var(&name, &optval, TRUE); 11588a7d6542SBram Moolenaar *STACK_TV_BOT(0) = optval; 11598a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 11608a7d6542SBram Moolenaar } 11618a7d6542SBram Moolenaar break; 11628a7d6542SBram Moolenaar 11638a7d6542SBram Moolenaar // load @register 11648a7d6542SBram Moolenaar case ISN_LOADREG: 1165270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 11668a7d6542SBram Moolenaar goto failed; 11678a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 11688a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 11698a7d6542SBram Moolenaar tv->vval.v_string = get_reg_contents( 11708a7d6542SBram Moolenaar iptr->isn_arg.number, GREG_EXPR_SRC); 11718a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 11728a7d6542SBram Moolenaar break; 11738a7d6542SBram Moolenaar 11748a7d6542SBram Moolenaar // store local variable 11758a7d6542SBram Moolenaar case ISN_STORE: 11768a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 11778a7d6542SBram Moolenaar tv = STACK_TV_VAR(iptr->isn_arg.number); 11788a7d6542SBram Moolenaar clear_tv(tv); 11798a7d6542SBram Moolenaar *tv = *STACK_TV_BOT(0); 11808a7d6542SBram Moolenaar break; 11818a7d6542SBram Moolenaar 1182b68b346eSBram Moolenaar // store variable or argument in outer scope 1183b68b346eSBram Moolenaar case ISN_STOREOUTER: 1184b68b346eSBram Moolenaar --ectx.ec_stack.ga_len; 1185b68b346eSBram Moolenaar tv = STACK_OUT_TV_VAR(iptr->isn_arg.number); 1186b68b346eSBram Moolenaar clear_tv(tv); 1187b68b346eSBram Moolenaar *tv = *STACK_TV_BOT(0); 1188b68b346eSBram Moolenaar break; 1189b68b346eSBram Moolenaar 1190b283a8a6SBram Moolenaar // store s: variable in old script 1191b283a8a6SBram Moolenaar case ISN_STORES: 1192b283a8a6SBram Moolenaar { 1193b283a8a6SBram Moolenaar hashtab_T *ht = &SCRIPT_VARS( 1194b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 1195b283a8a6SBram Moolenaar char_u *name = iptr->isn_arg.loadstore.ls_name; 11960bbf722aSBram Moolenaar dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE); 1197b283a8a6SBram Moolenaar 1198b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 11990bbf722aSBram Moolenaar if (di == NULL) 12005deeb3f1SBram Moolenaar store_var(name, STACK_TV_BOT(0)); 12010bbf722aSBram Moolenaar else 12020bbf722aSBram Moolenaar { 1203b283a8a6SBram Moolenaar clear_tv(&di->di_tv); 1204b283a8a6SBram Moolenaar di->di_tv = *STACK_TV_BOT(0); 1205b283a8a6SBram Moolenaar } 12060bbf722aSBram Moolenaar } 1207b283a8a6SBram Moolenaar break; 1208b283a8a6SBram Moolenaar 1209b283a8a6SBram Moolenaar // store script-local variable in Vim9 script 12108a7d6542SBram Moolenaar case ISN_STORESCRIPT: 12118a7d6542SBram Moolenaar { 121221b9e977SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 12138a7d6542SBram Moolenaar iptr->isn_arg.script.script_sid); 12148a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 12158a7d6542SBram Moolenaar + iptr->isn_arg.script.script_idx; 12168a7d6542SBram Moolenaar 12178a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 12188a7d6542SBram Moolenaar clear_tv(sv->sv_tv); 12198a7d6542SBram Moolenaar *sv->sv_tv = *STACK_TV_BOT(0); 12208a7d6542SBram Moolenaar } 12218a7d6542SBram Moolenaar break; 12228a7d6542SBram Moolenaar 12238a7d6542SBram Moolenaar // store option 12248a7d6542SBram Moolenaar case ISN_STOREOPT: 12258a7d6542SBram Moolenaar { 12268a7d6542SBram Moolenaar long n = 0; 12278a7d6542SBram Moolenaar char_u *s = NULL; 12288a7d6542SBram Moolenaar char *msg; 12298a7d6542SBram Moolenaar 12308a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 12318a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 12328a7d6542SBram Moolenaar if (tv->v_type == VAR_STRING) 123397a2af39SBram Moolenaar { 12348a7d6542SBram Moolenaar s = tv->vval.v_string; 123597a2af39SBram Moolenaar if (s == NULL) 123697a2af39SBram Moolenaar s = (char_u *)""; 123797a2af39SBram Moolenaar } 12388a7d6542SBram Moolenaar else 1239a6e67e4fSBram Moolenaar // must be VAR_NUMBER, CHECKTYPE makes sure 1240a6e67e4fSBram Moolenaar n = tv->vval.v_number; 12418a7d6542SBram Moolenaar msg = set_option_value(iptr->isn_arg.storeopt.so_name, 12428a7d6542SBram Moolenaar n, s, iptr->isn_arg.storeopt.so_flags); 1243e75ba268SBram Moolenaar clear_tv(tv); 12448a7d6542SBram Moolenaar if (msg != NULL) 12458a7d6542SBram Moolenaar { 12468a7d6542SBram Moolenaar emsg(_(msg)); 1247e859312eSBram Moolenaar goto on_error; 12488a7d6542SBram Moolenaar } 12498a7d6542SBram Moolenaar } 12508a7d6542SBram Moolenaar break; 12518a7d6542SBram Moolenaar 1252b283a8a6SBram Moolenaar // store $ENV 1253b283a8a6SBram Moolenaar case ISN_STOREENV: 1254b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 125520431c9dSBram Moolenaar tv = STACK_TV_BOT(0); 125620431c9dSBram Moolenaar vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv)); 125720431c9dSBram Moolenaar clear_tv(tv); 1258b283a8a6SBram Moolenaar break; 1259b283a8a6SBram Moolenaar 1260b283a8a6SBram Moolenaar // store @r 1261b283a8a6SBram Moolenaar case ISN_STOREREG: 1262b283a8a6SBram Moolenaar { 1263b283a8a6SBram Moolenaar int reg = iptr->isn_arg.number; 1264b283a8a6SBram Moolenaar 1265b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 1266401d9ffbSBram Moolenaar tv = STACK_TV_BOT(0); 1267b283a8a6SBram Moolenaar write_reg_contents(reg == '@' ? '"' : reg, 1268401d9ffbSBram Moolenaar tv_get_string(tv), -1, FALSE); 1269401d9ffbSBram Moolenaar clear_tv(tv); 1270b283a8a6SBram Moolenaar } 1271b283a8a6SBram Moolenaar break; 1272b283a8a6SBram Moolenaar 1273b283a8a6SBram Moolenaar // store v: variable 1274b283a8a6SBram Moolenaar case ISN_STOREV: 1275b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 1276b283a8a6SBram Moolenaar if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0)) 1277b283a8a6SBram Moolenaar == FAIL) 1278e859312eSBram Moolenaar // should not happen, type is checked when compiling 1279e859312eSBram Moolenaar goto on_error; 1280b283a8a6SBram Moolenaar break; 1281b283a8a6SBram Moolenaar 1282d3aac291SBram Moolenaar // store g:/b:/w:/t: variable 12838a7d6542SBram Moolenaar case ISN_STOREG: 1284d3aac291SBram Moolenaar case ISN_STOREB: 1285d3aac291SBram Moolenaar case ISN_STOREW: 1286d3aac291SBram Moolenaar case ISN_STORET: 12878a7d6542SBram Moolenaar { 12888a7d6542SBram Moolenaar dictitem_T *di; 1289d3aac291SBram Moolenaar hashtab_T *ht; 1290d3aac291SBram Moolenaar switch (iptr->isn_type) 1291d3aac291SBram Moolenaar { 1292d3aac291SBram Moolenaar case ISN_STOREG: 1293d3aac291SBram Moolenaar ht = get_globvar_ht(); 1294d3aac291SBram Moolenaar break; 1295d3aac291SBram Moolenaar case ISN_STOREB: 1296d3aac291SBram Moolenaar ht = &curbuf->b_vars->dv_hashtab; 1297d3aac291SBram Moolenaar break; 1298d3aac291SBram Moolenaar case ISN_STOREW: 1299d3aac291SBram Moolenaar ht = &curwin->w_vars->dv_hashtab; 1300d3aac291SBram Moolenaar break; 1301d3aac291SBram Moolenaar case ISN_STORET: 1302d3aac291SBram Moolenaar ht = &curtab->tp_vars->dv_hashtab; 1303d3aac291SBram Moolenaar break; 1304d3aac291SBram Moolenaar default: // Cannot reach here 1305d3aac291SBram Moolenaar goto failed; 1306d3aac291SBram Moolenaar } 13078a7d6542SBram Moolenaar 13088a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 1309bf67ea1aSBram Moolenaar di = find_var_in_ht(ht, 0, iptr->isn_arg.string + 2, TRUE); 13108a7d6542SBram Moolenaar if (di == NULL) 13110bbf722aSBram Moolenaar store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); 13128a7d6542SBram Moolenaar else 13138a7d6542SBram Moolenaar { 13148a7d6542SBram Moolenaar clear_tv(&di->di_tv); 13158a7d6542SBram Moolenaar di->di_tv = *STACK_TV_BOT(0); 13168a7d6542SBram Moolenaar } 13178a7d6542SBram Moolenaar } 13188a7d6542SBram Moolenaar break; 13198a7d6542SBram Moolenaar 13208a7d6542SBram Moolenaar // store number in local variable 13218a7d6542SBram Moolenaar case ISN_STORENR: 1322a471eeaeSBram Moolenaar tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx); 13238a7d6542SBram Moolenaar clear_tv(tv); 13248a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 1325a471eeaeSBram Moolenaar tv->vval.v_number = iptr->isn_arg.storenr.stnr_val; 13268a7d6542SBram Moolenaar break; 13278a7d6542SBram Moolenaar 13281cc2a94fSBram Moolenaar // store value in list variable 13291cc2a94fSBram Moolenaar case ISN_STORELIST: 13301cc2a94fSBram Moolenaar { 13311cc2a94fSBram Moolenaar typval_T *tv_idx = STACK_TV_BOT(-2); 13321cc2a94fSBram Moolenaar varnumber_T lidx = tv_idx->vval.v_number; 13331cc2a94fSBram Moolenaar typval_T *tv_list = STACK_TV_BOT(-1); 13341cc2a94fSBram Moolenaar list_T *list = tv_list->vval.v_list; 13351cc2a94fSBram Moolenaar 13361cc2a94fSBram Moolenaar if (lidx < 0 && list->lv_len + lidx >= 0) 13371cc2a94fSBram Moolenaar // negative index is relative to the end 13381cc2a94fSBram Moolenaar lidx = list->lv_len + lidx; 13391cc2a94fSBram Moolenaar if (lidx < 0 || lidx > list->lv_len) 13401cc2a94fSBram Moolenaar { 13411cc2a94fSBram Moolenaar semsg(_(e_listidx), lidx); 1342e859312eSBram Moolenaar goto on_error; 13431cc2a94fSBram Moolenaar } 13441cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-3); 13451cc2a94fSBram Moolenaar if (lidx < list->lv_len) 13461cc2a94fSBram Moolenaar { 13471cc2a94fSBram Moolenaar listitem_T *li = list_find(list, lidx); 13481cc2a94fSBram Moolenaar 13491cc2a94fSBram Moolenaar // overwrite existing list item 13501cc2a94fSBram Moolenaar clear_tv(&li->li_tv); 13511cc2a94fSBram Moolenaar li->li_tv = *tv; 13521cc2a94fSBram Moolenaar } 13531cc2a94fSBram Moolenaar else 13541cc2a94fSBram Moolenaar { 1355e859312eSBram Moolenaar // append to list, only fails when out of memory 13561cc2a94fSBram Moolenaar if (list_append_tv(list, tv) == FAIL) 13571cc2a94fSBram Moolenaar goto failed; 13581cc2a94fSBram Moolenaar clear_tv(tv); 13591cc2a94fSBram Moolenaar } 13601cc2a94fSBram Moolenaar clear_tv(tv_idx); 13611cc2a94fSBram Moolenaar clear_tv(tv_list); 1362f163bd5eSBram Moolenaar ectx.ec_stack.ga_len -= 3; 13631cc2a94fSBram Moolenaar } 13641cc2a94fSBram Moolenaar break; 13651cc2a94fSBram Moolenaar 13661cc2a94fSBram Moolenaar // store value in dict variable 13671cc2a94fSBram Moolenaar case ISN_STOREDICT: 13681cc2a94fSBram Moolenaar { 13691cc2a94fSBram Moolenaar typval_T *tv_key = STACK_TV_BOT(-2); 13701cc2a94fSBram Moolenaar char_u *key = tv_key->vval.v_string; 13711cc2a94fSBram Moolenaar typval_T *tv_dict = STACK_TV_BOT(-1); 13721cc2a94fSBram Moolenaar dict_T *dict = tv_dict->vval.v_dict; 13731cc2a94fSBram Moolenaar dictitem_T *di; 13741cc2a94fSBram Moolenaar 13751cc2a94fSBram Moolenaar if (key == NULL || *key == NUL) 13761cc2a94fSBram Moolenaar { 13771cc2a94fSBram Moolenaar emsg(_(e_emptykey)); 1378e859312eSBram Moolenaar goto on_error; 13791cc2a94fSBram Moolenaar } 13801cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-3); 13811cc2a94fSBram Moolenaar di = dict_find(dict, key, -1); 13821cc2a94fSBram Moolenaar if (di != NULL) 13831cc2a94fSBram Moolenaar { 1384e859312eSBram Moolenaar // overwrite existing value 13851cc2a94fSBram Moolenaar clear_tv(&di->di_tv); 13861cc2a94fSBram Moolenaar di->di_tv = *tv; 13871cc2a94fSBram Moolenaar } 13881cc2a94fSBram Moolenaar else 13891cc2a94fSBram Moolenaar { 1390e859312eSBram Moolenaar // add to dict, only fails when out of memory 13911cc2a94fSBram Moolenaar if (dict_add_tv(dict, (char *)key, tv) == FAIL) 13921cc2a94fSBram Moolenaar goto failed; 13931cc2a94fSBram Moolenaar clear_tv(tv); 13941cc2a94fSBram Moolenaar } 13951cc2a94fSBram Moolenaar clear_tv(tv_key); 13961cc2a94fSBram Moolenaar clear_tv(tv_dict); 1397f163bd5eSBram Moolenaar ectx.ec_stack.ga_len -= 3; 13981cc2a94fSBram Moolenaar } 13991cc2a94fSBram Moolenaar break; 14001cc2a94fSBram Moolenaar 14018a7d6542SBram Moolenaar // push constant 14028a7d6542SBram Moolenaar case ISN_PUSHNR: 14038a7d6542SBram Moolenaar case ISN_PUSHBOOL: 14048a7d6542SBram Moolenaar case ISN_PUSHSPEC: 14058a7d6542SBram Moolenaar case ISN_PUSHF: 14068a7d6542SBram Moolenaar case ISN_PUSHS: 14078a7d6542SBram Moolenaar case ISN_PUSHBLOB: 140842a480bfSBram Moolenaar case ISN_PUSHFUNC: 140942a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 141042a480bfSBram Moolenaar case ISN_PUSHJOB: 1411270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 14128a7d6542SBram Moolenaar goto failed; 14138a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 14148a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 14158a7d6542SBram Moolenaar switch (iptr->isn_type) 14168a7d6542SBram Moolenaar { 14178a7d6542SBram Moolenaar case ISN_PUSHNR: 14188a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 14198a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 14208a7d6542SBram Moolenaar break; 14218a7d6542SBram Moolenaar case ISN_PUSHBOOL: 14228a7d6542SBram Moolenaar tv->v_type = VAR_BOOL; 14238a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 14248a7d6542SBram Moolenaar break; 14258a7d6542SBram Moolenaar case ISN_PUSHSPEC: 14268a7d6542SBram Moolenaar tv->v_type = VAR_SPECIAL; 14278a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 14288a7d6542SBram Moolenaar break; 14298a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 14308a7d6542SBram Moolenaar case ISN_PUSHF: 14318a7d6542SBram Moolenaar tv->v_type = VAR_FLOAT; 14328a7d6542SBram Moolenaar tv->vval.v_float = iptr->isn_arg.fnumber; 14338a7d6542SBram Moolenaar break; 14348a7d6542SBram Moolenaar #endif 14358a7d6542SBram Moolenaar case ISN_PUSHBLOB: 14368a7d6542SBram Moolenaar blob_copy(iptr->isn_arg.blob, tv); 14378a7d6542SBram Moolenaar break; 143842a480bfSBram Moolenaar case ISN_PUSHFUNC: 143942a480bfSBram Moolenaar tv->v_type = VAR_FUNC; 1440087d2e15SBram Moolenaar if (iptr->isn_arg.string == NULL) 1441087d2e15SBram Moolenaar tv->vval.v_string = NULL; 1442087d2e15SBram Moolenaar else 1443087d2e15SBram Moolenaar tv->vval.v_string = 1444087d2e15SBram Moolenaar vim_strsave(iptr->isn_arg.string); 144542a480bfSBram Moolenaar break; 144642a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 144742a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 144842a480bfSBram Moolenaar tv->v_type = VAR_CHANNEL; 144942a480bfSBram Moolenaar tv->vval.v_channel = iptr->isn_arg.channel; 145042a480bfSBram Moolenaar if (tv->vval.v_channel != NULL) 145142a480bfSBram Moolenaar ++tv->vval.v_channel->ch_refcount; 145242a480bfSBram Moolenaar #endif 145342a480bfSBram Moolenaar break; 145442a480bfSBram Moolenaar case ISN_PUSHJOB: 145542a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 145642a480bfSBram Moolenaar tv->v_type = VAR_JOB; 145742a480bfSBram Moolenaar tv->vval.v_job = iptr->isn_arg.job; 145842a480bfSBram Moolenaar if (tv->vval.v_job != NULL) 145942a480bfSBram Moolenaar ++tv->vval.v_job->jv_refcount; 146042a480bfSBram Moolenaar #endif 146142a480bfSBram Moolenaar break; 14628a7d6542SBram Moolenaar default: 14638a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 1464e69f6d04SBram Moolenaar tv->vval.v_string = vim_strsave( 1465e69f6d04SBram Moolenaar iptr->isn_arg.string == NULL 1466e69f6d04SBram Moolenaar ? (char_u *)"" : iptr->isn_arg.string); 14678a7d6542SBram Moolenaar } 14688a7d6542SBram Moolenaar break; 14698a7d6542SBram Moolenaar 1470d72c1bf0SBram Moolenaar case ISN_UNLET: 1471d72c1bf0SBram Moolenaar if (do_unlet(iptr->isn_arg.unlet.ul_name, 1472d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_forceit) == FAIL) 1473e859312eSBram Moolenaar goto on_error; 1474d72c1bf0SBram Moolenaar break; 14757bdaea6eSBram Moolenaar case ISN_UNLETENV: 14767bdaea6eSBram Moolenaar vim_unsetenv(iptr->isn_arg.unlet.ul_name); 14777bdaea6eSBram Moolenaar break; 1478d72c1bf0SBram Moolenaar 14798a7d6542SBram Moolenaar // create a list from items on the stack; uses a single allocation 14808a7d6542SBram Moolenaar // for the list header and the items 14818a7d6542SBram Moolenaar case ISN_NEWLIST: 1482fe270817SBram Moolenaar if (exe_newlist(iptr->isn_arg.number, &ectx) == FAIL) 14838a7d6542SBram Moolenaar goto failed; 14848a7d6542SBram Moolenaar break; 14858a7d6542SBram Moolenaar 14868a7d6542SBram Moolenaar // create a dict from items on the stack 14878a7d6542SBram Moolenaar case ISN_NEWDICT: 14888a7d6542SBram Moolenaar { 14898a7d6542SBram Moolenaar int count = iptr->isn_arg.number; 14908a7d6542SBram Moolenaar dict_T *dict = dict_alloc(); 14918a7d6542SBram Moolenaar dictitem_T *item; 14928a7d6542SBram Moolenaar 14938a7d6542SBram Moolenaar if (dict == NULL) 14948a7d6542SBram Moolenaar goto failed; 14958a7d6542SBram Moolenaar for (idx = 0; idx < count; ++idx) 14968a7d6542SBram Moolenaar { 1497e859312eSBram Moolenaar // have already checked key type is VAR_STRING 14988a7d6542SBram Moolenaar tv = STACK_TV_BOT(2 * (idx - count)); 1499e859312eSBram Moolenaar // check key is unique 1500e859312eSBram Moolenaar item = dict_find(dict, tv->vval.v_string, -1); 1501e859312eSBram Moolenaar if (item != NULL) 1502e859312eSBram Moolenaar { 1503e859312eSBram Moolenaar semsg(_(e_duplicate_key), tv->vval.v_string); 1504e859312eSBram Moolenaar dict_unref(dict); 1505e859312eSBram Moolenaar goto on_error; 1506e859312eSBram Moolenaar } 15078a7d6542SBram Moolenaar item = dictitem_alloc(tv->vval.v_string); 15088a7d6542SBram Moolenaar clear_tv(tv); 15098a7d6542SBram Moolenaar if (item == NULL) 1510e859312eSBram Moolenaar { 1511e859312eSBram Moolenaar dict_unref(dict); 15128a7d6542SBram Moolenaar goto failed; 1513e859312eSBram Moolenaar } 15148a7d6542SBram Moolenaar item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); 15158a7d6542SBram Moolenaar item->di_tv.v_lock = 0; 15168a7d6542SBram Moolenaar if (dict_add(dict, item) == FAIL) 1517e859312eSBram Moolenaar { 1518d032f34aSBram Moolenaar // can this ever happen? 1519e859312eSBram Moolenaar dict_unref(dict); 15208a7d6542SBram Moolenaar goto failed; 15218a7d6542SBram Moolenaar } 1522e859312eSBram Moolenaar } 15238a7d6542SBram Moolenaar 15248a7d6542SBram Moolenaar if (count > 0) 15258a7d6542SBram Moolenaar ectx.ec_stack.ga_len -= 2 * count - 1; 1526270d0388SBram Moolenaar else if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 15278a7d6542SBram Moolenaar goto failed; 15288a7d6542SBram Moolenaar else 15298a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 15308a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 15318a7d6542SBram Moolenaar tv->v_type = VAR_DICT; 15328a7d6542SBram Moolenaar tv->vval.v_dict = dict; 15338a7d6542SBram Moolenaar ++dict->dv_refcount; 15348a7d6542SBram Moolenaar } 15358a7d6542SBram Moolenaar break; 15368a7d6542SBram Moolenaar 15378a7d6542SBram Moolenaar // call a :def function 15388a7d6542SBram Moolenaar case ISN_DCALL: 15398a7d6542SBram Moolenaar if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx, 15408a7d6542SBram Moolenaar iptr->isn_arg.dfunc.cdf_argcount, 15418a7d6542SBram Moolenaar &ectx) == FAIL) 1542e859312eSBram Moolenaar goto on_error; 15438a7d6542SBram Moolenaar break; 15448a7d6542SBram Moolenaar 15458a7d6542SBram Moolenaar // call a builtin function 15468a7d6542SBram Moolenaar case ISN_BCALL: 15478a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 15488a7d6542SBram Moolenaar if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx, 15498a7d6542SBram Moolenaar iptr->isn_arg.bfunc.cbf_argcount, 15508a7d6542SBram Moolenaar &ectx) == FAIL) 1551d032f34aSBram Moolenaar goto on_error; 15528a7d6542SBram Moolenaar break; 15538a7d6542SBram Moolenaar 15548a7d6542SBram Moolenaar // call a funcref or partial 15558a7d6542SBram Moolenaar case ISN_PCALL: 15568a7d6542SBram Moolenaar { 15578a7d6542SBram Moolenaar cpfunc_T *pfunc = &iptr->isn_arg.pfunc; 15588a7d6542SBram Moolenaar int r; 15596f5b6dfbSBram Moolenaar typval_T partial_tv; 15608a7d6542SBram Moolenaar 15618a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 15628a7d6542SBram Moolenaar if (pfunc->cpf_top) 15638a7d6542SBram Moolenaar { 15648a7d6542SBram Moolenaar // funcref is above the arguments 15658a7d6542SBram Moolenaar tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1); 15668a7d6542SBram Moolenaar } 15678a7d6542SBram Moolenaar else 15688a7d6542SBram Moolenaar { 15698a7d6542SBram Moolenaar // Get the funcref from the stack. 15708a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 15716f5b6dfbSBram Moolenaar partial_tv = *STACK_TV_BOT(0); 15726f5b6dfbSBram Moolenaar tv = &partial_tv; 15738a7d6542SBram Moolenaar } 15748a7d6542SBram Moolenaar r = call_partial(tv, pfunc->cpf_argcount, &ectx); 15756f5b6dfbSBram Moolenaar if (tv == &partial_tv) 15766f5b6dfbSBram Moolenaar clear_tv(&partial_tv); 15778a7d6542SBram Moolenaar if (r == FAIL) 1578d032f34aSBram Moolenaar goto on_error; 1579bd5da371SBram Moolenaar } 1580bd5da371SBram Moolenaar break; 15818a7d6542SBram Moolenaar 1582bd5da371SBram Moolenaar case ISN_PCALL_END: 1583bd5da371SBram Moolenaar // PCALL finished, arguments have been consumed and replaced by 1584bd5da371SBram Moolenaar // the return value. Now clear the funcref from the stack, 1585bd5da371SBram Moolenaar // and move the return value in its place. 15868a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 1587bd5da371SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 15888a7d6542SBram Moolenaar *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); 15898a7d6542SBram Moolenaar break; 15908a7d6542SBram Moolenaar 15918a7d6542SBram Moolenaar // call a user defined function or funcref/partial 15928a7d6542SBram Moolenaar case ISN_UCALL: 15938a7d6542SBram Moolenaar { 15948a7d6542SBram Moolenaar cufunc_T *cufunc = &iptr->isn_arg.ufunc; 15958a7d6542SBram Moolenaar 15968a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 15978a7d6542SBram Moolenaar if (call_eval_func(cufunc->cuf_name, 15987eeefd4aSBram Moolenaar cufunc->cuf_argcount, &ectx, iptr) == FAIL) 1599d032f34aSBram Moolenaar goto on_error; 16008a7d6542SBram Moolenaar } 16018a7d6542SBram Moolenaar break; 16028a7d6542SBram Moolenaar 16038a7d6542SBram Moolenaar // return from a :def function call 16048a7d6542SBram Moolenaar case ISN_RETURN: 16058a7d6542SBram Moolenaar { 16068cbd6dfcSBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 160720431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 16088cbd6dfcSBram Moolenaar 16098cbd6dfcSBram Moolenaar if (trystack->ga_len > 0) 16108cbd6dfcSBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 16118cbd6dfcSBram Moolenaar + trystack->ga_len - 1; 1612bf67ea1aSBram Moolenaar if (trycmd != NULL 1613bf67ea1aSBram Moolenaar && trycmd->tcd_frame_idx == ectx.ec_frame_idx 16148a7d6542SBram Moolenaar && trycmd->tcd_finally_idx != 0) 16158a7d6542SBram Moolenaar { 16168a7d6542SBram Moolenaar // jump to ":finally" 16178a7d6542SBram Moolenaar ectx.ec_iidx = trycmd->tcd_finally_idx; 16188a7d6542SBram Moolenaar trycmd->tcd_return = TRUE; 16198a7d6542SBram Moolenaar } 16208a7d6542SBram Moolenaar else 1621d032f34aSBram Moolenaar goto func_return; 16228a7d6542SBram Moolenaar } 16238a7d6542SBram Moolenaar break; 16248a7d6542SBram Moolenaar 16258a7d6542SBram Moolenaar // push a function reference to a compiled function 16268a7d6542SBram Moolenaar case ISN_FUNCREF: 16278a7d6542SBram Moolenaar { 16288a7d6542SBram Moolenaar partial_T *pt = NULL; 1629bf67ea1aSBram Moolenaar dfunc_T *pt_dfunc; 16308a7d6542SBram Moolenaar 16318a7d6542SBram Moolenaar pt = ALLOC_CLEAR_ONE(partial_T); 16328a7d6542SBram Moolenaar if (pt == NULL) 16338a7d6542SBram Moolenaar goto failed; 1634270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 1635c8cd2b34SBram Moolenaar { 1636bf67ea1aSBram Moolenaar vim_free(pt); 1637bf67ea1aSBram Moolenaar goto failed; 1638bf67ea1aSBram Moolenaar } 1639bf67ea1aSBram Moolenaar pt_dfunc = ((dfunc_T *)def_functions.ga_data) 1640bf67ea1aSBram Moolenaar + iptr->isn_arg.funcref.fr_func; 1641bf67ea1aSBram Moolenaar pt->pt_func = pt_dfunc->df_ufunc; 1642bf67ea1aSBram Moolenaar pt->pt_refcount = 1; 1643bf67ea1aSBram Moolenaar ++pt_dfunc->df_ufunc->uf_refcount; 1644bf67ea1aSBram Moolenaar 1645bf67ea1aSBram Moolenaar if (pt_dfunc->df_ufunc->uf_flags & FC_CLOSURE) 1646bf67ea1aSBram Moolenaar { 1647bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 1648bf67ea1aSBram Moolenaar + ectx.ec_dfunc_idx; 1649bf67ea1aSBram Moolenaar 1650bf67ea1aSBram Moolenaar // The closure needs to find arguments and local 1651bf67ea1aSBram Moolenaar // variables in the current stack. 1652f7779c63SBram Moolenaar pt->pt_ectx_stack = &ectx.ec_stack; 1653f7779c63SBram Moolenaar pt->pt_ectx_frame = ectx.ec_frame_idx; 1654bf67ea1aSBram Moolenaar 1655bf67ea1aSBram Moolenaar // If this function returns and the closure is still 1656bf67ea1aSBram Moolenaar // used, we need to make a copy of the context 1657bf67ea1aSBram Moolenaar // (arguments and local variables). Store a reference 1658bf67ea1aSBram Moolenaar // to the partial so we can handle that. 1659bf67ea1aSBram Moolenaar ++pt->pt_refcount; 1660bf67ea1aSBram Moolenaar tv = STACK_TV_VAR(dfunc->df_varcount 1661bf67ea1aSBram Moolenaar + iptr->isn_arg.funcref.fr_var_idx); 1662bf67ea1aSBram Moolenaar if (tv->v_type == VAR_PARTIAL) 1663bf67ea1aSBram Moolenaar { 1664bf67ea1aSBram Moolenaar // TODO: use a garray_T on ectx. 1665bf67ea1aSBram Moolenaar emsg("Multiple closures not supported yet"); 1666bf67ea1aSBram Moolenaar goto failed; 1667bf67ea1aSBram Moolenaar } 1668bf67ea1aSBram Moolenaar tv->v_type = VAR_PARTIAL; 1669bf67ea1aSBram Moolenaar tv->vval.v_partial = pt; 1670c8cd2b34SBram Moolenaar } 1671c8cd2b34SBram Moolenaar 16728a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 16738a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 16748a7d6542SBram Moolenaar tv->vval.v_partial = pt; 16758a7d6542SBram Moolenaar tv->v_type = VAR_PARTIAL; 16768a7d6542SBram Moolenaar } 16778a7d6542SBram Moolenaar break; 16788a7d6542SBram Moolenaar 16798a7d6542SBram Moolenaar // jump if a condition is met 16808a7d6542SBram Moolenaar case ISN_JUMP: 16818a7d6542SBram Moolenaar { 16828a7d6542SBram Moolenaar jumpwhen_T when = iptr->isn_arg.jump.jump_when; 16838a7d6542SBram Moolenaar int jump = TRUE; 16848a7d6542SBram Moolenaar 16858a7d6542SBram Moolenaar if (when != JUMP_ALWAYS) 16868a7d6542SBram Moolenaar { 16878a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 16888a7d6542SBram Moolenaar jump = tv2bool(tv); 16898a7d6542SBram Moolenaar if (when == JUMP_IF_FALSE 16908a7d6542SBram Moolenaar || when == JUMP_AND_KEEP_IF_FALSE) 16918a7d6542SBram Moolenaar jump = !jump; 1692777770fbSBram Moolenaar if (when == JUMP_IF_FALSE || !jump) 16938a7d6542SBram Moolenaar { 16948a7d6542SBram Moolenaar // drop the value from the stack 16958a7d6542SBram Moolenaar clear_tv(tv); 16968a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 16978a7d6542SBram Moolenaar } 16988a7d6542SBram Moolenaar } 16998a7d6542SBram Moolenaar if (jump) 17008a7d6542SBram Moolenaar ectx.ec_iidx = iptr->isn_arg.jump.jump_where; 17018a7d6542SBram Moolenaar } 17028a7d6542SBram Moolenaar break; 17038a7d6542SBram Moolenaar 17048a7d6542SBram Moolenaar // top of a for loop 17058a7d6542SBram Moolenaar case ISN_FOR: 17068a7d6542SBram Moolenaar { 17078a7d6542SBram Moolenaar list_T *list = STACK_TV_BOT(-1)->vval.v_list; 17088a7d6542SBram Moolenaar typval_T *idxtv = 17098a7d6542SBram Moolenaar STACK_TV_VAR(iptr->isn_arg.forloop.for_idx); 17108a7d6542SBram Moolenaar 17118a7d6542SBram Moolenaar // push the next item from the list 1712270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 17138a7d6542SBram Moolenaar goto failed; 17148a7d6542SBram Moolenaar if (++idxtv->vval.v_number >= list->lv_len) 17158a7d6542SBram Moolenaar // past the end of the list, jump to "endfor" 17168a7d6542SBram Moolenaar ectx.ec_iidx = iptr->isn_arg.forloop.for_end; 17178a7d6542SBram Moolenaar else if (list->lv_first == &range_list_item) 17188a7d6542SBram Moolenaar { 17198a7d6542SBram Moolenaar // non-materialized range() list 17208a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 17218a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 17228a7d6542SBram Moolenaar tv->vval.v_number = list_find_nr( 17238a7d6542SBram Moolenaar list, idxtv->vval.v_number, NULL); 17248a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 17258a7d6542SBram Moolenaar } 17268a7d6542SBram Moolenaar else 17278a7d6542SBram Moolenaar { 17288a7d6542SBram Moolenaar listitem_T *li = list_find(list, idxtv->vval.v_number); 17298a7d6542SBram Moolenaar 17308a7d6542SBram Moolenaar copy_tv(&li->li_tv, STACK_TV_BOT(0)); 17318a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 17328a7d6542SBram Moolenaar } 17338a7d6542SBram Moolenaar } 17348a7d6542SBram Moolenaar break; 17358a7d6542SBram Moolenaar 17368a7d6542SBram Moolenaar // start of ":try" block 17378a7d6542SBram Moolenaar case ISN_TRY: 17388a7d6542SBram Moolenaar { 173920431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 174020431c9dSBram Moolenaar 1741270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_trystack, 1) == FAIL) 17428a7d6542SBram Moolenaar goto failed; 17438a7d6542SBram Moolenaar trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data) 17448a7d6542SBram Moolenaar + ectx.ec_trystack.ga_len; 17458a7d6542SBram Moolenaar ++ectx.ec_trystack.ga_len; 17468a7d6542SBram Moolenaar ++trylevel; 1747bf67ea1aSBram Moolenaar trycmd->tcd_frame_idx = ectx.ec_frame_idx; 17488a7d6542SBram Moolenaar trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch; 17498a7d6542SBram Moolenaar trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally; 1750f575adffSBram Moolenaar trycmd->tcd_caught = FALSE; 17518a7d6542SBram Moolenaar } 17528a7d6542SBram Moolenaar break; 17538a7d6542SBram Moolenaar 17548a7d6542SBram Moolenaar case ISN_PUSHEXC: 17558a7d6542SBram Moolenaar if (current_exception == NULL) 17568a7d6542SBram Moolenaar { 17578a7d6542SBram Moolenaar iemsg("Evaluating catch while current_exception is NULL"); 17588a7d6542SBram Moolenaar goto failed; 17598a7d6542SBram Moolenaar } 1760270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 17618a7d6542SBram Moolenaar goto failed; 17628a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 17638a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 17648a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 17658a7d6542SBram Moolenaar tv->vval.v_string = vim_strsave( 17668a7d6542SBram Moolenaar (char_u *)current_exception->value); 17678a7d6542SBram Moolenaar break; 17688a7d6542SBram Moolenaar 17698a7d6542SBram Moolenaar case ISN_CATCH: 17708a7d6542SBram Moolenaar { 17718a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 17728a7d6542SBram Moolenaar 17738a7d6542SBram Moolenaar if (trystack->ga_len > 0) 17748a7d6542SBram Moolenaar { 177520431c9dSBram Moolenaar trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data) 17768a7d6542SBram Moolenaar + trystack->ga_len - 1; 17778a7d6542SBram Moolenaar trycmd->tcd_caught = TRUE; 17788a7d6542SBram Moolenaar } 17798a7d6542SBram Moolenaar did_emsg = got_int = did_throw = FALSE; 17808a7d6542SBram Moolenaar catch_exception(current_exception); 17818a7d6542SBram Moolenaar } 17828a7d6542SBram Moolenaar break; 17838a7d6542SBram Moolenaar 17848a7d6542SBram Moolenaar // end of ":try" block 17858a7d6542SBram Moolenaar case ISN_ENDTRY: 17868a7d6542SBram Moolenaar { 17878a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 17888a7d6542SBram Moolenaar 17898a7d6542SBram Moolenaar if (trystack->ga_len > 0) 17908a7d6542SBram Moolenaar { 179120431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 179220431c9dSBram Moolenaar 17938a7d6542SBram Moolenaar --trystack->ga_len; 17948a7d6542SBram Moolenaar --trylevel; 179568d130c6SBram Moolenaar ectx.ec_in_catch = FALSE; 17968a7d6542SBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 17978a7d6542SBram Moolenaar + trystack->ga_len; 1798f575adffSBram Moolenaar if (trycmd->tcd_caught && current_exception != NULL) 17998a7d6542SBram Moolenaar { 18008a7d6542SBram Moolenaar // discard the exception 18018a7d6542SBram Moolenaar if (caught_stack == current_exception) 18028a7d6542SBram Moolenaar caught_stack = caught_stack->caught; 18038a7d6542SBram Moolenaar discard_current_exception(); 18048a7d6542SBram Moolenaar } 18058a7d6542SBram Moolenaar 18068a7d6542SBram Moolenaar if (trycmd->tcd_return) 1807d032f34aSBram Moolenaar goto func_return; 18088a7d6542SBram Moolenaar } 18098a7d6542SBram Moolenaar } 18108a7d6542SBram Moolenaar break; 18118a7d6542SBram Moolenaar 18128a7d6542SBram Moolenaar case ISN_THROW: 18138a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 18148a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 18158a7d6542SBram Moolenaar if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL) 18168a7d6542SBram Moolenaar { 18178a7d6542SBram Moolenaar vim_free(tv->vval.v_string); 18188a7d6542SBram Moolenaar goto failed; 18198a7d6542SBram Moolenaar } 18208a7d6542SBram Moolenaar did_throw = TRUE; 18218a7d6542SBram Moolenaar break; 18228a7d6542SBram Moolenaar 18238a7d6542SBram Moolenaar // compare with special values 18248a7d6542SBram Moolenaar case ISN_COMPAREBOOL: 18258a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 18268a7d6542SBram Moolenaar { 18278a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 18288a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 18298a7d6542SBram Moolenaar varnumber_T arg1 = tv1->vval.v_number; 18308a7d6542SBram Moolenaar varnumber_T arg2 = tv2->vval.v_number; 18318a7d6542SBram Moolenaar int res; 18328a7d6542SBram Moolenaar 18338a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 18348a7d6542SBram Moolenaar { 18358a7d6542SBram Moolenaar case EXPR_EQUAL: res = arg1 == arg2; break; 18368a7d6542SBram Moolenaar case EXPR_NEQUAL: res = arg1 != arg2; break; 18378a7d6542SBram Moolenaar default: res = 0; break; 18388a7d6542SBram Moolenaar } 18398a7d6542SBram Moolenaar 18408a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 18418a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 18428a7d6542SBram Moolenaar tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; 18438a7d6542SBram Moolenaar } 18448a7d6542SBram Moolenaar break; 18458a7d6542SBram Moolenaar 18468a7d6542SBram Moolenaar // Operation with two number arguments 18478a7d6542SBram Moolenaar case ISN_OPNR: 18488a7d6542SBram Moolenaar case ISN_COMPARENR: 18498a7d6542SBram Moolenaar { 18508a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 18518a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 18528a7d6542SBram Moolenaar varnumber_T arg1 = tv1->vval.v_number; 18538a7d6542SBram Moolenaar varnumber_T arg2 = tv2->vval.v_number; 18548a7d6542SBram Moolenaar varnumber_T res; 18558a7d6542SBram Moolenaar 18568a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 18578a7d6542SBram Moolenaar { 18588a7d6542SBram Moolenaar case EXPR_MULT: res = arg1 * arg2; break; 18598a7d6542SBram Moolenaar case EXPR_DIV: res = arg1 / arg2; break; 18608a7d6542SBram Moolenaar case EXPR_REM: res = arg1 % arg2; break; 18618a7d6542SBram Moolenaar case EXPR_SUB: res = arg1 - arg2; break; 18628a7d6542SBram Moolenaar case EXPR_ADD: res = arg1 + arg2; break; 18638a7d6542SBram Moolenaar 18648a7d6542SBram Moolenaar case EXPR_EQUAL: res = arg1 == arg2; break; 18658a7d6542SBram Moolenaar case EXPR_NEQUAL: res = arg1 != arg2; break; 18668a7d6542SBram Moolenaar case EXPR_GREATER: res = arg1 > arg2; break; 18678a7d6542SBram Moolenaar case EXPR_GEQUAL: res = arg1 >= arg2; break; 18688a7d6542SBram Moolenaar case EXPR_SMALLER: res = arg1 < arg2; break; 18698a7d6542SBram Moolenaar case EXPR_SEQUAL: res = arg1 <= arg2; break; 18708a7d6542SBram Moolenaar default: res = 0; break; 18718a7d6542SBram Moolenaar } 18728a7d6542SBram Moolenaar 18738a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 18748a7d6542SBram Moolenaar if (iptr->isn_type == ISN_COMPARENR) 18758a7d6542SBram Moolenaar { 18768a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 18778a7d6542SBram Moolenaar tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; 18788a7d6542SBram Moolenaar } 18798a7d6542SBram Moolenaar else 18808a7d6542SBram Moolenaar tv1->vval.v_number = res; 18818a7d6542SBram Moolenaar } 18828a7d6542SBram Moolenaar break; 18838a7d6542SBram Moolenaar 18848a7d6542SBram Moolenaar // Computation with two float arguments 18858a7d6542SBram Moolenaar case ISN_OPFLOAT: 18868a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: 1887a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT 18888a7d6542SBram Moolenaar { 18898a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 18908a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 18918a7d6542SBram Moolenaar float_T arg1 = tv1->vval.v_float; 18928a7d6542SBram Moolenaar float_T arg2 = tv2->vval.v_float; 18938a7d6542SBram Moolenaar float_T res = 0; 18948a7d6542SBram Moolenaar int cmp = FALSE; 18958a7d6542SBram Moolenaar 18968a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 18978a7d6542SBram Moolenaar { 18988a7d6542SBram Moolenaar case EXPR_MULT: res = arg1 * arg2; break; 18998a7d6542SBram Moolenaar case EXPR_DIV: res = arg1 / arg2; break; 19008a7d6542SBram Moolenaar case EXPR_SUB: res = arg1 - arg2; break; 19018a7d6542SBram Moolenaar case EXPR_ADD: res = arg1 + arg2; break; 19028a7d6542SBram Moolenaar 19038a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = arg1 == arg2; break; 19048a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = arg1 != arg2; break; 19058a7d6542SBram Moolenaar case EXPR_GREATER: cmp = arg1 > arg2; break; 19068a7d6542SBram Moolenaar case EXPR_GEQUAL: cmp = arg1 >= arg2; break; 19078a7d6542SBram Moolenaar case EXPR_SMALLER: cmp = arg1 < arg2; break; 19088a7d6542SBram Moolenaar case EXPR_SEQUAL: cmp = arg1 <= arg2; break; 19098a7d6542SBram Moolenaar default: cmp = 0; break; 19108a7d6542SBram Moolenaar } 19118a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 19128a7d6542SBram Moolenaar if (iptr->isn_type == ISN_COMPAREFLOAT) 19138a7d6542SBram Moolenaar { 19148a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 19158a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 19168a7d6542SBram Moolenaar } 19178a7d6542SBram Moolenaar else 19188a7d6542SBram Moolenaar tv1->vval.v_float = res; 19198a7d6542SBram Moolenaar } 1920a5d5953dSBram Moolenaar #endif 19218a7d6542SBram Moolenaar break; 19228a7d6542SBram Moolenaar 19238a7d6542SBram Moolenaar case ISN_COMPARELIST: 19248a7d6542SBram Moolenaar { 19258a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 19268a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 19278a7d6542SBram Moolenaar list_T *arg1 = tv1->vval.v_list; 19288a7d6542SBram Moolenaar list_T *arg2 = tv2->vval.v_list; 19298a7d6542SBram Moolenaar int cmp = FALSE; 19308a7d6542SBram Moolenaar int ic = iptr->isn_arg.op.op_ic; 19318a7d6542SBram Moolenaar 19328a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 19338a7d6542SBram Moolenaar { 19348a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = 19358a7d6542SBram Moolenaar list_equal(arg1, arg2, ic, FALSE); break; 19368a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = 19378a7d6542SBram Moolenaar !list_equal(arg1, arg2, ic, FALSE); break; 19388a7d6542SBram Moolenaar case EXPR_IS: cmp = arg1 == arg2; break; 19398a7d6542SBram Moolenaar case EXPR_ISNOT: cmp = arg1 != arg2; break; 19408a7d6542SBram Moolenaar default: cmp = 0; break; 19418a7d6542SBram Moolenaar } 19428a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 19438a7d6542SBram Moolenaar clear_tv(tv1); 19448a7d6542SBram Moolenaar clear_tv(tv2); 19458a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 19468a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 19478a7d6542SBram Moolenaar } 19488a7d6542SBram Moolenaar break; 19498a7d6542SBram Moolenaar 19508a7d6542SBram Moolenaar case ISN_COMPAREBLOB: 19518a7d6542SBram Moolenaar { 19528a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 19538a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 19548a7d6542SBram Moolenaar blob_T *arg1 = tv1->vval.v_blob; 19558a7d6542SBram Moolenaar blob_T *arg2 = tv2->vval.v_blob; 19568a7d6542SBram Moolenaar int cmp = FALSE; 19578a7d6542SBram Moolenaar 19588a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 19598a7d6542SBram Moolenaar { 19608a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break; 19618a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break; 19628a7d6542SBram Moolenaar case EXPR_IS: cmp = arg1 == arg2; break; 19638a7d6542SBram Moolenaar case EXPR_ISNOT: cmp = arg1 != arg2; break; 19648a7d6542SBram Moolenaar default: cmp = 0; break; 19658a7d6542SBram Moolenaar } 19668a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 19678a7d6542SBram Moolenaar clear_tv(tv1); 19688a7d6542SBram Moolenaar clear_tv(tv2); 19698a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 19708a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 19718a7d6542SBram Moolenaar } 19728a7d6542SBram Moolenaar break; 19738a7d6542SBram Moolenaar 19748a7d6542SBram Moolenaar // TODO: handle separately 19758a7d6542SBram Moolenaar case ISN_COMPARESTRING: 19768a7d6542SBram Moolenaar case ISN_COMPAREDICT: 19778a7d6542SBram Moolenaar case ISN_COMPAREFUNC: 19788a7d6542SBram Moolenaar case ISN_COMPAREANY: 19798a7d6542SBram Moolenaar { 19808a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 19818a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 19828a7d6542SBram Moolenaar exptype_T exptype = iptr->isn_arg.op.op_type; 19838a7d6542SBram Moolenaar int ic = iptr->isn_arg.op.op_ic; 19848a7d6542SBram Moolenaar 19858a7d6542SBram Moolenaar typval_compare(tv1, tv2, exptype, ic); 19868a7d6542SBram Moolenaar clear_tv(tv2); 19878a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 19888a7d6542SBram Moolenaar tv1->vval.v_number = tv1->vval.v_number 19898a7d6542SBram Moolenaar ? VVAL_TRUE : VVAL_FALSE; 19908a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 19918a7d6542SBram Moolenaar } 19928a7d6542SBram Moolenaar break; 19938a7d6542SBram Moolenaar 19948a7d6542SBram Moolenaar case ISN_ADDLIST: 19958a7d6542SBram Moolenaar case ISN_ADDBLOB: 19968a7d6542SBram Moolenaar { 19978a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 19988a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 19998a7d6542SBram Moolenaar 20008a7d6542SBram Moolenaar if (iptr->isn_type == ISN_ADDLIST) 20018a7d6542SBram Moolenaar eval_addlist(tv1, tv2); 20028a7d6542SBram Moolenaar else 20038a7d6542SBram Moolenaar eval_addblob(tv1, tv2); 20048a7d6542SBram Moolenaar clear_tv(tv2); 20058a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 20068a7d6542SBram Moolenaar } 20078a7d6542SBram Moolenaar break; 20088a7d6542SBram Moolenaar 20098a7d6542SBram Moolenaar // Computation with two arguments of unknown type 20108a7d6542SBram Moolenaar case ISN_OPANY: 20118a7d6542SBram Moolenaar { 20128a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 20138a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 20148a7d6542SBram Moolenaar varnumber_T n1, n2; 20158a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 20168a7d6542SBram Moolenaar float_T f1 = 0, f2 = 0; 20178a7d6542SBram Moolenaar #endif 20188a7d6542SBram Moolenaar int error = FALSE; 20198a7d6542SBram Moolenaar 20208a7d6542SBram Moolenaar if (iptr->isn_arg.op.op_type == EXPR_ADD) 20218a7d6542SBram Moolenaar { 20228a7d6542SBram Moolenaar if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST) 20238a7d6542SBram Moolenaar { 20248a7d6542SBram Moolenaar eval_addlist(tv1, tv2); 20258a7d6542SBram Moolenaar clear_tv(tv2); 20268a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 20278a7d6542SBram Moolenaar break; 20288a7d6542SBram Moolenaar } 20298a7d6542SBram Moolenaar else if (tv1->v_type == VAR_BLOB 20308a7d6542SBram Moolenaar && tv2->v_type == VAR_BLOB) 20318a7d6542SBram Moolenaar { 20328a7d6542SBram Moolenaar eval_addblob(tv1, tv2); 20338a7d6542SBram Moolenaar clear_tv(tv2); 20348a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 20358a7d6542SBram Moolenaar break; 20368a7d6542SBram Moolenaar } 20378a7d6542SBram Moolenaar } 20388a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 20398a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT) 20408a7d6542SBram Moolenaar { 20418a7d6542SBram Moolenaar f1 = tv1->vval.v_float; 20428a7d6542SBram Moolenaar n1 = 0; 20438a7d6542SBram Moolenaar } 20448a7d6542SBram Moolenaar else 20458a7d6542SBram Moolenaar #endif 20468a7d6542SBram Moolenaar { 20478a7d6542SBram Moolenaar n1 = tv_get_number_chk(tv1, &error); 20488a7d6542SBram Moolenaar if (error) 2049d032f34aSBram Moolenaar goto on_error; 20508a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 20518a7d6542SBram Moolenaar if (tv2->v_type == VAR_FLOAT) 20528a7d6542SBram Moolenaar f1 = n1; 20538a7d6542SBram Moolenaar #endif 20548a7d6542SBram Moolenaar } 20558a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 20568a7d6542SBram Moolenaar if (tv2->v_type == VAR_FLOAT) 20578a7d6542SBram Moolenaar { 20588a7d6542SBram Moolenaar f2 = tv2->vval.v_float; 20598a7d6542SBram Moolenaar n2 = 0; 20608a7d6542SBram Moolenaar } 20618a7d6542SBram Moolenaar else 20628a7d6542SBram Moolenaar #endif 20638a7d6542SBram Moolenaar { 20648a7d6542SBram Moolenaar n2 = tv_get_number_chk(tv2, &error); 20658a7d6542SBram Moolenaar if (error) 2066d032f34aSBram Moolenaar goto on_error; 20678a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 20688a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT) 20698a7d6542SBram Moolenaar f2 = n2; 20708a7d6542SBram Moolenaar #endif 20718a7d6542SBram Moolenaar } 20728a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 20738a7d6542SBram Moolenaar // if there is a float on either side the result is a float 20748a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT) 20758a7d6542SBram Moolenaar { 20768a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 20778a7d6542SBram Moolenaar { 20788a7d6542SBram Moolenaar case EXPR_MULT: f1 = f1 * f2; break; 20798a7d6542SBram Moolenaar case EXPR_DIV: f1 = f1 / f2; break; 20808a7d6542SBram Moolenaar case EXPR_SUB: f1 = f1 - f2; break; 20818a7d6542SBram Moolenaar case EXPR_ADD: f1 = f1 + f2; break; 208268d130c6SBram Moolenaar default: emsg(_(e_modulus)); 2083f0b9f43cSBram Moolenaar goto on_error; 20848a7d6542SBram Moolenaar } 20858a7d6542SBram Moolenaar clear_tv(tv1); 20868a7d6542SBram Moolenaar clear_tv(tv2); 20878a7d6542SBram Moolenaar tv1->v_type = VAR_FLOAT; 20888a7d6542SBram Moolenaar tv1->vval.v_float = f1; 20898a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 20908a7d6542SBram Moolenaar } 20918a7d6542SBram Moolenaar else 20928a7d6542SBram Moolenaar #endif 20938a7d6542SBram Moolenaar { 20948a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 20958a7d6542SBram Moolenaar { 20968a7d6542SBram Moolenaar case EXPR_MULT: n1 = n1 * n2; break; 20978a7d6542SBram Moolenaar case EXPR_DIV: n1 = num_divide(n1, n2); break; 20988a7d6542SBram Moolenaar case EXPR_SUB: n1 = n1 - n2; break; 20998a7d6542SBram Moolenaar case EXPR_ADD: n1 = n1 + n2; break; 21008a7d6542SBram Moolenaar default: n1 = num_modulus(n1, n2); break; 21018a7d6542SBram Moolenaar } 21028a7d6542SBram Moolenaar clear_tv(tv1); 21038a7d6542SBram Moolenaar clear_tv(tv2); 21048a7d6542SBram Moolenaar tv1->v_type = VAR_NUMBER; 21058a7d6542SBram Moolenaar tv1->vval.v_number = n1; 21068a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 21078a7d6542SBram Moolenaar } 21088a7d6542SBram Moolenaar } 21098a7d6542SBram Moolenaar break; 21108a7d6542SBram Moolenaar 21118a7d6542SBram Moolenaar case ISN_CONCAT: 21128a7d6542SBram Moolenaar { 21138a7d6542SBram Moolenaar char_u *str1 = STACK_TV_BOT(-2)->vval.v_string; 21148a7d6542SBram Moolenaar char_u *str2 = STACK_TV_BOT(-1)->vval.v_string; 21158a7d6542SBram Moolenaar char_u *res; 21168a7d6542SBram Moolenaar 21178a7d6542SBram Moolenaar res = concat_str(str1, str2); 21188a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(-2)); 21198a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 21208a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 21218a7d6542SBram Moolenaar STACK_TV_BOT(-1)->vval.v_string = res; 21228a7d6542SBram Moolenaar } 21238a7d6542SBram Moolenaar break; 21248a7d6542SBram Moolenaar 21258a7d6542SBram Moolenaar case ISN_INDEX: 21268a7d6542SBram Moolenaar { 21278a7d6542SBram Moolenaar list_T *list; 21288a7d6542SBram Moolenaar varnumber_T n; 21298a7d6542SBram Moolenaar listitem_T *li; 2130435d8978SBram Moolenaar typval_T temp_tv; 21318a7d6542SBram Moolenaar 21328a7d6542SBram Moolenaar // list index: list is at stack-2, index at stack-1 21338a7d6542SBram Moolenaar tv = STACK_TV_BOT(-2); 21348a7d6542SBram Moolenaar if (tv->v_type != VAR_LIST) 21358a7d6542SBram Moolenaar { 21368a7d6542SBram Moolenaar emsg(_(e_listreq)); 2137f0b9f43cSBram Moolenaar goto on_error; 21388a7d6542SBram Moolenaar } 21398a7d6542SBram Moolenaar list = tv->vval.v_list; 21408a7d6542SBram Moolenaar 21418a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 21428a7d6542SBram Moolenaar if (tv->v_type != VAR_NUMBER) 21438a7d6542SBram Moolenaar { 21448a7d6542SBram Moolenaar emsg(_(e_number_exp)); 2145f0b9f43cSBram Moolenaar goto on_error; 21468a7d6542SBram Moolenaar } 21478a7d6542SBram Moolenaar n = tv->vval.v_number; 21488a7d6542SBram Moolenaar clear_tv(tv); 21498a7d6542SBram Moolenaar if ((li = list_find(list, n)) == NULL) 21508a7d6542SBram Moolenaar { 21518a7d6542SBram Moolenaar semsg(_(e_listidx), n); 2152f0b9f43cSBram Moolenaar goto on_error; 21538a7d6542SBram Moolenaar } 21548a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 2155435d8978SBram Moolenaar // Clear the list after getting the item, to avoid that it 215668d130c6SBram Moolenaar // makes the item invalid. 2157435d8978SBram Moolenaar tv = STACK_TV_BOT(-1); 2158435d8978SBram Moolenaar temp_tv = *tv; 2159435d8978SBram Moolenaar copy_tv(&li->li_tv, tv); 2160435d8978SBram Moolenaar clear_tv(&temp_tv); 21618a7d6542SBram Moolenaar } 21628a7d6542SBram Moolenaar break; 21638a7d6542SBram Moolenaar 21649af78769SBram Moolenaar case ISN_SLICE: 21659af78769SBram Moolenaar { 21669af78769SBram Moolenaar list_T *list; 21679af78769SBram Moolenaar int count = iptr->isn_arg.number; 21689af78769SBram Moolenaar 2169c5b1c20bSBram Moolenaar // type will have been checked to be a list 21709af78769SBram Moolenaar tv = STACK_TV_BOT(-1); 21719af78769SBram Moolenaar list = tv->vval.v_list; 21729af78769SBram Moolenaar 21739af78769SBram Moolenaar // no error for short list, expect it to be checked earlier 21749af78769SBram Moolenaar if (list != NULL && list->lv_len >= count) 21759af78769SBram Moolenaar { 21769af78769SBram Moolenaar list_T *newlist = list_slice(list, 21779af78769SBram Moolenaar count, list->lv_len - 1); 21789af78769SBram Moolenaar 21799af78769SBram Moolenaar if (newlist != NULL) 21809af78769SBram Moolenaar { 21819af78769SBram Moolenaar list_unref(list); 21829af78769SBram Moolenaar tv->vval.v_list = newlist; 21839af78769SBram Moolenaar ++newlist->lv_refcount; 21849af78769SBram Moolenaar } 21859af78769SBram Moolenaar } 21869af78769SBram Moolenaar } 21879af78769SBram Moolenaar break; 21889af78769SBram Moolenaar 218947a519a9SBram Moolenaar case ISN_GETITEM: 219047a519a9SBram Moolenaar { 219147a519a9SBram Moolenaar listitem_T *li; 219247a519a9SBram Moolenaar int index = iptr->isn_arg.number; 219347a519a9SBram Moolenaar 2194c785b9a7SBram Moolenaar // Get list item: list is at stack-1, push item. 2195c785b9a7SBram Moolenaar // List type and length is checked for when compiling. 219647a519a9SBram Moolenaar tv = STACK_TV_BOT(-1); 2197c785b9a7SBram Moolenaar li = list_find(tv->vval.v_list, index); 219847a519a9SBram Moolenaar 219947a519a9SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 220047a519a9SBram Moolenaar goto failed; 220147a519a9SBram Moolenaar ++ectx.ec_stack.ga_len; 220247a519a9SBram Moolenaar copy_tv(&li->li_tv, STACK_TV_BOT(-1)); 220347a519a9SBram Moolenaar } 220447a519a9SBram Moolenaar break; 220547a519a9SBram Moolenaar 22068a7d6542SBram Moolenaar case ISN_MEMBER: 22078a7d6542SBram Moolenaar { 22088a7d6542SBram Moolenaar dict_T *dict; 22091cc2a94fSBram Moolenaar char_u *key; 22101cc2a94fSBram Moolenaar dictitem_T *di; 221150788ef3SBram Moolenaar typval_T temp_tv; 22121cc2a94fSBram Moolenaar 22131cc2a94fSBram Moolenaar // dict member: dict is at stack-2, key at stack-1 22141cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-2); 22154dac32caSBram Moolenaar // no need to check for VAR_DICT, CHECKTYPE will check. 22161cc2a94fSBram Moolenaar dict = tv->vval.v_dict; 22171cc2a94fSBram Moolenaar 22181cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-1); 22194dac32caSBram Moolenaar // no need to check for VAR_STRING, 2STRING will check. 22201cc2a94fSBram Moolenaar key = tv->vval.v_string; 22214dac32caSBram Moolenaar 22221cc2a94fSBram Moolenaar if ((di = dict_find(dict, key, -1)) == NULL) 22231cc2a94fSBram Moolenaar { 22241cc2a94fSBram Moolenaar semsg(_(e_dictkey), key); 2225f0b9f43cSBram Moolenaar goto on_error; 22261cc2a94fSBram Moolenaar } 22271cc2a94fSBram Moolenaar clear_tv(tv); 222850788ef3SBram Moolenaar --ectx.ec_stack.ga_len; 222950788ef3SBram Moolenaar // Clear the dict after getting the item, to avoid that it 223050788ef3SBram Moolenaar // make the item invalid. 223150788ef3SBram Moolenaar tv = STACK_TV_BOT(-1); 223250788ef3SBram Moolenaar temp_tv = *tv; 223350788ef3SBram Moolenaar copy_tv(&di->di_tv, tv); 223450788ef3SBram Moolenaar clear_tv(&temp_tv); 22351cc2a94fSBram Moolenaar } 22361cc2a94fSBram Moolenaar break; 22371cc2a94fSBram Moolenaar 22381cc2a94fSBram Moolenaar // dict member with string key 22391cc2a94fSBram Moolenaar case ISN_STRINGMEMBER: 22401cc2a94fSBram Moolenaar { 22411cc2a94fSBram Moolenaar dict_T *dict; 22428a7d6542SBram Moolenaar dictitem_T *di; 2243fb9d5c51SBram Moolenaar typval_T temp_tv; 22448a7d6542SBram Moolenaar 22458a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 22468a7d6542SBram Moolenaar if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) 22478a7d6542SBram Moolenaar { 22488a7d6542SBram Moolenaar emsg(_(e_dictreq)); 2249d032f34aSBram Moolenaar goto on_error; 22508a7d6542SBram Moolenaar } 22518a7d6542SBram Moolenaar dict = tv->vval.v_dict; 22528a7d6542SBram Moolenaar 22538a7d6542SBram Moolenaar if ((di = dict_find(dict, iptr->isn_arg.string, -1)) 22548a7d6542SBram Moolenaar == NULL) 22558a7d6542SBram Moolenaar { 22568a7d6542SBram Moolenaar semsg(_(e_dictkey), iptr->isn_arg.string); 2257d032f34aSBram Moolenaar goto on_error; 22588a7d6542SBram Moolenaar } 2259fb9d5c51SBram Moolenaar // Clear the dict after getting the item, to avoid that it 2260fb9d5c51SBram Moolenaar // make the item invalid. 2261fb9d5c51SBram Moolenaar temp_tv = *tv; 22628a7d6542SBram Moolenaar copy_tv(&di->di_tv, tv); 2263fb9d5c51SBram Moolenaar clear_tv(&temp_tv); 22648a7d6542SBram Moolenaar } 22658a7d6542SBram Moolenaar break; 22668a7d6542SBram Moolenaar 22678a7d6542SBram Moolenaar case ISN_NEGATENR: 22688a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 2269c58164c5SBram Moolenaar if (tv->v_type != VAR_NUMBER 2270c58164c5SBram Moolenaar #ifdef FEAT_FLOAT 2271c58164c5SBram Moolenaar && tv->v_type != VAR_FLOAT 2272c58164c5SBram Moolenaar #endif 2273c58164c5SBram Moolenaar ) 2274c58164c5SBram Moolenaar { 2275c58164c5SBram Moolenaar emsg(_(e_number_exp)); 2276f0b9f43cSBram Moolenaar goto on_error; 2277c58164c5SBram Moolenaar } 2278c58164c5SBram Moolenaar #ifdef FEAT_FLOAT 2279c58164c5SBram Moolenaar if (tv->v_type == VAR_FLOAT) 2280c58164c5SBram Moolenaar tv->vval.v_float = -tv->vval.v_float; 2281c58164c5SBram Moolenaar else 2282c58164c5SBram Moolenaar #endif 22838a7d6542SBram Moolenaar tv->vval.v_number = -tv->vval.v_number; 22848a7d6542SBram Moolenaar break; 22858a7d6542SBram Moolenaar 22868a7d6542SBram Moolenaar case ISN_CHECKNR: 22878a7d6542SBram Moolenaar { 22888a7d6542SBram Moolenaar int error = FALSE; 22898a7d6542SBram Moolenaar 22908a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 22918a7d6542SBram Moolenaar if (check_not_string(tv) == FAIL) 2292f0b9f43cSBram Moolenaar goto on_error; 22938a7d6542SBram Moolenaar (void)tv_get_number_chk(tv, &error); 22948a7d6542SBram Moolenaar if (error) 2295f0b9f43cSBram Moolenaar goto on_error; 22968a7d6542SBram Moolenaar } 22978a7d6542SBram Moolenaar break; 22988a7d6542SBram Moolenaar 22998a7d6542SBram Moolenaar case ISN_CHECKTYPE: 23008a7d6542SBram Moolenaar { 23018a7d6542SBram Moolenaar checktype_T *ct = &iptr->isn_arg.type; 23028a7d6542SBram Moolenaar 23038a7d6542SBram Moolenaar tv = STACK_TV_BOT(ct->ct_off); 2304c8cd2b34SBram Moolenaar // TODO: better type comparison 2305c8cd2b34SBram Moolenaar if (tv->v_type != ct->ct_type 2306c8cd2b34SBram Moolenaar && !((tv->v_type == VAR_PARTIAL 2307c8cd2b34SBram Moolenaar && ct->ct_type == VAR_FUNC) 2308c8cd2b34SBram Moolenaar || (tv->v_type == VAR_FUNC 2309c8cd2b34SBram Moolenaar && ct->ct_type == VAR_PARTIAL))) 23108a7d6542SBram Moolenaar { 23118a7d6542SBram Moolenaar semsg(_("E1029: Expected %s but got %s"), 23128a7d6542SBram Moolenaar vartype_name(ct->ct_type), 23138a7d6542SBram Moolenaar vartype_name(tv->v_type)); 2314f0b9f43cSBram Moolenaar goto on_error; 23158a7d6542SBram Moolenaar } 23168a7d6542SBram Moolenaar } 23178a7d6542SBram Moolenaar break; 23188a7d6542SBram Moolenaar 23199af78769SBram Moolenaar case ISN_CHECKLEN: 23209af78769SBram Moolenaar { 23219af78769SBram Moolenaar int min_len = iptr->isn_arg.checklen.cl_min_len; 23229af78769SBram Moolenaar list_T *list = NULL; 23239af78769SBram Moolenaar 23249af78769SBram Moolenaar tv = STACK_TV_BOT(-1); 23259af78769SBram Moolenaar if (tv->v_type == VAR_LIST) 23269af78769SBram Moolenaar list = tv->vval.v_list; 23279af78769SBram Moolenaar if (list == NULL || list->lv_len < min_len 23289af78769SBram Moolenaar || (list->lv_len > min_len 23299af78769SBram Moolenaar && !iptr->isn_arg.checklen.cl_more_OK)) 23309af78769SBram Moolenaar { 23319af78769SBram Moolenaar semsg(_("E1093: Expected %d items but got %d"), 23329af78769SBram Moolenaar min_len, list == NULL ? 0 : list->lv_len); 2333f0b9f43cSBram Moolenaar goto on_error; 23349af78769SBram Moolenaar } 23359af78769SBram Moolenaar } 23369af78769SBram Moolenaar break; 23379af78769SBram Moolenaar 23388a7d6542SBram Moolenaar case ISN_2BOOL: 23398a7d6542SBram Moolenaar { 23408a7d6542SBram Moolenaar int n; 23418a7d6542SBram Moolenaar 23428a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 23438a7d6542SBram Moolenaar n = tv2bool(tv); 23448a7d6542SBram Moolenaar if (iptr->isn_arg.number) // invert 23458a7d6542SBram Moolenaar n = !n; 23468a7d6542SBram Moolenaar clear_tv(tv); 23478a7d6542SBram Moolenaar tv->v_type = VAR_BOOL; 23488a7d6542SBram Moolenaar tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE; 23498a7d6542SBram Moolenaar } 23508a7d6542SBram Moolenaar break; 23518a7d6542SBram Moolenaar 23528a7d6542SBram Moolenaar case ISN_2STRING: 23538a7d6542SBram Moolenaar { 23548a7d6542SBram Moolenaar char_u *str; 23558a7d6542SBram Moolenaar 23568a7d6542SBram Moolenaar tv = STACK_TV_BOT(iptr->isn_arg.number); 23578a7d6542SBram Moolenaar if (tv->v_type != VAR_STRING) 23588a7d6542SBram Moolenaar { 23598a7d6542SBram Moolenaar str = typval_tostring(tv); 23608a7d6542SBram Moolenaar clear_tv(tv); 23618a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 23628a7d6542SBram Moolenaar tv->vval.v_string = str; 23638a7d6542SBram Moolenaar } 23648a7d6542SBram Moolenaar } 23658a7d6542SBram Moolenaar break; 23668a7d6542SBram Moolenaar 2367389df259SBram Moolenaar case ISN_SHUFFLE: 2368389df259SBram Moolenaar { 2369389df259SBram Moolenaar typval_T tmp_tv; 2370389df259SBram Moolenaar int item = iptr->isn_arg.shuffle.shfl_item; 2371389df259SBram Moolenaar int up = iptr->isn_arg.shuffle.shfl_up; 2372389df259SBram Moolenaar 2373389df259SBram Moolenaar tmp_tv = *STACK_TV_BOT(-item); 2374389df259SBram Moolenaar for ( ; up > 0 && item > 1; --up) 2375389df259SBram Moolenaar { 2376389df259SBram Moolenaar *STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1); 2377389df259SBram Moolenaar --item; 2378389df259SBram Moolenaar } 2379389df259SBram Moolenaar *STACK_TV_BOT(-item) = tmp_tv; 2380389df259SBram Moolenaar } 2381389df259SBram Moolenaar break; 2382389df259SBram Moolenaar 23838a7d6542SBram Moolenaar case ISN_DROP: 23848a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 23858a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(0)); 23868a7d6542SBram Moolenaar break; 23878a7d6542SBram Moolenaar } 2388f0b9f43cSBram Moolenaar continue; 2389f0b9f43cSBram Moolenaar 2390d032f34aSBram Moolenaar func_return: 2391d032f34aSBram Moolenaar // Restore previous function. If the frame pointer is zero then there 2392d032f34aSBram Moolenaar // is none and we are done. 2393d032f34aSBram Moolenaar if (ectx.ec_frame_idx == initial_frame_idx) 2394d032f34aSBram Moolenaar { 2395d032f34aSBram Moolenaar if (handle_closure_in_use(&ectx, FALSE) == FAIL) 2396d032f34aSBram Moolenaar // only fails when out of memory 2397d032f34aSBram Moolenaar goto failed; 2398d032f34aSBram Moolenaar goto done; 2399d032f34aSBram Moolenaar } 2400d032f34aSBram Moolenaar if (func_return(&ectx) == FAIL) 2401d032f34aSBram Moolenaar // only fails when out of memory 2402d032f34aSBram Moolenaar goto failed; 2403d032f34aSBram Moolenaar 2404f0b9f43cSBram Moolenaar on_error: 2405f0b9f43cSBram Moolenaar if (trylevel == 0) 2406f0b9f43cSBram Moolenaar goto failed; 24078a7d6542SBram Moolenaar } 24088a7d6542SBram Moolenaar 24098a7d6542SBram Moolenaar done: 24108a7d6542SBram Moolenaar // function finished, get result from the stack. 24118a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 24128a7d6542SBram Moolenaar *rettv = *tv; 24138a7d6542SBram Moolenaar tv->v_type = VAR_UNKNOWN; 24148a7d6542SBram Moolenaar ret = OK; 24158a7d6542SBram Moolenaar 24168a7d6542SBram Moolenaar failed: 24177eeefd4aSBram Moolenaar // When failed need to unwind the call stack. 2418bf67ea1aSBram Moolenaar while (ectx.ec_frame_idx != initial_frame_idx) 24197eeefd4aSBram Moolenaar func_return(&ectx); 24201a2f4bf6SBram Moolenaar failed_early: 2421a26b9700SBram Moolenaar current_sctx.sc_version = save_sc_version; 2422bf67ea1aSBram Moolenaar 2423bf67ea1aSBram Moolenaar // Free all local variables, but not arguments. 24248a7d6542SBram Moolenaar for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx) 24258a7d6542SBram Moolenaar clear_tv(STACK_TV(idx)); 2426bf67ea1aSBram Moolenaar 24278a7d6542SBram Moolenaar vim_free(ectx.ec_stack.ga_data); 242820431c9dSBram Moolenaar vim_free(ectx.ec_trystack.ga_data); 24298a7d6542SBram Moolenaar return ret; 24308a7d6542SBram Moolenaar } 24318a7d6542SBram Moolenaar 24328a7d6542SBram Moolenaar /* 24338a7d6542SBram Moolenaar * ":dissassemble". 2434777770fbSBram Moolenaar * We don't really need this at runtime, but we do have tests that require it, 2435777770fbSBram Moolenaar * so always include this. 24368a7d6542SBram Moolenaar */ 24378a7d6542SBram Moolenaar void 24388a7d6542SBram Moolenaar ex_disassemble(exarg_T *eap) 24398a7d6542SBram Moolenaar { 244021456cdcSBram Moolenaar char_u *arg = eap->arg; 24410f18b6d1SBram Moolenaar char_u *fname; 24420f18b6d1SBram Moolenaar ufunc_T *ufunc; 24438a7d6542SBram Moolenaar dfunc_T *dfunc; 24448a7d6542SBram Moolenaar isn_T *instr; 24458a7d6542SBram Moolenaar int current; 24468a7d6542SBram Moolenaar int line_idx = 0; 24478a7d6542SBram Moolenaar int prev_current = 0; 24484c17ad94SBram Moolenaar int is_global = FALSE; 24498a7d6542SBram Moolenaar 2450bfd65589SBram Moolenaar if (STRNCMP(arg, "<lambda>", 8) == 0) 2451bfd65589SBram Moolenaar { 2452bfd65589SBram Moolenaar arg += 8; 2453bfd65589SBram Moolenaar (void)getdigits(&arg); 2454bfd65589SBram Moolenaar fname = vim_strnsave(eap->arg, arg - eap->arg); 2455bfd65589SBram Moolenaar } 2456bfd65589SBram Moolenaar else 24574c17ad94SBram Moolenaar fname = trans_function_name(&arg, &is_global, FALSE, 2458b68b346eSBram Moolenaar TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL); 245921456cdcSBram Moolenaar if (fname == NULL) 246021456cdcSBram Moolenaar { 246121456cdcSBram Moolenaar semsg(_(e_invarg2), eap->arg); 246221456cdcSBram Moolenaar return; 246321456cdcSBram Moolenaar } 246421456cdcSBram Moolenaar 24654c17ad94SBram Moolenaar ufunc = find_func(fname, is_global, NULL); 2466a26b9700SBram Moolenaar if (ufunc == NULL) 2467a26b9700SBram Moolenaar { 2468a26b9700SBram Moolenaar char_u *p = untrans_function_name(fname); 2469a26b9700SBram Moolenaar 2470a26b9700SBram Moolenaar if (p != NULL) 2471a26b9700SBram Moolenaar // Try again without making it script-local. 24724c17ad94SBram Moolenaar ufunc = find_func(p, FALSE, NULL); 2473a26b9700SBram Moolenaar } 24740f18b6d1SBram Moolenaar vim_free(fname); 24758a7d6542SBram Moolenaar if (ufunc == NULL) 24768a7d6542SBram Moolenaar { 2477df2ecddfSBram Moolenaar semsg(_("E1061: Cannot find function %s"), eap->arg); 24788a7d6542SBram Moolenaar return; 24798a7d6542SBram Moolenaar } 24800cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_TO_BE_COMPILED 2481822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL) 2482822ba247SBram Moolenaar return; 24830cb5bcf5SBram Moolenaar if (ufunc->uf_def_status != UF_COMPILED) 24848a7d6542SBram Moolenaar { 2485df2ecddfSBram Moolenaar semsg(_("E1062: Function %s is not compiled"), eap->arg); 24868a7d6542SBram Moolenaar return; 24878a7d6542SBram Moolenaar } 24888a7d6542SBram Moolenaar if (ufunc->uf_name_exp != NULL) 24898a7d6542SBram Moolenaar msg((char *)ufunc->uf_name_exp); 24908a7d6542SBram Moolenaar else 24918a7d6542SBram Moolenaar msg((char *)ufunc->uf_name); 24928a7d6542SBram Moolenaar 24938a7d6542SBram Moolenaar dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; 24948a7d6542SBram Moolenaar instr = dfunc->df_instr; 24958a7d6542SBram Moolenaar for (current = 0; current < dfunc->df_instr_count; ++current) 24968a7d6542SBram Moolenaar { 24978a7d6542SBram Moolenaar isn_T *iptr = &instr[current]; 2498f2460a3aSBram Moolenaar char *line; 24998a7d6542SBram Moolenaar 25008a7d6542SBram Moolenaar while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len) 25018a7d6542SBram Moolenaar { 25028a7d6542SBram Moolenaar if (current > prev_current) 25038a7d6542SBram Moolenaar { 25048a7d6542SBram Moolenaar msg_puts("\n\n"); 25058a7d6542SBram Moolenaar prev_current = current; 25068a7d6542SBram Moolenaar } 2507f2460a3aSBram Moolenaar line = ((char **)ufunc->uf_lines.ga_data)[line_idx++]; 2508f2460a3aSBram Moolenaar if (line != NULL) 2509f2460a3aSBram Moolenaar msg(line); 25108a7d6542SBram Moolenaar } 25118a7d6542SBram Moolenaar 25128a7d6542SBram Moolenaar switch (iptr->isn_type) 25138a7d6542SBram Moolenaar { 25148a7d6542SBram Moolenaar case ISN_EXEC: 25158a7d6542SBram Moolenaar smsg("%4d EXEC %s", current, iptr->isn_arg.string); 25168a7d6542SBram Moolenaar break; 2517cfe435d7SBram Moolenaar case ISN_EXECCONCAT: 2518cfe435d7SBram Moolenaar smsg("%4d EXECCONCAT %lld", current, 2519cfe435d7SBram Moolenaar (long long)iptr->isn_arg.number); 2520cfe435d7SBram Moolenaar break; 25218a7d6542SBram Moolenaar case ISN_ECHO: 25228a7d6542SBram Moolenaar { 25238a7d6542SBram Moolenaar echo_T *echo = &iptr->isn_arg.echo; 25248a7d6542SBram Moolenaar 25258a7d6542SBram Moolenaar smsg("%4d %s %d", current, 25268a7d6542SBram Moolenaar echo->echo_with_white ? "ECHO" : "ECHON", 25278a7d6542SBram Moolenaar echo->echo_count); 25288a7d6542SBram Moolenaar } 25298a7d6542SBram Moolenaar break; 2530ad39c094SBram Moolenaar case ISN_EXECUTE: 25311082772fSBram Moolenaar smsg("%4d EXECUTE %lld", current, 25321082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 2533ad39c094SBram Moolenaar break; 2534f93c7feaSBram Moolenaar case ISN_ECHOMSG: 2535f93c7feaSBram Moolenaar smsg("%4d ECHOMSG %lld", current, 2536f93c7feaSBram Moolenaar (long long)(iptr->isn_arg.number)); 2537f93c7feaSBram Moolenaar break; 2538f93c7feaSBram Moolenaar case ISN_ECHOERR: 2539f93c7feaSBram Moolenaar smsg("%4d ECHOERR %lld", current, 2540f93c7feaSBram Moolenaar (long long)(iptr->isn_arg.number)); 2541f93c7feaSBram Moolenaar break; 25428a7d6542SBram Moolenaar case ISN_LOAD: 2543c8cd2b34SBram Moolenaar case ISN_LOADOUTER: 2544c8cd2b34SBram Moolenaar { 2545c8cd2b34SBram Moolenaar char *add = iptr->isn_type == ISN_LOAD ? "" : "OUTER"; 2546c8cd2b34SBram Moolenaar 25478a7d6542SBram Moolenaar if (iptr->isn_arg.number < 0) 2548c8cd2b34SBram Moolenaar smsg("%4d LOAD%s arg[%lld]", current, add, 2549c8cd2b34SBram Moolenaar (long long)(iptr->isn_arg.number 2550c8cd2b34SBram Moolenaar + STACK_FRAME_SIZE)); 25518a7d6542SBram Moolenaar else 2552c8cd2b34SBram Moolenaar smsg("%4d LOAD%s $%lld", current, add, 25531082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 2554c8cd2b34SBram Moolenaar } 25558a7d6542SBram Moolenaar break; 25568a7d6542SBram Moolenaar case ISN_LOADV: 25578a7d6542SBram Moolenaar smsg("%4d LOADV v:%s", current, 25588a7d6542SBram Moolenaar get_vim_var_name(iptr->isn_arg.number)); 25598a7d6542SBram Moolenaar break; 25608a7d6542SBram Moolenaar case ISN_LOADSCRIPT: 25618a7d6542SBram Moolenaar { 25628a7d6542SBram Moolenaar scriptitem_T *si = 256321b9e977SBram Moolenaar SCRIPT_ITEM(iptr->isn_arg.script.script_sid); 25648a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 25658a7d6542SBram Moolenaar + iptr->isn_arg.script.script_idx; 25668a7d6542SBram Moolenaar 25678a7d6542SBram Moolenaar smsg("%4d LOADSCRIPT %s from %s", current, 25688a7d6542SBram Moolenaar sv->sv_name, si->sn_name); 25698a7d6542SBram Moolenaar } 25708a7d6542SBram Moolenaar break; 25718a7d6542SBram Moolenaar case ISN_LOADS: 25728a7d6542SBram Moolenaar { 2573b283a8a6SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 2574b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 25758a7d6542SBram Moolenaar 25768a7d6542SBram Moolenaar smsg("%4d LOADS s:%s from %s", current, 25775deeb3f1SBram Moolenaar iptr->isn_arg.loadstore.ls_name, si->sn_name); 25788a7d6542SBram Moolenaar } 25798a7d6542SBram Moolenaar break; 25808a7d6542SBram Moolenaar case ISN_LOADG: 25818a7d6542SBram Moolenaar smsg("%4d LOADG g:%s", current, iptr->isn_arg.string); 25828a7d6542SBram Moolenaar break; 2583d3aac291SBram Moolenaar case ISN_LOADB: 2584d3aac291SBram Moolenaar smsg("%4d LOADB b:%s", current, iptr->isn_arg.string); 2585d3aac291SBram Moolenaar break; 2586d3aac291SBram Moolenaar case ISN_LOADW: 2587d3aac291SBram Moolenaar smsg("%4d LOADW w:%s", current, iptr->isn_arg.string); 2588d3aac291SBram Moolenaar break; 2589d3aac291SBram Moolenaar case ISN_LOADT: 2590d3aac291SBram Moolenaar smsg("%4d LOADT t:%s", current, iptr->isn_arg.string); 2591d3aac291SBram Moolenaar break; 25928a7d6542SBram Moolenaar case ISN_LOADOPT: 25938a7d6542SBram Moolenaar smsg("%4d LOADOPT %s", current, iptr->isn_arg.string); 25948a7d6542SBram Moolenaar break; 25958a7d6542SBram Moolenaar case ISN_LOADENV: 25968a7d6542SBram Moolenaar smsg("%4d LOADENV %s", current, iptr->isn_arg.string); 25978a7d6542SBram Moolenaar break; 25988a7d6542SBram Moolenaar case ISN_LOADREG: 25991082772fSBram Moolenaar smsg("%4d LOADREG @%c", current, (int)(iptr->isn_arg.number)); 26008a7d6542SBram Moolenaar break; 26018a7d6542SBram Moolenaar 26028a7d6542SBram Moolenaar case ISN_STORE: 2603b68b346eSBram Moolenaar case ISN_STOREOUTER: 2604b68b346eSBram Moolenaar { 2605b68b346eSBram Moolenaar char *add = iptr->isn_type == ISN_STORE ? "" : "OUTER"; 2606b68b346eSBram Moolenaar 2607170fcfcfSBram Moolenaar if (iptr->isn_arg.number < 0) 2608b68b346eSBram Moolenaar smsg("%4d STORE%s arg[%lld]", current, add, 2609db99f9f2SBram Moolenaar (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE)); 2610170fcfcfSBram Moolenaar else 2611b68b346eSBram Moolenaar smsg("%4d STORE%s $%lld", current, add, 26121082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 2613b68b346eSBram Moolenaar } 26148a7d6542SBram Moolenaar break; 2615b283a8a6SBram Moolenaar case ISN_STOREV: 2616b283a8a6SBram Moolenaar smsg("%4d STOREV v:%s", current, 2617b283a8a6SBram Moolenaar get_vim_var_name(iptr->isn_arg.number)); 2618b283a8a6SBram Moolenaar break; 26198a7d6542SBram Moolenaar case ISN_STOREG: 2620b283a8a6SBram Moolenaar smsg("%4d STOREG %s", current, iptr->isn_arg.string); 2621b283a8a6SBram Moolenaar break; 2622d3aac291SBram Moolenaar case ISN_STOREB: 2623d3aac291SBram Moolenaar smsg("%4d STOREB %s", current, iptr->isn_arg.string); 2624d3aac291SBram Moolenaar break; 2625d3aac291SBram Moolenaar case ISN_STOREW: 2626d3aac291SBram Moolenaar smsg("%4d STOREW %s", current, iptr->isn_arg.string); 2627d3aac291SBram Moolenaar break; 2628d3aac291SBram Moolenaar case ISN_STORET: 2629d3aac291SBram Moolenaar smsg("%4d STORET %s", current, iptr->isn_arg.string); 2630d3aac291SBram Moolenaar break; 2631b283a8a6SBram Moolenaar case ISN_STORES: 2632b283a8a6SBram Moolenaar { 2633b283a8a6SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 2634b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 2635b283a8a6SBram Moolenaar 26360bbf722aSBram Moolenaar smsg("%4d STORES %s in %s", current, 26375deeb3f1SBram Moolenaar iptr->isn_arg.loadstore.ls_name, si->sn_name); 2638b283a8a6SBram Moolenaar } 26398a7d6542SBram Moolenaar break; 26408a7d6542SBram Moolenaar case ISN_STORESCRIPT: 26418a7d6542SBram Moolenaar { 26428a7d6542SBram Moolenaar scriptitem_T *si = 264321b9e977SBram Moolenaar SCRIPT_ITEM(iptr->isn_arg.script.script_sid); 26448a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 26458a7d6542SBram Moolenaar + iptr->isn_arg.script.script_idx; 26468a7d6542SBram Moolenaar 26478a7d6542SBram Moolenaar smsg("%4d STORESCRIPT %s in %s", current, 26488a7d6542SBram Moolenaar sv->sv_name, si->sn_name); 26498a7d6542SBram Moolenaar } 26508a7d6542SBram Moolenaar break; 26518a7d6542SBram Moolenaar case ISN_STOREOPT: 26528a7d6542SBram Moolenaar smsg("%4d STOREOPT &%s", current, 26538a7d6542SBram Moolenaar iptr->isn_arg.storeopt.so_name); 26548a7d6542SBram Moolenaar break; 2655b283a8a6SBram Moolenaar case ISN_STOREENV: 2656b283a8a6SBram Moolenaar smsg("%4d STOREENV $%s", current, iptr->isn_arg.string); 2657b283a8a6SBram Moolenaar break; 2658b283a8a6SBram Moolenaar case ISN_STOREREG: 26591082772fSBram Moolenaar smsg("%4d STOREREG @%c", current, (int)iptr->isn_arg.number); 2660b283a8a6SBram Moolenaar break; 26618a7d6542SBram Moolenaar case ISN_STORENR: 26628a7d6542SBram Moolenaar smsg("%4d STORE %lld in $%d", current, 2663a471eeaeSBram Moolenaar iptr->isn_arg.storenr.stnr_val, 2664a471eeaeSBram Moolenaar iptr->isn_arg.storenr.stnr_idx); 26658a7d6542SBram Moolenaar break; 26668a7d6542SBram Moolenaar 26671cc2a94fSBram Moolenaar case ISN_STORELIST: 26681cc2a94fSBram Moolenaar smsg("%4d STORELIST", current); 26691cc2a94fSBram Moolenaar break; 26701cc2a94fSBram Moolenaar 26711cc2a94fSBram Moolenaar case ISN_STOREDICT: 26721cc2a94fSBram Moolenaar smsg("%4d STOREDICT", current); 26731cc2a94fSBram Moolenaar break; 26741cc2a94fSBram Moolenaar 26758a7d6542SBram Moolenaar // constants 26768a7d6542SBram Moolenaar case ISN_PUSHNR: 26771082772fSBram Moolenaar smsg("%4d PUSHNR %lld", current, 26781082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 26798a7d6542SBram Moolenaar break; 26808a7d6542SBram Moolenaar case ISN_PUSHBOOL: 26818a7d6542SBram Moolenaar case ISN_PUSHSPEC: 26828a7d6542SBram Moolenaar smsg("%4d PUSH %s", current, 26838a7d6542SBram Moolenaar get_var_special_name(iptr->isn_arg.number)); 26848a7d6542SBram Moolenaar break; 26858a7d6542SBram Moolenaar case ISN_PUSHF: 2686a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT 26878a7d6542SBram Moolenaar smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber); 2688a5d5953dSBram Moolenaar #endif 26898a7d6542SBram Moolenaar break; 26908a7d6542SBram Moolenaar case ISN_PUSHS: 26918a7d6542SBram Moolenaar smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string); 26928a7d6542SBram Moolenaar break; 26938a7d6542SBram Moolenaar case ISN_PUSHBLOB: 26948a7d6542SBram Moolenaar { 26958a7d6542SBram Moolenaar char_u *r; 26968a7d6542SBram Moolenaar char_u numbuf[NUMBUFLEN]; 26978a7d6542SBram Moolenaar char_u *tofree; 26988a7d6542SBram Moolenaar 26998a7d6542SBram Moolenaar r = blob2string(iptr->isn_arg.blob, &tofree, numbuf); 2700ff80cb68SBram Moolenaar smsg("%4d PUSHBLOB %s", current, r); 27018a7d6542SBram Moolenaar vim_free(tofree); 27028a7d6542SBram Moolenaar } 27038a7d6542SBram Moolenaar break; 270442a480bfSBram Moolenaar case ISN_PUSHFUNC: 2705087d2e15SBram Moolenaar { 2706087d2e15SBram Moolenaar char *name = (char *)iptr->isn_arg.string; 2707087d2e15SBram Moolenaar 2708087d2e15SBram Moolenaar smsg("%4d PUSHFUNC \"%s\"", current, 2709087d2e15SBram Moolenaar name == NULL ? "[none]" : name); 2710087d2e15SBram Moolenaar } 271142a480bfSBram Moolenaar break; 271242a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 271342a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 271442a480bfSBram Moolenaar { 271542a480bfSBram Moolenaar channel_T *channel = iptr->isn_arg.channel; 271642a480bfSBram Moolenaar 271742a480bfSBram Moolenaar smsg("%4d PUSHCHANNEL %d", current, 271842a480bfSBram Moolenaar channel == NULL ? 0 : channel->ch_id); 271942a480bfSBram Moolenaar } 272042a480bfSBram Moolenaar #endif 272142a480bfSBram Moolenaar break; 272242a480bfSBram Moolenaar case ISN_PUSHJOB: 272342a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 272442a480bfSBram Moolenaar { 272542a480bfSBram Moolenaar typval_T tv; 272642a480bfSBram Moolenaar char_u *name; 272742a480bfSBram Moolenaar 272842a480bfSBram Moolenaar tv.v_type = VAR_JOB; 272942a480bfSBram Moolenaar tv.vval.v_job = iptr->isn_arg.job; 273042a480bfSBram Moolenaar name = tv_get_string(&tv); 2731f51cb4e0SBram Moolenaar smsg("%4d PUSHJOB \"%s\"", current, name); 273242a480bfSBram Moolenaar } 273342a480bfSBram Moolenaar #endif 273442a480bfSBram Moolenaar break; 27358a7d6542SBram Moolenaar case ISN_PUSHEXC: 27368a7d6542SBram Moolenaar smsg("%4d PUSH v:exception", current); 27378a7d6542SBram Moolenaar break; 2738d72c1bf0SBram Moolenaar case ISN_UNLET: 2739d72c1bf0SBram Moolenaar smsg("%4d UNLET%s %s", current, 2740d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_forceit ? "!" : "", 2741d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_name); 2742d72c1bf0SBram Moolenaar break; 27437bdaea6eSBram Moolenaar case ISN_UNLETENV: 27447bdaea6eSBram Moolenaar smsg("%4d UNLETENV%s $%s", current, 27457bdaea6eSBram Moolenaar iptr->isn_arg.unlet.ul_forceit ? "!" : "", 27467bdaea6eSBram Moolenaar iptr->isn_arg.unlet.ul_name); 27477bdaea6eSBram Moolenaar break; 27488a7d6542SBram Moolenaar case ISN_NEWLIST: 27491082772fSBram Moolenaar smsg("%4d NEWLIST size %lld", current, 27501082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 27518a7d6542SBram Moolenaar break; 27528a7d6542SBram Moolenaar case ISN_NEWDICT: 27531082772fSBram Moolenaar smsg("%4d NEWDICT size %lld", current, 27541082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 27558a7d6542SBram Moolenaar break; 27568a7d6542SBram Moolenaar 27578a7d6542SBram Moolenaar // function call 27588a7d6542SBram Moolenaar case ISN_BCALL: 27598a7d6542SBram Moolenaar { 27608a7d6542SBram Moolenaar cbfunc_T *cbfunc = &iptr->isn_arg.bfunc; 27618a7d6542SBram Moolenaar 27628a7d6542SBram Moolenaar smsg("%4d BCALL %s(argc %d)", current, 27638a7d6542SBram Moolenaar internal_func_name(cbfunc->cbf_idx), 27648a7d6542SBram Moolenaar cbfunc->cbf_argcount); 27658a7d6542SBram Moolenaar } 27668a7d6542SBram Moolenaar break; 27678a7d6542SBram Moolenaar case ISN_DCALL: 27688a7d6542SBram Moolenaar { 27698a7d6542SBram Moolenaar cdfunc_T *cdfunc = &iptr->isn_arg.dfunc; 27708a7d6542SBram Moolenaar dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 27718a7d6542SBram Moolenaar + cdfunc->cdf_idx; 27728a7d6542SBram Moolenaar 27738a7d6542SBram Moolenaar smsg("%4d DCALL %s(argc %d)", current, 27748a7d6542SBram Moolenaar df->df_ufunc->uf_name_exp != NULL 27758a7d6542SBram Moolenaar ? df->df_ufunc->uf_name_exp 27768a7d6542SBram Moolenaar : df->df_ufunc->uf_name, cdfunc->cdf_argcount); 27778a7d6542SBram Moolenaar } 27788a7d6542SBram Moolenaar break; 27798a7d6542SBram Moolenaar case ISN_UCALL: 27808a7d6542SBram Moolenaar { 27818a7d6542SBram Moolenaar cufunc_T *cufunc = &iptr->isn_arg.ufunc; 27828a7d6542SBram Moolenaar 27838a7d6542SBram Moolenaar smsg("%4d UCALL %s(argc %d)", current, 27848a7d6542SBram Moolenaar cufunc->cuf_name, cufunc->cuf_argcount); 27858a7d6542SBram Moolenaar } 27868a7d6542SBram Moolenaar break; 27878a7d6542SBram Moolenaar case ISN_PCALL: 27888a7d6542SBram Moolenaar { 27898a7d6542SBram Moolenaar cpfunc_T *cpfunc = &iptr->isn_arg.pfunc; 27908a7d6542SBram Moolenaar 27918a7d6542SBram Moolenaar smsg("%4d PCALL%s (argc %d)", current, 27928a7d6542SBram Moolenaar cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); 27938a7d6542SBram Moolenaar } 27948a7d6542SBram Moolenaar break; 2795bd5da371SBram Moolenaar case ISN_PCALL_END: 2796bd5da371SBram Moolenaar smsg("%4d PCALL end", current); 2797bd5da371SBram Moolenaar break; 27988a7d6542SBram Moolenaar case ISN_RETURN: 27998a7d6542SBram Moolenaar smsg("%4d RETURN", current); 28008a7d6542SBram Moolenaar break; 28018a7d6542SBram Moolenaar case ISN_FUNCREF: 28028a7d6542SBram Moolenaar { 28035adc55cbSBram Moolenaar funcref_T *funcref = &iptr->isn_arg.funcref; 28048a7d6542SBram Moolenaar dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 28055adc55cbSBram Moolenaar + funcref->fr_func; 28068a7d6542SBram Moolenaar 2807bf67ea1aSBram Moolenaar smsg("%4d FUNCREF %s $%d", current, df->df_ufunc->uf_name, 28085adc55cbSBram Moolenaar funcref->fr_var_idx + dfunc->df_varcount); 28098a7d6542SBram Moolenaar } 28108a7d6542SBram Moolenaar break; 28118a7d6542SBram Moolenaar 28128a7d6542SBram Moolenaar case ISN_JUMP: 28138a7d6542SBram Moolenaar { 28148a7d6542SBram Moolenaar char *when = "?"; 28158a7d6542SBram Moolenaar 28168a7d6542SBram Moolenaar switch (iptr->isn_arg.jump.jump_when) 28178a7d6542SBram Moolenaar { 28188a7d6542SBram Moolenaar case JUMP_ALWAYS: 28198a7d6542SBram Moolenaar when = "JUMP"; 28208a7d6542SBram Moolenaar break; 28218a7d6542SBram Moolenaar case JUMP_AND_KEEP_IF_TRUE: 28228a7d6542SBram Moolenaar when = "JUMP_AND_KEEP_IF_TRUE"; 28238a7d6542SBram Moolenaar break; 28248a7d6542SBram Moolenaar case JUMP_IF_FALSE: 28258a7d6542SBram Moolenaar when = "JUMP_IF_FALSE"; 28268a7d6542SBram Moolenaar break; 28278a7d6542SBram Moolenaar case JUMP_AND_KEEP_IF_FALSE: 28288a7d6542SBram Moolenaar when = "JUMP_AND_KEEP_IF_FALSE"; 28298a7d6542SBram Moolenaar break; 28308a7d6542SBram Moolenaar } 28318a677a37SBram Moolenaar smsg("%4d %s -> %d", current, when, 28328a7d6542SBram Moolenaar iptr->isn_arg.jump.jump_where); 28338a7d6542SBram Moolenaar } 28348a7d6542SBram Moolenaar break; 28358a7d6542SBram Moolenaar 28368a7d6542SBram Moolenaar case ISN_FOR: 28378a7d6542SBram Moolenaar { 28388a7d6542SBram Moolenaar forloop_T *forloop = &iptr->isn_arg.forloop; 28398a7d6542SBram Moolenaar 28408a7d6542SBram Moolenaar smsg("%4d FOR $%d -> %d", current, 28418a7d6542SBram Moolenaar forloop->for_idx, forloop->for_end); 28428a7d6542SBram Moolenaar } 28438a7d6542SBram Moolenaar break; 28448a7d6542SBram Moolenaar 28458a7d6542SBram Moolenaar case ISN_TRY: 28468a7d6542SBram Moolenaar { 28478a7d6542SBram Moolenaar try_T *try = &iptr->isn_arg.try; 28488a7d6542SBram Moolenaar 28498a7d6542SBram Moolenaar smsg("%4d TRY catch -> %d, finally -> %d", current, 28508a7d6542SBram Moolenaar try->try_catch, try->try_finally); 28518a7d6542SBram Moolenaar } 28528a7d6542SBram Moolenaar break; 28538a7d6542SBram Moolenaar case ISN_CATCH: 28548a7d6542SBram Moolenaar // TODO 28558a7d6542SBram Moolenaar smsg("%4d CATCH", current); 28568a7d6542SBram Moolenaar break; 28578a7d6542SBram Moolenaar case ISN_ENDTRY: 28588a7d6542SBram Moolenaar smsg("%4d ENDTRY", current); 28598a7d6542SBram Moolenaar break; 28608a7d6542SBram Moolenaar case ISN_THROW: 28618a7d6542SBram Moolenaar smsg("%4d THROW", current); 28628a7d6542SBram Moolenaar break; 28638a7d6542SBram Moolenaar 28648a7d6542SBram Moolenaar // expression operations on number 28658a7d6542SBram Moolenaar case ISN_OPNR: 28668a7d6542SBram Moolenaar case ISN_OPFLOAT: 28678a7d6542SBram Moolenaar case ISN_OPANY: 28688a7d6542SBram Moolenaar { 28698a7d6542SBram Moolenaar char *what; 28708a7d6542SBram Moolenaar char *ins; 28718a7d6542SBram Moolenaar 28728a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 28738a7d6542SBram Moolenaar { 28748a7d6542SBram Moolenaar case EXPR_MULT: what = "*"; break; 28758a7d6542SBram Moolenaar case EXPR_DIV: what = "/"; break; 28768a7d6542SBram Moolenaar case EXPR_REM: what = "%"; break; 28778a7d6542SBram Moolenaar case EXPR_SUB: what = "-"; break; 28788a7d6542SBram Moolenaar case EXPR_ADD: what = "+"; break; 28798a7d6542SBram Moolenaar default: what = "???"; break; 28808a7d6542SBram Moolenaar } 28818a7d6542SBram Moolenaar switch (iptr->isn_type) 28828a7d6542SBram Moolenaar { 28838a7d6542SBram Moolenaar case ISN_OPNR: ins = "OPNR"; break; 28848a7d6542SBram Moolenaar case ISN_OPFLOAT: ins = "OPFLOAT"; break; 28858a7d6542SBram Moolenaar case ISN_OPANY: ins = "OPANY"; break; 28868a7d6542SBram Moolenaar default: ins = "???"; break; 28878a7d6542SBram Moolenaar } 28888a7d6542SBram Moolenaar smsg("%4d %s %s", current, ins, what); 28898a7d6542SBram Moolenaar } 28908a7d6542SBram Moolenaar break; 28918a7d6542SBram Moolenaar 28928a7d6542SBram Moolenaar case ISN_COMPAREBOOL: 28938a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 28948a7d6542SBram Moolenaar case ISN_COMPARENR: 28958a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: 28968a7d6542SBram Moolenaar case ISN_COMPARESTRING: 28978a7d6542SBram Moolenaar case ISN_COMPAREBLOB: 28988a7d6542SBram Moolenaar case ISN_COMPARELIST: 28998a7d6542SBram Moolenaar case ISN_COMPAREDICT: 29008a7d6542SBram Moolenaar case ISN_COMPAREFUNC: 29018a7d6542SBram Moolenaar case ISN_COMPAREANY: 29028a7d6542SBram Moolenaar { 29038a7d6542SBram Moolenaar char *p; 29048a7d6542SBram Moolenaar char buf[10]; 29058a7d6542SBram Moolenaar char *type; 29068a7d6542SBram Moolenaar 29078a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 29088a7d6542SBram Moolenaar { 29098a7d6542SBram Moolenaar case EXPR_EQUAL: p = "=="; break; 29108a7d6542SBram Moolenaar case EXPR_NEQUAL: p = "!="; break; 29118a7d6542SBram Moolenaar case EXPR_GREATER: p = ">"; break; 29128a7d6542SBram Moolenaar case EXPR_GEQUAL: p = ">="; break; 29138a7d6542SBram Moolenaar case EXPR_SMALLER: p = "<"; break; 29148a7d6542SBram Moolenaar case EXPR_SEQUAL: p = "<="; break; 29158a7d6542SBram Moolenaar case EXPR_MATCH: p = "=~"; break; 29168a7d6542SBram Moolenaar case EXPR_IS: p = "is"; break; 29178a7d6542SBram Moolenaar case EXPR_ISNOT: p = "isnot"; break; 29188a7d6542SBram Moolenaar case EXPR_NOMATCH: p = "!~"; break; 29198a7d6542SBram Moolenaar default: p = "???"; break; 29208a7d6542SBram Moolenaar } 29218a7d6542SBram Moolenaar STRCPY(buf, p); 29228a7d6542SBram Moolenaar if (iptr->isn_arg.op.op_ic == TRUE) 29238a7d6542SBram Moolenaar strcat(buf, "?"); 29248a7d6542SBram Moolenaar switch(iptr->isn_type) 29258a7d6542SBram Moolenaar { 29268a7d6542SBram Moolenaar case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break; 29278a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 29288a7d6542SBram Moolenaar type = "COMPARESPECIAL"; break; 29298a7d6542SBram Moolenaar case ISN_COMPARENR: type = "COMPARENR"; break; 29308a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break; 29318a7d6542SBram Moolenaar case ISN_COMPARESTRING: 29328a7d6542SBram Moolenaar type = "COMPARESTRING"; break; 29338a7d6542SBram Moolenaar case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break; 29348a7d6542SBram Moolenaar case ISN_COMPARELIST: type = "COMPARELIST"; break; 29358a7d6542SBram Moolenaar case ISN_COMPAREDICT: type = "COMPAREDICT"; break; 29368a7d6542SBram Moolenaar case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break; 29378a7d6542SBram Moolenaar case ISN_COMPAREANY: type = "COMPAREANY"; break; 29388a7d6542SBram Moolenaar default: type = "???"; break; 29398a7d6542SBram Moolenaar } 29408a7d6542SBram Moolenaar 29418a7d6542SBram Moolenaar smsg("%4d %s %s", current, type, buf); 29428a7d6542SBram Moolenaar } 29438a7d6542SBram Moolenaar break; 29448a7d6542SBram Moolenaar 29458a7d6542SBram Moolenaar case ISN_ADDLIST: smsg("%4d ADDLIST", current); break; 29468a7d6542SBram Moolenaar case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break; 29478a7d6542SBram Moolenaar 29488a7d6542SBram Moolenaar // expression operations 29498a7d6542SBram Moolenaar case ISN_CONCAT: smsg("%4d CONCAT", current); break; 29508a7d6542SBram Moolenaar case ISN_INDEX: smsg("%4d INDEX", current); break; 29519af78769SBram Moolenaar case ISN_SLICE: smsg("%4d SLICE %lld", 29529af78769SBram Moolenaar current, iptr->isn_arg.number); break; 295347a519a9SBram Moolenaar case ISN_GETITEM: smsg("%4d ITEM %lld", 295447a519a9SBram Moolenaar current, iptr->isn_arg.number); break; 29551cc2a94fSBram Moolenaar case ISN_MEMBER: smsg("%4d MEMBER", current); break; 29561cc2a94fSBram Moolenaar case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current, 29578a7d6542SBram Moolenaar iptr->isn_arg.string); break; 29588a7d6542SBram Moolenaar case ISN_NEGATENR: smsg("%4d NEGATENR", current); break; 29598a7d6542SBram Moolenaar 29608a7d6542SBram Moolenaar case ISN_CHECKNR: smsg("%4d CHECKNR", current); break; 29618a7d6542SBram Moolenaar case ISN_CHECKTYPE: smsg("%4d CHECKTYPE %s stack[%d]", current, 29628a7d6542SBram Moolenaar vartype_name(iptr->isn_arg.type.ct_type), 29638a7d6542SBram Moolenaar iptr->isn_arg.type.ct_off); 29648a7d6542SBram Moolenaar break; 29659af78769SBram Moolenaar case ISN_CHECKLEN: smsg("%4d CHECKLEN %s%d", current, 29669af78769SBram Moolenaar iptr->isn_arg.checklen.cl_more_OK ? ">= " : "", 29679af78769SBram Moolenaar iptr->isn_arg.checklen.cl_min_len); 29689af78769SBram Moolenaar break; 29698a7d6542SBram Moolenaar case ISN_2BOOL: if (iptr->isn_arg.number) 29708a7d6542SBram Moolenaar smsg("%4d INVERT (!val)", current); 29718a7d6542SBram Moolenaar else 29728a7d6542SBram Moolenaar smsg("%4d 2BOOL (!!val)", current); 29738a7d6542SBram Moolenaar break; 2974db99f9f2SBram Moolenaar case ISN_2STRING: smsg("%4d 2STRING stack[%lld]", current, 2975db99f9f2SBram Moolenaar (long long)(iptr->isn_arg.number)); 29768a7d6542SBram Moolenaar break; 29778a7d6542SBram Moolenaar 2978389df259SBram Moolenaar case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current, 2979389df259SBram Moolenaar iptr->isn_arg.shuffle.shfl_item, 2980389df259SBram Moolenaar iptr->isn_arg.shuffle.shfl_up); 2981389df259SBram Moolenaar break; 29828a7d6542SBram Moolenaar case ISN_DROP: smsg("%4d DROP", current); break; 29838a7d6542SBram Moolenaar } 29848a7d6542SBram Moolenaar } 29858a7d6542SBram Moolenaar } 29868a7d6542SBram Moolenaar 29878a7d6542SBram Moolenaar /* 29888a7d6542SBram Moolenaar * Return TRUE when "tv" is not falsey: non-zero, non-empty string, non-empty 29898a7d6542SBram Moolenaar * list, etc. Mostly like what JavaScript does, except that empty list and 29908a7d6542SBram Moolenaar * empty dictionary are FALSE. 29918a7d6542SBram Moolenaar */ 29928a7d6542SBram Moolenaar int 29938a7d6542SBram Moolenaar tv2bool(typval_T *tv) 29948a7d6542SBram Moolenaar { 29958a7d6542SBram Moolenaar switch (tv->v_type) 29968a7d6542SBram Moolenaar { 29978a7d6542SBram Moolenaar case VAR_NUMBER: 29988a7d6542SBram Moolenaar return tv->vval.v_number != 0; 29998a7d6542SBram Moolenaar case VAR_FLOAT: 30008a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 30018a7d6542SBram Moolenaar return tv->vval.v_float != 0.0; 30028a7d6542SBram Moolenaar #else 30038a7d6542SBram Moolenaar break; 30048a7d6542SBram Moolenaar #endif 30058a7d6542SBram Moolenaar case VAR_PARTIAL: 30068a7d6542SBram Moolenaar return tv->vval.v_partial != NULL; 30078a7d6542SBram Moolenaar case VAR_FUNC: 30088a7d6542SBram Moolenaar case VAR_STRING: 30098a7d6542SBram Moolenaar return tv->vval.v_string != NULL && *tv->vval.v_string != NUL; 30108a7d6542SBram Moolenaar case VAR_LIST: 30118a7d6542SBram Moolenaar return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0; 30128a7d6542SBram Moolenaar case VAR_DICT: 30138a7d6542SBram Moolenaar return tv->vval.v_dict != NULL 30148a7d6542SBram Moolenaar && tv->vval.v_dict->dv_hashtab.ht_used > 0; 30158a7d6542SBram Moolenaar case VAR_BOOL: 30168a7d6542SBram Moolenaar case VAR_SPECIAL: 30178a7d6542SBram Moolenaar return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE; 30188a7d6542SBram Moolenaar case VAR_JOB: 30198a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL 30208a7d6542SBram Moolenaar return tv->vval.v_job != NULL; 30218a7d6542SBram Moolenaar #else 30228a7d6542SBram Moolenaar break; 30238a7d6542SBram Moolenaar #endif 30248a7d6542SBram Moolenaar case VAR_CHANNEL: 30258a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL 30268a7d6542SBram Moolenaar return tv->vval.v_channel != NULL; 30278a7d6542SBram Moolenaar #else 30288a7d6542SBram Moolenaar break; 30298a7d6542SBram Moolenaar #endif 30308a7d6542SBram Moolenaar case VAR_BLOB: 30318a7d6542SBram Moolenaar return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0; 30328a7d6542SBram Moolenaar case VAR_UNKNOWN: 30334c683750SBram Moolenaar case VAR_ANY: 30348a7d6542SBram Moolenaar case VAR_VOID: 30358a7d6542SBram Moolenaar break; 30368a7d6542SBram Moolenaar } 30378a7d6542SBram Moolenaar return FALSE; 30388a7d6542SBram Moolenaar } 30398a7d6542SBram Moolenaar 30408a7d6542SBram Moolenaar /* 30418a7d6542SBram Moolenaar * If "tv" is a string give an error and return FAIL. 30428a7d6542SBram Moolenaar */ 30438a7d6542SBram Moolenaar int 30448a7d6542SBram Moolenaar check_not_string(typval_T *tv) 30458a7d6542SBram Moolenaar { 30468a7d6542SBram Moolenaar if (tv->v_type == VAR_STRING) 30478a7d6542SBram Moolenaar { 30488a7d6542SBram Moolenaar emsg(_("E1030: Using a String as a Number")); 30498a7d6542SBram Moolenaar clear_tv(tv); 30508a7d6542SBram Moolenaar return FAIL; 30518a7d6542SBram Moolenaar } 30528a7d6542SBram Moolenaar return OK; 30538a7d6542SBram Moolenaar } 30548a7d6542SBram Moolenaar 30558a7d6542SBram Moolenaar 30568a7d6542SBram Moolenaar #endif // FEAT_EVAL 3057