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 */ 57cd45ed03SBram Moolenaar struct ectx_S { 588a7d6542SBram Moolenaar garray_T ec_stack; // stack of typval_T values 59bf67ea1aSBram Moolenaar int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx 608a7d6542SBram Moolenaar 61c8cd2b34SBram Moolenaar garray_T *ec_outer_stack; // stack used for closures 62c8cd2b34SBram Moolenaar int ec_outer_frame; // stack frame in ec_outer_stack 63c8cd2b34SBram Moolenaar 648a7d6542SBram Moolenaar garray_T ec_trystack; // stack of trycmd_T values 658a7d6542SBram Moolenaar int ec_in_catch; // when TRUE in catch or finally block 668a7d6542SBram Moolenaar 678a7d6542SBram Moolenaar int ec_dfunc_idx; // current function index 688a7d6542SBram Moolenaar isn_T *ec_instr; // array with instructions 698a7d6542SBram Moolenaar int ec_iidx; // index in ec_instr: instruction to execute 70148ce7aeSBram Moolenaar 71148ce7aeSBram Moolenaar garray_T ec_funcrefs; // partials that might be a closure 72cd45ed03SBram Moolenaar }; 738a7d6542SBram Moolenaar 748a7d6542SBram Moolenaar // Get pointer to item relative to the bottom of the stack, -1 is the last one. 7511107babSBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx)) 768a7d6542SBram Moolenaar 77418f1df5SBram Moolenaar void 78418f1df5SBram Moolenaar to_string_error(vartype_T vartype) 79418f1df5SBram Moolenaar { 80451c2e35SBram Moolenaar semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype)); 81418f1df5SBram Moolenaar } 82418f1df5SBram Moolenaar 838a7d6542SBram Moolenaar /* 84170fcfcfSBram Moolenaar * Return the number of arguments, including optional arguments and any vararg. 858a7d6542SBram Moolenaar */ 868a7d6542SBram Moolenaar static int 878a7d6542SBram Moolenaar ufunc_argcount(ufunc_T *ufunc) 888a7d6542SBram Moolenaar { 898a7d6542SBram Moolenaar return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0); 908a7d6542SBram Moolenaar } 918a7d6542SBram Moolenaar 928a7d6542SBram Moolenaar /* 93170fcfcfSBram Moolenaar * Set the instruction index, depending on omitted arguments, where the default 94170fcfcfSBram Moolenaar * values are to be computed. If all optional arguments are present, start 95170fcfcfSBram Moolenaar * with the function body. 96170fcfcfSBram Moolenaar * The expression evaluation is at the start of the instructions: 97170fcfcfSBram Moolenaar * 0 -> EVAL default1 98170fcfcfSBram Moolenaar * STORE arg[-2] 99170fcfcfSBram Moolenaar * 1 -> EVAL default2 100170fcfcfSBram Moolenaar * STORE arg[-1] 101170fcfcfSBram Moolenaar * 2 -> function body 102170fcfcfSBram Moolenaar */ 103170fcfcfSBram Moolenaar static void 104170fcfcfSBram Moolenaar init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx) 105170fcfcfSBram Moolenaar { 106170fcfcfSBram Moolenaar if (ufunc->uf_def_args.ga_len == 0) 107170fcfcfSBram Moolenaar ectx->ec_iidx = 0; 108170fcfcfSBram Moolenaar else 109170fcfcfSBram Moolenaar { 110170fcfcfSBram Moolenaar int defcount = ufunc->uf_args.ga_len - argcount; 111170fcfcfSBram Moolenaar 112170fcfcfSBram Moolenaar // If there is a varargs argument defcount can be negative, no defaults 113170fcfcfSBram Moolenaar // to evaluate then. 114170fcfcfSBram Moolenaar if (defcount < 0) 115170fcfcfSBram Moolenaar defcount = 0; 116170fcfcfSBram Moolenaar ectx->ec_iidx = ufunc->uf_def_arg_idx[ 117170fcfcfSBram Moolenaar ufunc->uf_def_args.ga_len - defcount]; 118170fcfcfSBram Moolenaar } 119170fcfcfSBram Moolenaar } 120170fcfcfSBram Moolenaar 121170fcfcfSBram Moolenaar /* 122fe270817SBram Moolenaar * Create a new list from "count" items at the bottom of the stack. 123fe270817SBram Moolenaar * When "count" is zero an empty list is added to the stack. 124fe270817SBram Moolenaar */ 125fe270817SBram Moolenaar static int 126fe270817SBram Moolenaar exe_newlist(int count, ectx_T *ectx) 127fe270817SBram Moolenaar { 128fe270817SBram Moolenaar list_T *list = list_alloc_with_items(count); 129fe270817SBram Moolenaar int idx; 130fe270817SBram Moolenaar typval_T *tv; 131fe270817SBram Moolenaar 132fe270817SBram Moolenaar if (list == NULL) 133fe270817SBram Moolenaar return FAIL; 134fe270817SBram Moolenaar for (idx = 0; idx < count; ++idx) 135fe270817SBram Moolenaar list_set_item(list, idx, STACK_TV_BOT(idx - count)); 136fe270817SBram Moolenaar 137fe270817SBram Moolenaar if (count > 0) 138fe270817SBram Moolenaar ectx->ec_stack.ga_len -= count - 1; 139270d0388SBram Moolenaar else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) 140fe270817SBram Moolenaar return FAIL; 141fe270817SBram Moolenaar else 142fe270817SBram Moolenaar ++ectx->ec_stack.ga_len; 143fe270817SBram Moolenaar tv = STACK_TV_BOT(-1); 144fe270817SBram Moolenaar tv->v_type = VAR_LIST; 145fe270817SBram Moolenaar tv->vval.v_list = list; 146fe270817SBram Moolenaar ++list->lv_refcount; 147fe270817SBram Moolenaar return OK; 148fe270817SBram Moolenaar } 149fe270817SBram Moolenaar 150fe270817SBram Moolenaar /* 1518a7d6542SBram Moolenaar * Call compiled function "cdf_idx" from compiled code. 1528a7d6542SBram Moolenaar * 1538a7d6542SBram Moolenaar * Stack has: 1548a7d6542SBram Moolenaar * - current arguments (already there) 1558a7d6542SBram Moolenaar * - omitted optional argument (default values) added here 1568a7d6542SBram Moolenaar * - stack frame: 1578a7d6542SBram Moolenaar * - pointer to calling function 1588a7d6542SBram Moolenaar * - Index of next instruction in calling function 1598a7d6542SBram Moolenaar * - previous frame pointer 1608a7d6542SBram Moolenaar * - reserved space for local variables 1618a7d6542SBram Moolenaar */ 1628a7d6542SBram Moolenaar static int 1631378fbc4SBram Moolenaar call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx) 1648a7d6542SBram Moolenaar { 1651378fbc4SBram Moolenaar int argcount = argcount_arg; 1668a7d6542SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx; 1678a7d6542SBram Moolenaar ufunc_T *ufunc = dfunc->df_ufunc; 1681378fbc4SBram Moolenaar int arg_to_add; 1691378fbc4SBram Moolenaar int vararg_count = 0; 170148ce7aeSBram Moolenaar int varcount; 1718a7d6542SBram Moolenaar int idx; 172c620c055SBram Moolenaar estack_T *entry; 1738a7d6542SBram Moolenaar 1748a7d6542SBram Moolenaar if (dfunc->df_deleted) 1758a7d6542SBram Moolenaar { 176cd45ed03SBram Moolenaar // don't use ufunc->uf_name, it may have been freed 177cd45ed03SBram Moolenaar emsg_funcname(e_func_deleted, 178cd45ed03SBram Moolenaar dfunc->df_name == NULL ? (char_u *)"unknown" : dfunc->df_name); 1798a7d6542SBram Moolenaar return FAIL; 1808a7d6542SBram Moolenaar } 1818a7d6542SBram Moolenaar 1821378fbc4SBram Moolenaar if (ufunc->uf_va_name != NULL) 1831378fbc4SBram Moolenaar { 184fe270817SBram Moolenaar // Need to make a list out of the vararg arguments. 1851378fbc4SBram Moolenaar // Stack at time of call with 2 varargs: 1861378fbc4SBram Moolenaar // normal_arg 1871378fbc4SBram Moolenaar // optional_arg 1881378fbc4SBram Moolenaar // vararg_1 1891378fbc4SBram Moolenaar // vararg_2 190fe270817SBram Moolenaar // After creating the list: 1911378fbc4SBram Moolenaar // normal_arg 1921378fbc4SBram Moolenaar // optional_arg 193fe270817SBram Moolenaar // vararg-list 194fe270817SBram Moolenaar // With missing optional arguments we get: 195fe270817SBram Moolenaar // normal_arg 196fe270817SBram Moolenaar // After creating the list 197fe270817SBram Moolenaar // normal_arg 198fe270817SBram Moolenaar // (space for optional_arg) 199fe270817SBram Moolenaar // vararg-list 2001378fbc4SBram Moolenaar vararg_count = argcount - ufunc->uf_args.ga_len; 2011378fbc4SBram Moolenaar if (vararg_count < 0) 2021378fbc4SBram Moolenaar vararg_count = 0; 2031378fbc4SBram Moolenaar else 2041378fbc4SBram Moolenaar argcount -= vararg_count; 205fe270817SBram Moolenaar if (exe_newlist(vararg_count, ectx) == FAIL) 2061378fbc4SBram Moolenaar return FAIL; 207fe270817SBram Moolenaar 208fe270817SBram Moolenaar vararg_count = 1; 2091378fbc4SBram Moolenaar } 2101378fbc4SBram Moolenaar 211fe270817SBram Moolenaar arg_to_add = ufunc->uf_args.ga_len - argcount; 2121378fbc4SBram Moolenaar if (arg_to_add < 0) 2131378fbc4SBram Moolenaar { 21479e8db9aSBram Moolenaar if (arg_to_add == -1) 215451c2e35SBram Moolenaar emsg(_(e_one_argument_too_many)); 21679e8db9aSBram Moolenaar else 217451c2e35SBram Moolenaar semsg(_(e_nr_arguments_too_many), -arg_to_add); 2181378fbc4SBram Moolenaar return FAIL; 2191378fbc4SBram Moolenaar } 220148ce7aeSBram Moolenaar 221148ce7aeSBram Moolenaar // Reserve space for: 222148ce7aeSBram Moolenaar // - missing arguments 223148ce7aeSBram Moolenaar // - stack frame 224148ce7aeSBram Moolenaar // - local variables 225148ce7aeSBram Moolenaar // - if needed: a counter for number of closures created in 226148ce7aeSBram Moolenaar // ectx->ec_funcrefs. 227148ce7aeSBram Moolenaar varcount = dfunc->df_varcount + dfunc->df_has_closure; 228148ce7aeSBram Moolenaar if (ga_grow(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE + varcount) 229148ce7aeSBram Moolenaar == FAIL) 2308a7d6542SBram Moolenaar return FAIL; 2318a7d6542SBram Moolenaar 2320ba48e8cSBram Moolenaar // If depth of calling is getting too high, don't execute the function. 2330ba48e8cSBram Moolenaar if (funcdepth_increment() == FAIL) 2340ba48e8cSBram Moolenaar return FAIL; 2350ba48e8cSBram Moolenaar 236fe270817SBram Moolenaar // Move the vararg-list to below the missing optional arguments. 237fe270817SBram Moolenaar if (vararg_count > 0 && arg_to_add > 0) 238fe270817SBram Moolenaar *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1); 239170fcfcfSBram Moolenaar 240170fcfcfSBram Moolenaar // Reserve space for omitted optional arguments, filled in soon. 2411378fbc4SBram Moolenaar for (idx = 0; idx < arg_to_add; ++idx) 242fe270817SBram Moolenaar STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN; 2431378fbc4SBram Moolenaar ectx->ec_stack.ga_len += arg_to_add; 2448a7d6542SBram Moolenaar 2458a7d6542SBram Moolenaar // Store current execution state in stack frame for ISN_RETURN. 2468a7d6542SBram Moolenaar STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx; 2478a7d6542SBram Moolenaar STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx; 2485366e1aeSBram Moolenaar STACK_TV_BOT(2)->vval.v_string = (void *)ectx->ec_outer_stack; 2495366e1aeSBram Moolenaar STACK_TV_BOT(3)->vval.v_number = ectx->ec_outer_frame; 2505366e1aeSBram Moolenaar STACK_TV_BOT(4)->vval.v_number = ectx->ec_frame_idx; 251bf67ea1aSBram Moolenaar ectx->ec_frame_idx = ectx->ec_stack.ga_len; 2528a7d6542SBram Moolenaar 2538a7d6542SBram Moolenaar // Initialize local variables 254148ce7aeSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 2558a7d6542SBram Moolenaar STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN; 256148ce7aeSBram Moolenaar if (dfunc->df_has_closure) 257148ce7aeSBram Moolenaar { 258148ce7aeSBram Moolenaar typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + dfunc->df_varcount); 259148ce7aeSBram Moolenaar 260148ce7aeSBram Moolenaar tv->v_type = VAR_NUMBER; 261148ce7aeSBram Moolenaar tv->vval.v_number = 0; 262148ce7aeSBram Moolenaar } 263148ce7aeSBram Moolenaar ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount; 2648a7d6542SBram Moolenaar 265cd45ed03SBram Moolenaar if (ufunc->uf_partial != NULL) 266cd45ed03SBram Moolenaar { 267cd45ed03SBram Moolenaar ectx->ec_outer_stack = ufunc->uf_partial->pt_ectx_stack; 268cd45ed03SBram Moolenaar ectx->ec_outer_frame = ufunc->uf_partial->pt_ectx_frame; 269cd45ed03SBram Moolenaar } 270cd45ed03SBram Moolenaar 2718a7d6542SBram Moolenaar // Set execution state to the start of the called function. 2728a7d6542SBram Moolenaar ectx->ec_dfunc_idx = cdf_idx; 2738a7d6542SBram Moolenaar ectx->ec_instr = dfunc->df_instr; 274c620c055SBram Moolenaar entry = estack_push_ufunc(dfunc->df_ufunc, 1); 275c620c055SBram Moolenaar if (entry != NULL) 276c620c055SBram Moolenaar { 277c620c055SBram Moolenaar // Set the script context to the script where the function was defined. 278c620c055SBram Moolenaar // TODO: save more than the SID? 279c620c055SBram Moolenaar entry->es_save_sid = current_sctx.sc_sid; 280c620c055SBram Moolenaar current_sctx.sc_sid = ufunc->uf_script_ctx.sc_sid; 281c620c055SBram Moolenaar } 282170fcfcfSBram Moolenaar 283170fcfcfSBram Moolenaar // Decide where to start execution, handles optional arguments. 284170fcfcfSBram Moolenaar init_instr_idx(ufunc, argcount, ectx); 2858a7d6542SBram Moolenaar 2868a7d6542SBram Moolenaar return OK; 2878a7d6542SBram Moolenaar } 2888a7d6542SBram Moolenaar 2898a7d6542SBram Moolenaar // Get pointer to item in the stack. 2908a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx) 2918a7d6542SBram Moolenaar 2928a7d6542SBram Moolenaar /* 293bf67ea1aSBram Moolenaar * Used when returning from a function: Check if any closure is still 294bf67ea1aSBram Moolenaar * referenced. If so then move the arguments and variables to a separate piece 295bf67ea1aSBram Moolenaar * of stack to be used when the closure is called. 296bf67ea1aSBram Moolenaar * When "free_arguments" is TRUE the arguments are to be freed. 297bf67ea1aSBram Moolenaar * Returns FAIL when out of memory. 298bf67ea1aSBram Moolenaar */ 299bf67ea1aSBram Moolenaar static int 300bf67ea1aSBram Moolenaar handle_closure_in_use(ectx_T *ectx, int free_arguments) 301bf67ea1aSBram Moolenaar { 302bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 303bf67ea1aSBram Moolenaar + ectx->ec_dfunc_idx; 304fdeab65dSBram Moolenaar int argcount; 305fdeab65dSBram Moolenaar int top; 306bf67ea1aSBram Moolenaar int idx; 307bf67ea1aSBram Moolenaar typval_T *tv; 308bf67ea1aSBram Moolenaar int closure_in_use = FALSE; 309148ce7aeSBram Moolenaar garray_T *gap = &ectx->ec_funcrefs; 310148ce7aeSBram Moolenaar varnumber_T closure_count; 311bf67ea1aSBram Moolenaar 312fdeab65dSBram Moolenaar if (dfunc->df_ufunc == NULL) 313148ce7aeSBram Moolenaar return OK; // function was freed 314148ce7aeSBram Moolenaar if (dfunc->df_has_closure == 0) 315148ce7aeSBram Moolenaar return OK; // no closures 316148ce7aeSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + dfunc->df_varcount); 317148ce7aeSBram Moolenaar closure_count = tv->vval.v_number; 318148ce7aeSBram Moolenaar if (closure_count == 0) 319148ce7aeSBram Moolenaar return OK; // no funcrefs created 320148ce7aeSBram Moolenaar 321fdeab65dSBram Moolenaar argcount = ufunc_argcount(dfunc->df_ufunc); 322fdeab65dSBram Moolenaar top = ectx->ec_frame_idx - argcount; 323fdeab65dSBram Moolenaar 324bf67ea1aSBram Moolenaar // Check if any created closure is still in use. 325148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 326bf67ea1aSBram Moolenaar { 327c70bdab0SBram Moolenaar partial_T *pt; 328c70bdab0SBram Moolenaar int off = gap->ga_len - closure_count + idx; 329148ce7aeSBram Moolenaar 330c70bdab0SBram Moolenaar if (off < 0) 331c70bdab0SBram Moolenaar continue; // count is off or already done 332c70bdab0SBram Moolenaar pt = ((partial_T **)gap->ga_data)[off]; 333148ce7aeSBram Moolenaar if (pt->pt_refcount > 1) 334221fcc74SBram Moolenaar { 335148ce7aeSBram Moolenaar int refcount = pt->pt_refcount; 336221fcc74SBram Moolenaar int i; 337221fcc74SBram Moolenaar 338f821ddaaSBram Moolenaar // A Reference in a local variables doesn't count, it gets 339221fcc74SBram Moolenaar // unreferenced on return. 340221fcc74SBram Moolenaar for (i = 0; i < dfunc->df_varcount; ++i) 341221fcc74SBram Moolenaar { 342221fcc74SBram Moolenaar typval_T *stv = STACK_TV(ectx->ec_frame_idx 343221fcc74SBram Moolenaar + STACK_FRAME_SIZE + i); 344148ce7aeSBram Moolenaar if (stv->v_type == VAR_PARTIAL && pt == stv->vval.v_partial) 345221fcc74SBram Moolenaar --refcount; 346221fcc74SBram Moolenaar } 347221fcc74SBram Moolenaar if (refcount > 1) 348f7779c63SBram Moolenaar { 349bf67ea1aSBram Moolenaar closure_in_use = TRUE; 350f7779c63SBram Moolenaar break; 351f7779c63SBram Moolenaar } 352bf67ea1aSBram Moolenaar } 353221fcc74SBram Moolenaar } 354bf67ea1aSBram Moolenaar 355bf67ea1aSBram Moolenaar if (closure_in_use) 356bf67ea1aSBram Moolenaar { 357bf67ea1aSBram Moolenaar funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T); 358bf67ea1aSBram Moolenaar typval_T *stack; 359bf67ea1aSBram Moolenaar 360bf67ea1aSBram Moolenaar // A closure is using the arguments and/or local variables. 361bf67ea1aSBram Moolenaar // Move them to the called function. 362bf67ea1aSBram Moolenaar if (funcstack == NULL) 363bf67ea1aSBram Moolenaar return FAIL; 36485d5e2b7SBram Moolenaar funcstack->fs_var_offset = argcount + STACK_FRAME_SIZE; 36585d5e2b7SBram Moolenaar funcstack->fs_ga.ga_len = funcstack->fs_var_offset + dfunc->df_varcount; 366bf67ea1aSBram Moolenaar stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len); 367bf67ea1aSBram Moolenaar funcstack->fs_ga.ga_data = stack; 368bf67ea1aSBram Moolenaar if (stack == NULL) 369bf67ea1aSBram Moolenaar { 370bf67ea1aSBram Moolenaar vim_free(funcstack); 371bf67ea1aSBram Moolenaar return FAIL; 372bf67ea1aSBram Moolenaar } 373bf67ea1aSBram Moolenaar 374bf67ea1aSBram Moolenaar // Move or copy the arguments. 375bf67ea1aSBram Moolenaar for (idx = 0; idx < argcount; ++idx) 376bf67ea1aSBram Moolenaar { 377bf67ea1aSBram Moolenaar tv = STACK_TV(top + idx); 378bf67ea1aSBram Moolenaar if (free_arguments) 379bf67ea1aSBram Moolenaar { 380bf67ea1aSBram Moolenaar *(stack + idx) = *tv; 381bf67ea1aSBram Moolenaar tv->v_type = VAR_UNKNOWN; 382bf67ea1aSBram Moolenaar } 383bf67ea1aSBram Moolenaar else 384bf67ea1aSBram Moolenaar copy_tv(tv, stack + idx); 385bf67ea1aSBram Moolenaar } 386bf67ea1aSBram Moolenaar // Move the local variables. 387bf67ea1aSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 388bf67ea1aSBram Moolenaar { 389bf67ea1aSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx); 390f821ddaaSBram Moolenaar 39185d5e2b7SBram Moolenaar // A partial created for a local function, that is also used as a 39285d5e2b7SBram Moolenaar // local variable, has a reference count for the variable, thus 39385d5e2b7SBram Moolenaar // will never go down to zero. When all these refcounts are one 39485d5e2b7SBram Moolenaar // then the funcstack is unused. We need to count how many we have 39585d5e2b7SBram Moolenaar // so we need when to check. 396f821ddaaSBram Moolenaar if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) 397f821ddaaSBram Moolenaar { 398f821ddaaSBram Moolenaar int i; 399f821ddaaSBram Moolenaar 400148ce7aeSBram Moolenaar for (i = 0; i < closure_count; ++i) 40185d5e2b7SBram Moolenaar if (tv->vval.v_partial == ((partial_T **)gap->ga_data)[ 40285d5e2b7SBram Moolenaar gap->ga_len - closure_count + i]) 40385d5e2b7SBram Moolenaar ++funcstack->fs_min_refcount; 404f821ddaaSBram Moolenaar } 405f821ddaaSBram Moolenaar 40685d5e2b7SBram Moolenaar *(stack + funcstack->fs_var_offset + idx) = *tv; 407bf67ea1aSBram Moolenaar tv->v_type = VAR_UNKNOWN; 408bf67ea1aSBram Moolenaar } 409bf67ea1aSBram Moolenaar 410148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 411bf67ea1aSBram Moolenaar { 412148ce7aeSBram Moolenaar partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len 413148ce7aeSBram Moolenaar - closure_count + idx]; 414148ce7aeSBram Moolenaar if (pt->pt_refcount > 1) 415f7779c63SBram Moolenaar { 416bf67ea1aSBram Moolenaar ++funcstack->fs_refcount; 417148ce7aeSBram Moolenaar pt->pt_funcstack = funcstack; 418148ce7aeSBram Moolenaar pt->pt_ectx_stack = &funcstack->fs_ga; 419148ce7aeSBram Moolenaar pt->pt_ectx_frame = ectx->ec_frame_idx - top; 420f7779c63SBram Moolenaar } 421bf67ea1aSBram Moolenaar } 422bf67ea1aSBram Moolenaar } 423148ce7aeSBram Moolenaar 424148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 425148ce7aeSBram Moolenaar partial_unref(((partial_T **)gap->ga_data)[gap->ga_len 426148ce7aeSBram Moolenaar - closure_count + idx]); 427148ce7aeSBram Moolenaar gap->ga_len -= closure_count; 428148ce7aeSBram Moolenaar if (gap->ga_len == 0) 429148ce7aeSBram Moolenaar ga_clear(gap); 430bf67ea1aSBram Moolenaar 431bf67ea1aSBram Moolenaar return OK; 432bf67ea1aSBram Moolenaar } 433bf67ea1aSBram Moolenaar 434bf67ea1aSBram Moolenaar /* 43585d5e2b7SBram Moolenaar * Called when a partial is freed or its reference count goes down to one. The 43685d5e2b7SBram Moolenaar * funcstack may be the only reference to the partials in the local variables. 43785d5e2b7SBram Moolenaar * Go over all of them, the funcref and can be freed if all partials 43885d5e2b7SBram Moolenaar * referencing the funcstack have a reference count of one. 43985d5e2b7SBram Moolenaar */ 44085d5e2b7SBram Moolenaar void 44185d5e2b7SBram Moolenaar funcstack_check_refcount(funcstack_T *funcstack) 44285d5e2b7SBram Moolenaar { 44385d5e2b7SBram Moolenaar int i; 44485d5e2b7SBram Moolenaar garray_T *gap = &funcstack->fs_ga; 44585d5e2b7SBram Moolenaar int done = 0; 44685d5e2b7SBram Moolenaar 44785d5e2b7SBram Moolenaar if (funcstack->fs_refcount > funcstack->fs_min_refcount) 44885d5e2b7SBram Moolenaar return; 44985d5e2b7SBram Moolenaar for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i) 45085d5e2b7SBram Moolenaar { 45185d5e2b7SBram Moolenaar typval_T *tv = ((typval_T *)gap->ga_data) + i; 45285d5e2b7SBram Moolenaar 45385d5e2b7SBram Moolenaar if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL 45485d5e2b7SBram Moolenaar && tv->vval.v_partial->pt_funcstack == funcstack 45585d5e2b7SBram Moolenaar && tv->vval.v_partial->pt_refcount == 1) 45685d5e2b7SBram Moolenaar ++done; 45785d5e2b7SBram Moolenaar } 45885d5e2b7SBram Moolenaar if (done == funcstack->fs_min_refcount) 45985d5e2b7SBram Moolenaar { 46085d5e2b7SBram Moolenaar typval_T *stack = gap->ga_data; 46185d5e2b7SBram Moolenaar 46285d5e2b7SBram Moolenaar // All partials referencing the funcstack have a reference count of 46385d5e2b7SBram Moolenaar // one, thus the funcstack is no longer of use. 46485d5e2b7SBram Moolenaar for (i = 0; i < gap->ga_len; ++i) 46585d5e2b7SBram Moolenaar clear_tv(stack + i); 46685d5e2b7SBram Moolenaar vim_free(stack); 46785d5e2b7SBram Moolenaar vim_free(funcstack); 46885d5e2b7SBram Moolenaar } 46985d5e2b7SBram Moolenaar } 47085d5e2b7SBram Moolenaar 47185d5e2b7SBram Moolenaar /* 4728a7d6542SBram Moolenaar * Return from the current function. 4738a7d6542SBram Moolenaar */ 474bf67ea1aSBram Moolenaar static int 4758a7d6542SBram Moolenaar func_return(ectx_T *ectx) 4768a7d6542SBram Moolenaar { 4778a7d6542SBram Moolenaar int idx; 47834c54eb6SBram Moolenaar int ret_idx; 479bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 480bf67ea1aSBram Moolenaar + ectx->ec_dfunc_idx; 481bf67ea1aSBram Moolenaar int argcount = ufunc_argcount(dfunc->df_ufunc); 482bf67ea1aSBram Moolenaar int top = ectx->ec_frame_idx - argcount; 483c620c055SBram Moolenaar estack_T *entry; 4848a7d6542SBram Moolenaar 4858a7d6542SBram Moolenaar // execution context goes one level up 486c620c055SBram Moolenaar entry = estack_pop(); 487c620c055SBram Moolenaar if (entry != NULL) 488c620c055SBram Moolenaar current_sctx.sc_sid = entry->es_save_sid; 4898a7d6542SBram Moolenaar 490bf67ea1aSBram Moolenaar if (handle_closure_in_use(ectx, TRUE) == FAIL) 491bf67ea1aSBram Moolenaar return FAIL; 492bf67ea1aSBram Moolenaar 493bf67ea1aSBram Moolenaar // Clear the arguments. 494bf67ea1aSBram Moolenaar for (idx = top; idx < ectx->ec_frame_idx; ++idx) 495bf67ea1aSBram Moolenaar clear_tv(STACK_TV(idx)); 496bf67ea1aSBram Moolenaar 497bf67ea1aSBram Moolenaar // Clear local variables and temp values, but not the return value. 498bf67ea1aSBram Moolenaar for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE; 4998a7d6542SBram Moolenaar idx < ectx->ec_stack.ga_len - 1; ++idx) 5008a7d6542SBram Moolenaar clear_tv(STACK_TV(idx)); 501170fcfcfSBram Moolenaar 50234c54eb6SBram Moolenaar // The return value should be on top of the stack. However, when aborting 50334c54eb6SBram Moolenaar // it may not be there and ec_frame_idx is the top of the stack. 50434c54eb6SBram Moolenaar ret_idx = ectx->ec_stack.ga_len - 1; 50534c54eb6SBram Moolenaar if (ret_idx == ectx->ec_frame_idx + 4) 50634c54eb6SBram Moolenaar ret_idx = 0; 50734c54eb6SBram Moolenaar 508170fcfcfSBram Moolenaar // Restore the previous frame. 509bf67ea1aSBram Moolenaar ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame_idx)->vval.v_number; 510bf67ea1aSBram Moolenaar ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx + 1)->vval.v_number; 5115366e1aeSBram Moolenaar ectx->ec_outer_stack = 5125366e1aeSBram Moolenaar (void *)STACK_TV(ectx->ec_frame_idx + 2)->vval.v_string; 5135366e1aeSBram Moolenaar ectx->ec_outer_frame = STACK_TV(ectx->ec_frame_idx + 3)->vval.v_number; 5145366e1aeSBram Moolenaar // restoring ec_frame_idx must be last 5155366e1aeSBram Moolenaar ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx + 4)->vval.v_number; 5168a7d6542SBram Moolenaar dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; 5178a7d6542SBram Moolenaar ectx->ec_instr = dfunc->df_instr; 518170fcfcfSBram Moolenaar 51934c54eb6SBram Moolenaar if (ret_idx > 0) 52034c54eb6SBram Moolenaar { 52134c54eb6SBram Moolenaar // Reset the stack to the position before the call, with a spot for the 52234c54eb6SBram Moolenaar // return value, moved there from above the frame. 523170fcfcfSBram Moolenaar ectx->ec_stack.ga_len = top + 1; 52434c54eb6SBram Moolenaar *STACK_TV_BOT(-1) = *STACK_TV(ret_idx); 52534c54eb6SBram Moolenaar } 52634c54eb6SBram Moolenaar else 52734c54eb6SBram Moolenaar // Reset the stack to the position before the call. 52834c54eb6SBram Moolenaar ectx->ec_stack.ga_len = top; 529bf67ea1aSBram Moolenaar 5300ba48e8cSBram Moolenaar funcdepth_decrement(); 531bf67ea1aSBram Moolenaar return OK; 5328a7d6542SBram Moolenaar } 5338a7d6542SBram Moolenaar 5348a7d6542SBram Moolenaar #undef STACK_TV 5358a7d6542SBram Moolenaar 5368a7d6542SBram Moolenaar /* 5378a7d6542SBram Moolenaar * Prepare arguments and rettv for calling a builtin or user function. 5388a7d6542SBram Moolenaar */ 5398a7d6542SBram Moolenaar static int 5408a7d6542SBram Moolenaar call_prepare(int argcount, typval_T *argvars, ectx_T *ectx) 5418a7d6542SBram Moolenaar { 5428a7d6542SBram Moolenaar int idx; 5438a7d6542SBram Moolenaar typval_T *tv; 5448a7d6542SBram Moolenaar 5458a7d6542SBram Moolenaar // Move arguments from bottom of the stack to argvars[] and add terminator. 5468a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 5478a7d6542SBram Moolenaar argvars[idx] = *STACK_TV_BOT(idx - argcount); 5488a7d6542SBram Moolenaar argvars[argcount].v_type = VAR_UNKNOWN; 5498a7d6542SBram Moolenaar 5508a7d6542SBram Moolenaar // Result replaces the arguments on the stack. 5518a7d6542SBram Moolenaar if (argcount > 0) 5528a7d6542SBram Moolenaar ectx->ec_stack.ga_len -= argcount - 1; 553270d0388SBram Moolenaar else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) 5548a7d6542SBram Moolenaar return FAIL; 5558a7d6542SBram Moolenaar else 5568a7d6542SBram Moolenaar ++ectx->ec_stack.ga_len; 5578a7d6542SBram Moolenaar 5588a7d6542SBram Moolenaar // Default return value is zero. 5598a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 5608a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 5618a7d6542SBram Moolenaar tv->vval.v_number = 0; 5628a7d6542SBram Moolenaar 5638a7d6542SBram Moolenaar return OK; 5648a7d6542SBram Moolenaar } 5658a7d6542SBram Moolenaar 56608f7a41bSBram Moolenaar // Ugly global to avoid passing the execution context around through many 56708f7a41bSBram Moolenaar // layers. 56808f7a41bSBram Moolenaar static ectx_T *current_ectx = NULL; 56908f7a41bSBram Moolenaar 5708a7d6542SBram Moolenaar /* 5718a7d6542SBram Moolenaar * Call a builtin function by index. 5728a7d6542SBram Moolenaar */ 5738a7d6542SBram Moolenaar static int 5748a7d6542SBram Moolenaar call_bfunc(int func_idx, int argcount, ectx_T *ectx) 5758a7d6542SBram Moolenaar { 5768a7d6542SBram Moolenaar typval_T argvars[MAX_FUNC_ARGS]; 5778a7d6542SBram Moolenaar int idx; 578171fb923SBram Moolenaar int did_emsg_before = did_emsg; 57908f7a41bSBram Moolenaar ectx_T *prev_ectx = current_ectx; 5808a7d6542SBram Moolenaar 5818a7d6542SBram Moolenaar if (call_prepare(argcount, argvars, ectx) == FAIL) 5828a7d6542SBram Moolenaar return FAIL; 5838a7d6542SBram Moolenaar 58408f7a41bSBram Moolenaar // Call the builtin function. Set "current_ectx" so that when it 58508f7a41bSBram Moolenaar // recursively invokes call_def_function() a closure context can be set. 58608f7a41bSBram Moolenaar current_ectx = ectx; 5878a7d6542SBram Moolenaar call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1)); 58808f7a41bSBram Moolenaar current_ectx = prev_ectx; 5898a7d6542SBram Moolenaar 5908a7d6542SBram Moolenaar // Clear the arguments. 5918a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 5928a7d6542SBram Moolenaar clear_tv(&argvars[idx]); 593015f4267SBram Moolenaar 59457f799e6SBram Moolenaar if (did_emsg > did_emsg_before) 595015f4267SBram Moolenaar return FAIL; 5968a7d6542SBram Moolenaar return OK; 5978a7d6542SBram Moolenaar } 5988a7d6542SBram Moolenaar 5998a7d6542SBram Moolenaar /* 6008a7d6542SBram Moolenaar * Execute a user defined function. 6017eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 6028a7d6542SBram Moolenaar */ 6038a7d6542SBram Moolenaar static int 6047eeefd4aSBram Moolenaar call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr) 6058a7d6542SBram Moolenaar { 6068a7d6542SBram Moolenaar typval_T argvars[MAX_FUNC_ARGS]; 6078a7d6542SBram Moolenaar funcexe_T funcexe; 6088a7d6542SBram Moolenaar int error; 6098a7d6542SBram Moolenaar int idx; 61028ee892aSBram Moolenaar int did_emsg_before = did_emsg; 6118a7d6542SBram Moolenaar 6120cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_TO_BE_COMPILED 613822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL) 614822ba247SBram Moolenaar return FAIL; 6150cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_COMPILED) 6167eeefd4aSBram Moolenaar { 61752c124d3SBram Moolenaar error = check_user_func_argcount(ufunc, argcount); 6185082471fSBram Moolenaar if (error != FCERR_UNKNOWN) 6195082471fSBram Moolenaar { 6205082471fSBram Moolenaar if (error == FCERR_TOOMANY) 6215082471fSBram Moolenaar semsg(_(e_toomanyarg), ufunc->uf_name); 6225082471fSBram Moolenaar else 6235082471fSBram Moolenaar semsg(_(e_toofewarg), ufunc->uf_name); 6245082471fSBram Moolenaar return FAIL; 6255082471fSBram Moolenaar } 6265082471fSBram Moolenaar 6277eeefd4aSBram Moolenaar // The function has been compiled, can call it quickly. For a function 6287eeefd4aSBram Moolenaar // that was defined later: we can call it directly next time. 629cd45ed03SBram Moolenaar // TODO: what if the function was deleted and then defined again? 6307eeefd4aSBram Moolenaar if (iptr != NULL) 6317eeefd4aSBram Moolenaar { 63220431c9dSBram Moolenaar delete_instr(iptr); 6337eeefd4aSBram Moolenaar iptr->isn_type = ISN_DCALL; 6347eeefd4aSBram Moolenaar iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx; 6357eeefd4aSBram Moolenaar iptr->isn_arg.dfunc.cdf_argcount = argcount; 6367eeefd4aSBram Moolenaar } 6378a7d6542SBram Moolenaar return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx); 6387eeefd4aSBram Moolenaar } 6398a7d6542SBram Moolenaar 6408a7d6542SBram Moolenaar if (call_prepare(argcount, argvars, ectx) == FAIL) 6418a7d6542SBram Moolenaar return FAIL; 642a80faa89SBram Moolenaar CLEAR_FIELD(funcexe); 6438a7d6542SBram Moolenaar funcexe.evaluate = TRUE; 6448a7d6542SBram Moolenaar 6458a7d6542SBram Moolenaar // Call the user function. Result goes in last position on the stack. 6468a7d6542SBram Moolenaar // TODO: add selfdict if there is one 6478a7d6542SBram Moolenaar error = call_user_func_check(ufunc, argcount, argvars, 6488a7d6542SBram Moolenaar STACK_TV_BOT(-1), &funcexe, NULL); 6498a7d6542SBram Moolenaar 6508a7d6542SBram Moolenaar // Clear the arguments. 6518a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 6528a7d6542SBram Moolenaar clear_tv(&argvars[idx]); 6538a7d6542SBram Moolenaar 6548a7d6542SBram Moolenaar if (error != FCERR_NONE) 6558a7d6542SBram Moolenaar { 6568a7d6542SBram Moolenaar user_func_error(error, ufunc->uf_name); 6578a7d6542SBram Moolenaar return FAIL; 6588a7d6542SBram Moolenaar } 65928ee892aSBram Moolenaar if (did_emsg > did_emsg_before) 660ed677f55SBram Moolenaar // Error other than from calling the function itself. 661ed677f55SBram Moolenaar return FAIL; 6628a7d6542SBram Moolenaar return OK; 6638a7d6542SBram Moolenaar } 6648a7d6542SBram Moolenaar 6658a7d6542SBram Moolenaar /* 666a177344dSBram Moolenaar * Return TRUE if an error was given or CTRL-C was pressed. 667a177344dSBram Moolenaar */ 668a177344dSBram Moolenaar static int 669a177344dSBram Moolenaar vim9_aborting(int prev_called_emsg) 670a177344dSBram Moolenaar { 671a177344dSBram Moolenaar return called_emsg > prev_called_emsg || got_int || did_throw; 672a177344dSBram Moolenaar } 673a177344dSBram Moolenaar 674a177344dSBram Moolenaar /* 6758a7d6542SBram Moolenaar * Execute a function by "name". 6768a7d6542SBram Moolenaar * This can be a builtin function or a user function. 6777eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 6788a7d6542SBram Moolenaar * Returns FAIL if not found without an error message. 6798a7d6542SBram Moolenaar */ 6808a7d6542SBram Moolenaar static int 6817eeefd4aSBram Moolenaar call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) 6828a7d6542SBram Moolenaar { 6838a7d6542SBram Moolenaar ufunc_T *ufunc; 6848a7d6542SBram Moolenaar 6858a7d6542SBram Moolenaar if (builtin_function(name, -1)) 6868a7d6542SBram Moolenaar { 6878a7d6542SBram Moolenaar int func_idx = find_internal_func(name); 6888a7d6542SBram Moolenaar 6898a7d6542SBram Moolenaar if (func_idx < 0) 6908a7d6542SBram Moolenaar return FAIL; 691389df259SBram Moolenaar if (check_internal_func(func_idx, argcount) < 0) 6928a7d6542SBram Moolenaar return FAIL; 6938a7d6542SBram Moolenaar return call_bfunc(func_idx, argcount, ectx); 6948a7d6542SBram Moolenaar } 6958a7d6542SBram Moolenaar 6964c17ad94SBram Moolenaar ufunc = find_func(name, FALSE, NULL); 697a177344dSBram Moolenaar 698a177344dSBram Moolenaar if (ufunc == NULL) 699a177344dSBram Moolenaar { 700a177344dSBram Moolenaar int called_emsg_before = called_emsg; 701a177344dSBram Moolenaar 702a177344dSBram Moolenaar if (script_autoload(name, TRUE)) 703a177344dSBram Moolenaar // loaded a package, search for the function again 704a177344dSBram Moolenaar ufunc = find_func(name, FALSE, NULL); 705a177344dSBram Moolenaar if (vim9_aborting(called_emsg_before)) 706a177344dSBram Moolenaar return FAIL; // bail out if loading the script caused an error 707a177344dSBram Moolenaar } 708a177344dSBram Moolenaar 7098a7d6542SBram Moolenaar if (ufunc != NULL) 7107eeefd4aSBram Moolenaar return call_ufunc(ufunc, argcount, ectx, iptr); 7118a7d6542SBram Moolenaar 7128a7d6542SBram Moolenaar return FAIL; 7138a7d6542SBram Moolenaar } 7148a7d6542SBram Moolenaar 7158a7d6542SBram Moolenaar static int 716a90afb9aSBram Moolenaar call_partial(typval_T *tv, int argcount_arg, ectx_T *ectx) 7178a7d6542SBram Moolenaar { 718a90afb9aSBram Moolenaar int argcount = argcount_arg; 719bd5da371SBram Moolenaar char_u *name = NULL; 7208a7d6542SBram Moolenaar int called_emsg_before = called_emsg; 72195006e3dSBram Moolenaar int res; 7228a7d6542SBram Moolenaar 7238a7d6542SBram Moolenaar if (tv->v_type == VAR_PARTIAL) 7248a7d6542SBram Moolenaar { 7258a7d6542SBram Moolenaar partial_T *pt = tv->vval.v_partial; 726a90afb9aSBram Moolenaar int i; 727a90afb9aSBram Moolenaar 728a90afb9aSBram Moolenaar if (pt->pt_argc > 0) 729a90afb9aSBram Moolenaar { 730a90afb9aSBram Moolenaar // Make space for arguments from the partial, shift the "argcount" 731a90afb9aSBram Moolenaar // arguments up. 732a90afb9aSBram Moolenaar if (ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL) 733a90afb9aSBram Moolenaar return FAIL; 734a90afb9aSBram Moolenaar for (i = 1; i <= argcount; ++i) 735a90afb9aSBram Moolenaar *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i); 736a90afb9aSBram Moolenaar ectx->ec_stack.ga_len += pt->pt_argc; 737a90afb9aSBram Moolenaar argcount += pt->pt_argc; 738a90afb9aSBram Moolenaar 739a90afb9aSBram Moolenaar // copy the arguments from the partial onto the stack 740a90afb9aSBram Moolenaar for (i = 0; i < pt->pt_argc; ++i) 741a90afb9aSBram Moolenaar copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i)); 742a90afb9aSBram Moolenaar } 7438a7d6542SBram Moolenaar 7448a7d6542SBram Moolenaar if (pt->pt_func != NULL) 745f7779c63SBram Moolenaar { 746f7779c63SBram Moolenaar int ret = call_ufunc(pt->pt_func, argcount, ectx, NULL); 747f7779c63SBram Moolenaar 748f7779c63SBram Moolenaar // closure may need the function context where it was defined 749f7779c63SBram Moolenaar ectx->ec_outer_stack = pt->pt_ectx_stack; 750f7779c63SBram Moolenaar ectx->ec_outer_frame = pt->pt_ectx_frame; 751f7779c63SBram Moolenaar 752f7779c63SBram Moolenaar return ret; 753f7779c63SBram Moolenaar } 7548a7d6542SBram Moolenaar name = pt->pt_name; 7558a7d6542SBram Moolenaar } 756bd5da371SBram Moolenaar else if (tv->v_type == VAR_FUNC) 7578a7d6542SBram Moolenaar name = tv->vval.v_string; 75895006e3dSBram Moolenaar if (name != NULL) 75995006e3dSBram Moolenaar { 76095006e3dSBram Moolenaar char_u fname_buf[FLEN_FIXED + 1]; 76195006e3dSBram Moolenaar char_u *tofree = NULL; 76295006e3dSBram Moolenaar int error = FCERR_NONE; 76395006e3dSBram Moolenaar char_u *fname; 76495006e3dSBram Moolenaar 76595006e3dSBram Moolenaar // May need to translate <SNR>123_ to K_SNR. 76695006e3dSBram Moolenaar fname = fname_trans_sid(name, fname_buf, &tofree, &error); 76795006e3dSBram Moolenaar if (error != FCERR_NONE) 76895006e3dSBram Moolenaar res = FAIL; 76995006e3dSBram Moolenaar else 77095006e3dSBram Moolenaar res = call_by_name(fname, argcount, ectx, NULL); 77195006e3dSBram Moolenaar vim_free(tofree); 77295006e3dSBram Moolenaar } 77395006e3dSBram Moolenaar 77495006e3dSBram Moolenaar if (name == NULL || res == FAIL) 7758a7d6542SBram Moolenaar { 7768a7d6542SBram Moolenaar if (called_emsg == called_emsg_before) 777015f4267SBram Moolenaar semsg(_(e_unknownfunc), 778015f4267SBram Moolenaar name == NULL ? (char_u *)"[unknown]" : name); 7798a7d6542SBram Moolenaar return FAIL; 7808a7d6542SBram Moolenaar } 7818a7d6542SBram Moolenaar return OK; 7828a7d6542SBram Moolenaar } 7838a7d6542SBram Moolenaar 7848a7d6542SBram Moolenaar /* 7850b4c66c6SBram Moolenaar * Check if "lock" is VAR_LOCKED or VAR_FIXED. If so give an error and return 7860b4c66c6SBram Moolenaar * TRUE. 7870b4c66c6SBram Moolenaar */ 7880b4c66c6SBram Moolenaar static int 7890b4c66c6SBram Moolenaar error_if_locked(int lock, char *error) 7900b4c66c6SBram Moolenaar { 7910b4c66c6SBram Moolenaar if (lock & (VAR_LOCKED | VAR_FIXED)) 7920b4c66c6SBram Moolenaar { 7930b4c66c6SBram Moolenaar emsg(_(error)); 7940b4c66c6SBram Moolenaar return TRUE; 7950b4c66c6SBram Moolenaar } 7960b4c66c6SBram Moolenaar return FALSE; 7970b4c66c6SBram Moolenaar } 7980b4c66c6SBram Moolenaar 7990b4c66c6SBram Moolenaar /* 8000bbf722aSBram Moolenaar * Store "tv" in variable "name". 8010bbf722aSBram Moolenaar * This is for s: and g: variables. 8020bbf722aSBram Moolenaar */ 8030bbf722aSBram Moolenaar static void 8040bbf722aSBram Moolenaar store_var(char_u *name, typval_T *tv) 8050bbf722aSBram Moolenaar { 8060bbf722aSBram Moolenaar funccal_entry_T entry; 8070bbf722aSBram Moolenaar 8080bbf722aSBram Moolenaar save_funccal(&entry); 80930fd8204SBram Moolenaar set_var_const(name, NULL, tv, FALSE, ASSIGN_NO_DECL); 8100bbf722aSBram Moolenaar restore_funccal(); 8110bbf722aSBram Moolenaar } 8120bbf722aSBram Moolenaar 8133beaf9cdSBram Moolenaar /* 8144f5e3977SBram Moolenaar * Convert "tv" to a string. 8154f5e3977SBram Moolenaar * Return FAIL if not allowed. 8164f5e3977SBram Moolenaar */ 8174f5e3977SBram Moolenaar static int 8184f5e3977SBram Moolenaar do_2string(typval_T *tv, int is_2string_any) 8194f5e3977SBram Moolenaar { 8204f5e3977SBram Moolenaar if (tv->v_type != VAR_STRING) 8214f5e3977SBram Moolenaar { 8224f5e3977SBram Moolenaar char_u *str; 8234f5e3977SBram Moolenaar 8244f5e3977SBram Moolenaar if (is_2string_any) 8254f5e3977SBram Moolenaar { 8264f5e3977SBram Moolenaar switch (tv->v_type) 8274f5e3977SBram Moolenaar { 8284f5e3977SBram Moolenaar case VAR_SPECIAL: 8294f5e3977SBram Moolenaar case VAR_BOOL: 8304f5e3977SBram Moolenaar case VAR_NUMBER: 8314f5e3977SBram Moolenaar case VAR_FLOAT: 8324f5e3977SBram Moolenaar case VAR_BLOB: break; 8334f5e3977SBram Moolenaar default: to_string_error(tv->v_type); 8344f5e3977SBram Moolenaar return FAIL; 8354f5e3977SBram Moolenaar } 8364f5e3977SBram Moolenaar } 8374f5e3977SBram Moolenaar str = typval_tostring(tv); 8384f5e3977SBram Moolenaar clear_tv(tv); 8394f5e3977SBram Moolenaar tv->v_type = VAR_STRING; 8404f5e3977SBram Moolenaar tv->vval.v_string = str; 8414f5e3977SBram Moolenaar } 8424f5e3977SBram Moolenaar return OK; 8434f5e3977SBram Moolenaar } 8444f5e3977SBram Moolenaar 8454f5e3977SBram Moolenaar /* 8463beaf9cdSBram Moolenaar * When the value of "sv" is a null list of dict, allocate it. 8473beaf9cdSBram Moolenaar */ 8483beaf9cdSBram Moolenaar static void 8493beaf9cdSBram Moolenaar allocate_if_null(typval_T *tv) 8503beaf9cdSBram Moolenaar { 8513beaf9cdSBram Moolenaar switch (tv->v_type) 8523beaf9cdSBram Moolenaar { 8533beaf9cdSBram Moolenaar case VAR_LIST: 8543beaf9cdSBram Moolenaar if (tv->vval.v_list == NULL) 8553beaf9cdSBram Moolenaar rettv_list_alloc(tv); 8563beaf9cdSBram Moolenaar break; 8573beaf9cdSBram Moolenaar case VAR_DICT: 8583beaf9cdSBram Moolenaar if (tv->vval.v_dict == NULL) 8593beaf9cdSBram Moolenaar rettv_dict_alloc(tv); 8603beaf9cdSBram Moolenaar break; 8613beaf9cdSBram Moolenaar default: 8623beaf9cdSBram Moolenaar break; 8633beaf9cdSBram Moolenaar } 8643beaf9cdSBram Moolenaar } 865d3aac291SBram Moolenaar 8660bbf722aSBram Moolenaar /* 8678a7d6542SBram Moolenaar * Execute a function by "name". 8688a7d6542SBram Moolenaar * This can be a builtin function, user function or a funcref. 8697eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 8708a7d6542SBram Moolenaar */ 8718a7d6542SBram Moolenaar static int 8727eeefd4aSBram Moolenaar call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) 8738a7d6542SBram Moolenaar { 8748a7d6542SBram Moolenaar int called_emsg_before = called_emsg; 875ed677f55SBram Moolenaar int res; 8768a7d6542SBram Moolenaar 877ed677f55SBram Moolenaar res = call_by_name(name, argcount, ectx, iptr); 878ed677f55SBram Moolenaar if (res == FAIL && called_emsg == called_emsg_before) 8798a7d6542SBram Moolenaar { 8801df8b3fbSBram Moolenaar dictitem_T *v; 8811df8b3fbSBram Moolenaar 8821df8b3fbSBram Moolenaar v = find_var(name, NULL, FALSE); 8831df8b3fbSBram Moolenaar if (v == NULL) 8841df8b3fbSBram Moolenaar { 8851df8b3fbSBram Moolenaar semsg(_(e_unknownfunc), name); 8868a7d6542SBram Moolenaar return FAIL; 8878a7d6542SBram Moolenaar } 8881df8b3fbSBram Moolenaar if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC) 8891df8b3fbSBram Moolenaar { 8901df8b3fbSBram Moolenaar semsg(_(e_unknownfunc), name); 8911df8b3fbSBram Moolenaar return FAIL; 8921df8b3fbSBram Moolenaar } 8931df8b3fbSBram Moolenaar return call_partial(&v->di_tv, argcount, ectx); 8941df8b3fbSBram Moolenaar } 895ed677f55SBram Moolenaar return res; 8968a7d6542SBram Moolenaar } 8978a7d6542SBram Moolenaar 8988a7d6542SBram Moolenaar /* 899f112f30aSBram Moolenaar * When a function reference is used, fill a partial with the information 900f112f30aSBram Moolenaar * needed, especially when it is used as a closure. 901f112f30aSBram Moolenaar */ 902cd45ed03SBram Moolenaar int 903f112f30aSBram Moolenaar fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx) 904f112f30aSBram Moolenaar { 905f112f30aSBram Moolenaar pt->pt_func = ufunc; 906f112f30aSBram Moolenaar pt->pt_refcount = 1; 907f112f30aSBram Moolenaar 908f112f30aSBram Moolenaar if (pt->pt_func->uf_flags & FC_CLOSURE) 909f112f30aSBram Moolenaar { 910f112f30aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 911f112f30aSBram Moolenaar + ectx->ec_dfunc_idx; 912f112f30aSBram Moolenaar 913f112f30aSBram Moolenaar // The closure needs to find arguments and local 914f112f30aSBram Moolenaar // variables in the current stack. 915f112f30aSBram Moolenaar pt->pt_ectx_stack = &ectx->ec_stack; 916f112f30aSBram Moolenaar pt->pt_ectx_frame = ectx->ec_frame_idx; 917f112f30aSBram Moolenaar 918f112f30aSBram Moolenaar // If this function returns and the closure is still 919f112f30aSBram Moolenaar // being used, we need to make a copy of the context 920f112f30aSBram Moolenaar // (arguments and local variables). Store a reference 921f112f30aSBram Moolenaar // to the partial so we can handle that. 922f112f30aSBram Moolenaar if (ga_grow(&ectx->ec_funcrefs, 1) == FAIL) 923f112f30aSBram Moolenaar { 924f112f30aSBram Moolenaar vim_free(pt); 925f112f30aSBram Moolenaar return FAIL; 926f112f30aSBram Moolenaar } 927f112f30aSBram Moolenaar // Extra variable keeps the count of closures created 928f112f30aSBram Moolenaar // in the current function call. 929f112f30aSBram Moolenaar ++(((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx 930f112f30aSBram Moolenaar + STACK_FRAME_SIZE + dfunc->df_varcount)->vval.v_number; 931f112f30aSBram Moolenaar 932f112f30aSBram Moolenaar ((partial_T **)ectx->ec_funcrefs.ga_data) 933f112f30aSBram Moolenaar [ectx->ec_funcrefs.ga_len] = pt; 934f112f30aSBram Moolenaar ++pt->pt_refcount; 935f112f30aSBram Moolenaar ++ectx->ec_funcrefs.ga_len; 936f112f30aSBram Moolenaar } 937f112f30aSBram Moolenaar ++pt->pt_func->uf_refcount; 938f112f30aSBram Moolenaar return OK; 939f112f30aSBram Moolenaar } 940f112f30aSBram Moolenaar 941f112f30aSBram Moolenaar /* 9428a7d6542SBram Moolenaar * Call a "def" function from old Vim script. 9438a7d6542SBram Moolenaar * Return OK or FAIL. 9448a7d6542SBram Moolenaar */ 9458a7d6542SBram Moolenaar int 9468a7d6542SBram Moolenaar call_def_function( 9478a7d6542SBram Moolenaar ufunc_T *ufunc, 94823e03252SBram Moolenaar int argc_arg, // nr of arguments 9498a7d6542SBram Moolenaar typval_T *argv, // arguments 9506f5b6dfbSBram Moolenaar partial_T *partial, // optional partial for context 9518a7d6542SBram Moolenaar typval_T *rettv) // return value 9528a7d6542SBram Moolenaar { 9538a7d6542SBram Moolenaar ectx_T ectx; // execution context 95423e03252SBram Moolenaar int argc = argc_arg; 955bf67ea1aSBram Moolenaar int initial_frame_idx; 9568a7d6542SBram Moolenaar typval_T *tv; 9578a7d6542SBram Moolenaar int idx; 9588a7d6542SBram Moolenaar int ret = FAIL; 959170fcfcfSBram Moolenaar int defcount = ufunc->uf_args.ga_len - argc; 960ee8580e5SBram Moolenaar sctx_T save_current_sctx = current_sctx; 961270d0388SBram Moolenaar int breakcheck_count = 0; 962eeece9e4SBram Moolenaar int did_emsg_before = did_emsg_cumul + did_emsg; 96377e5dcc3SBram Moolenaar int save_suppress_errthrow = suppress_errthrow; 964352134bbSBram Moolenaar msglist_T **saved_msg_list = NULL; 965352134bbSBram Moolenaar msglist_T *private_msg_list = NULL; 96602194d2bSBram Moolenaar cmdmod_T save_cmdmod; 96702194d2bSBram Moolenaar int restore_cmdmod = FALSE; 96856602ba1SBram Moolenaar int save_emsg_silent_def = emsg_silent_def; 96956602ba1SBram Moolenaar int save_did_emsg_def = did_emsg_def; 970171fb923SBram Moolenaar int trylevel_at_start = trylevel; 9710ba48e8cSBram Moolenaar int orig_funcdepth; 9728a7d6542SBram Moolenaar 9738a7d6542SBram Moolenaar // Get pointer to item in the stack. 9748a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) 9758a7d6542SBram Moolenaar 9768a7d6542SBram Moolenaar // Get pointer to item at the bottom of the stack, -1 is the bottom. 9778a7d6542SBram Moolenaar #undef STACK_TV_BOT 9788a7d6542SBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx) 9798a7d6542SBram Moolenaar 9801378fbc4SBram Moolenaar // Get pointer to a local variable on the stack. Negative for arguments. 981bf67ea1aSBram Moolenaar #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx) 9828a7d6542SBram Moolenaar 983c8cd2b34SBram Moolenaar // Like STACK_TV_VAR but use the outer scope 984c8cd2b34SBram Moolenaar #define STACK_OUT_TV_VAR(idx) (((typval_T *)ectx.ec_outer_stack->ga_data) + ectx.ec_outer_frame + STACK_FRAME_SIZE + idx) 985c8cd2b34SBram Moolenaar 9860cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_NOT_COMPILED 9870cb5bcf5SBram Moolenaar || (ufunc->uf_def_status == UF_TO_BE_COMPILED 988822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL)) 98925e0f586SBram Moolenaar { 990eeece9e4SBram Moolenaar if (did_emsg_cumul + did_emsg == did_emsg_before) 991451c2e35SBram Moolenaar semsg(_(e_function_is_not_compiled_str), 992682d0a15SBram Moolenaar printable_func_name(ufunc)); 993822ba247SBram Moolenaar return FAIL; 99425e0f586SBram Moolenaar } 995822ba247SBram Moolenaar 99609689a02SBram Moolenaar { 997822ba247SBram Moolenaar // Check the function was really compiled. 99809689a02SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 99909689a02SBram Moolenaar + ufunc->uf_dfunc_idx; 100009689a02SBram Moolenaar if (dfunc->df_instr == NULL) 100138ddf333SBram Moolenaar { 100238ddf333SBram Moolenaar iemsg("using call_def_function() on not compiled function"); 100309689a02SBram Moolenaar return FAIL; 100409689a02SBram Moolenaar } 100538ddf333SBram Moolenaar } 10068a7d6542SBram Moolenaar 10070ba48e8cSBram Moolenaar // If depth of calling is getting too high, don't execute the function. 10080ba48e8cSBram Moolenaar orig_funcdepth = funcdepth_get(); 10090ba48e8cSBram Moolenaar if (funcdepth_increment() == FAIL) 10100ba48e8cSBram Moolenaar return FAIL; 10110ba48e8cSBram Moolenaar 10123b6a6eb7SBram Moolenaar CLEAR_FIELD(ectx); 10133b6a6eb7SBram Moolenaar ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; 10143b6a6eb7SBram Moolenaar ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); 10153b6a6eb7SBram Moolenaar if (ga_grow(&ectx.ec_stack, 20) == FAIL) 10160ba48e8cSBram Moolenaar { 10170ba48e8cSBram Moolenaar funcdepth_decrement(); 10183b6a6eb7SBram Moolenaar return FAIL; 10190ba48e8cSBram Moolenaar } 10208a7d6542SBram Moolenaar ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); 1021148ce7aeSBram Moolenaar ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10); 10228a7d6542SBram Moolenaar 1023*fc0e8f5cSBram Moolenaar // Put arguments on the stack, but no more than what the function expects. 1024*fc0e8f5cSBram Moolenaar // A lambda can be called with more arguments than it uses. 1025*fc0e8f5cSBram Moolenaar for (idx = 0; idx < argc 1026*fc0e8f5cSBram Moolenaar && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len); 1027*fc0e8f5cSBram Moolenaar ++idx) 10288a7d6542SBram Moolenaar { 102965b9545fSBram Moolenaar if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len 10308b565c2cSBram Moolenaar && check_typval_type(ufunc->uf_arg_types[idx], &argv[idx], 10318b565c2cSBram Moolenaar idx + 1) == FAIL) 103265b9545fSBram Moolenaar goto failed_early; 10338a7d6542SBram Moolenaar copy_tv(&argv[idx], STACK_TV_BOT(0)); 10348a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 10358a7d6542SBram Moolenaar } 103623e03252SBram Moolenaar 103723e03252SBram Moolenaar // Turn varargs into a list. Empty list if no args. 103823e03252SBram Moolenaar if (ufunc->uf_va_name != NULL) 103923e03252SBram Moolenaar { 104023e03252SBram Moolenaar int vararg_count = argc - ufunc->uf_args.ga_len; 104123e03252SBram Moolenaar 104223e03252SBram Moolenaar if (vararg_count < 0) 104323e03252SBram Moolenaar vararg_count = 0; 104423e03252SBram Moolenaar else 104523e03252SBram Moolenaar argc -= vararg_count; 104623e03252SBram Moolenaar if (exe_newlist(vararg_count, &ectx) == FAIL) 10471a2f4bf6SBram Moolenaar goto failed_early; 104824aa48b7SBram Moolenaar 104924aa48b7SBram Moolenaar // Check the type of the list items. 105024aa48b7SBram Moolenaar tv = STACK_TV_BOT(-1); 105124aa48b7SBram Moolenaar if (ufunc->uf_va_type != NULL 10522f8cbc4bSBram Moolenaar && ufunc->uf_va_type != &t_any 105324aa48b7SBram Moolenaar && ufunc->uf_va_type->tt_member != &t_any 105424aa48b7SBram Moolenaar && tv->vval.v_list != NULL) 105524aa48b7SBram Moolenaar { 105624aa48b7SBram Moolenaar type_T *expected = ufunc->uf_va_type->tt_member; 105724aa48b7SBram Moolenaar listitem_T *li = tv->vval.v_list->lv_first; 105824aa48b7SBram Moolenaar 105924aa48b7SBram Moolenaar for (idx = 0; idx < vararg_count; ++idx) 106024aa48b7SBram Moolenaar { 10618b565c2cSBram Moolenaar if (check_typval_type(expected, &li->li_tv, 10628b565c2cSBram Moolenaar argc + idx + 1) == FAIL) 106324aa48b7SBram Moolenaar goto failed_early; 106424aa48b7SBram Moolenaar li = li->li_next; 106524aa48b7SBram Moolenaar } 106624aa48b7SBram Moolenaar } 106724aa48b7SBram Moolenaar 106823e03252SBram Moolenaar if (defcount > 0) 106923e03252SBram Moolenaar // Move varargs list to below missing default arguments. 107023e03252SBram Moolenaar *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1); 107123e03252SBram Moolenaar --ectx.ec_stack.ga_len; 107223e03252SBram Moolenaar } 107323e03252SBram Moolenaar 1074170fcfcfSBram Moolenaar // Make space for omitted arguments, will store default value below. 107523e03252SBram Moolenaar // Any varargs list goes after them. 1076170fcfcfSBram Moolenaar if (defcount > 0) 1077170fcfcfSBram Moolenaar for (idx = 0; idx < defcount; ++idx) 1078170fcfcfSBram Moolenaar { 1079170fcfcfSBram Moolenaar STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; 1080170fcfcfSBram Moolenaar ++ectx.ec_stack.ga_len; 1081170fcfcfSBram Moolenaar } 108223e03252SBram Moolenaar if (ufunc->uf_va_name != NULL) 108323e03252SBram Moolenaar ++ectx.ec_stack.ga_len; 10848a7d6542SBram Moolenaar 10858a7d6542SBram Moolenaar // Frame pointer points to just after arguments. 1086bf67ea1aSBram Moolenaar ectx.ec_frame_idx = ectx.ec_stack.ga_len; 1087bf67ea1aSBram Moolenaar initial_frame_idx = ectx.ec_frame_idx; 10888a7d6542SBram Moolenaar 10896f5b6dfbSBram Moolenaar if (partial != NULL) 10906f5b6dfbSBram Moolenaar { 109108f7a41bSBram Moolenaar if (partial->pt_ectx_stack == NULL && current_ectx != NULL) 109208f7a41bSBram Moolenaar { 109308f7a41bSBram Moolenaar // TODO: is this always the right way? 109408f7a41bSBram Moolenaar ectx.ec_outer_stack = ¤t_ectx->ec_stack; 109508f7a41bSBram Moolenaar ectx.ec_outer_frame = current_ectx->ec_frame_idx; 109608f7a41bSBram Moolenaar } 109708f7a41bSBram Moolenaar else 109808f7a41bSBram Moolenaar { 10996f5b6dfbSBram Moolenaar ectx.ec_outer_stack = partial->pt_ectx_stack; 11006f5b6dfbSBram Moolenaar ectx.ec_outer_frame = partial->pt_ectx_frame; 11016f5b6dfbSBram Moolenaar } 110208f7a41bSBram Moolenaar } 1103f112f30aSBram Moolenaar else if (ufunc->uf_partial != NULL) 1104f112f30aSBram Moolenaar { 1105f112f30aSBram Moolenaar ectx.ec_outer_stack = ufunc->uf_partial->pt_ectx_stack; 1106f112f30aSBram Moolenaar ectx.ec_outer_frame = ufunc->uf_partial->pt_ectx_frame; 1107f112f30aSBram Moolenaar } 11086f5b6dfbSBram Moolenaar 11098a7d6542SBram Moolenaar // dummy frame entries 11108a7d6542SBram Moolenaar for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) 11118a7d6542SBram Moolenaar { 11128a7d6542SBram Moolenaar STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; 11138a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 11148a7d6542SBram Moolenaar } 11158a7d6542SBram Moolenaar 1116bd5da371SBram Moolenaar { 1117148ce7aeSBram Moolenaar // Reserve space for local variables and any closure reference count. 1118bd5da371SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 1119bd5da371SBram Moolenaar + ufunc->uf_dfunc_idx; 1120bd5da371SBram Moolenaar 1121148ce7aeSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 11228a7d6542SBram Moolenaar STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; 1123148ce7aeSBram Moolenaar ectx.ec_stack.ga_len += dfunc->df_varcount; 1124148ce7aeSBram Moolenaar if (dfunc->df_has_closure) 1125148ce7aeSBram Moolenaar { 1126148ce7aeSBram Moolenaar STACK_TV_VAR(idx)->v_type = VAR_NUMBER; 1127148ce7aeSBram Moolenaar STACK_TV_VAR(idx)->vval.v_number = 0; 1128148ce7aeSBram Moolenaar ++ectx.ec_stack.ga_len; 1129148ce7aeSBram Moolenaar } 11308a7d6542SBram Moolenaar 11318a7d6542SBram Moolenaar ectx.ec_instr = dfunc->df_instr; 1132bd5da371SBram Moolenaar } 1133170fcfcfSBram Moolenaar 1134ee8580e5SBram Moolenaar // Following errors are in the function, not the caller. 1135a26b9700SBram Moolenaar // Commands behave like vim9script. 1136ee8580e5SBram Moolenaar estack_push_ufunc(ufunc, 1); 1137ee8580e5SBram Moolenaar current_sctx = ufunc->uf_script_ctx; 1138a26b9700SBram Moolenaar current_sctx.sc_version = SCRIPT_VERSION_VIM9; 1139a26b9700SBram Moolenaar 1140352134bbSBram Moolenaar // Use a specific location for storing error messages to be converted to an 1141352134bbSBram Moolenaar // exception. 1142352134bbSBram Moolenaar saved_msg_list = msg_list; 1143352134bbSBram Moolenaar msg_list = &private_msg_list; 1144352134bbSBram Moolenaar 114577e5dcc3SBram Moolenaar // Do turn errors into exceptions. 114677e5dcc3SBram Moolenaar suppress_errthrow = FALSE; 114777e5dcc3SBram Moolenaar 114856602ba1SBram Moolenaar // When ":silent!" was used before calling then we still abort the 114956602ba1SBram Moolenaar // function. If ":silent!" is used in the function then we don't. 115056602ba1SBram Moolenaar emsg_silent_def = emsg_silent; 115156602ba1SBram Moolenaar did_emsg_def = 0; 115256602ba1SBram Moolenaar 1153170fcfcfSBram Moolenaar // Decide where to start execution, handles optional arguments. 1154170fcfcfSBram Moolenaar init_instr_idx(ufunc, argc, &ectx); 1155170fcfcfSBram Moolenaar 11568a7d6542SBram Moolenaar for (;;) 11578a7d6542SBram Moolenaar { 11588a7d6542SBram Moolenaar isn_T *iptr; 115920431c9dSBram Moolenaar 1160270d0388SBram Moolenaar if (++breakcheck_count >= 100) 1161270d0388SBram Moolenaar { 1162270d0388SBram Moolenaar line_breakcheck(); 1163270d0388SBram Moolenaar breakcheck_count = 0; 1164270d0388SBram Moolenaar } 116520431c9dSBram Moolenaar if (got_int) 116620431c9dSBram Moolenaar { 116720431c9dSBram Moolenaar // Turn CTRL-C into an exception. 116820431c9dSBram Moolenaar got_int = FALSE; 116997acfc78SBram Moolenaar if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL) 117020431c9dSBram Moolenaar goto failed; 117120431c9dSBram Moolenaar did_throw = TRUE; 117220431c9dSBram Moolenaar } 11738a7d6542SBram Moolenaar 1174a26b9700SBram Moolenaar if (did_emsg && msg_list != NULL && *msg_list != NULL) 1175a26b9700SBram Moolenaar { 1176a26b9700SBram Moolenaar // Turn an error message into an exception. 1177a26b9700SBram Moolenaar did_emsg = FALSE; 1178a26b9700SBram Moolenaar if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL) 1179a26b9700SBram Moolenaar goto failed; 1180a26b9700SBram Moolenaar did_throw = TRUE; 1181a26b9700SBram Moolenaar *msg_list = NULL; 1182a26b9700SBram Moolenaar } 1183a26b9700SBram Moolenaar 11848a7d6542SBram Moolenaar if (did_throw && !ectx.ec_in_catch) 11858a7d6542SBram Moolenaar { 11868a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 118720431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 11888a7d6542SBram Moolenaar 11898a7d6542SBram Moolenaar // An exception jumps to the first catch, finally, or returns from 11908a7d6542SBram Moolenaar // the current function. 11918a7d6542SBram Moolenaar if (trystack->ga_len > 0) 11928a7d6542SBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; 1193bf67ea1aSBram Moolenaar if (trycmd != NULL && trycmd->tcd_frame_idx == ectx.ec_frame_idx) 11948a7d6542SBram Moolenaar { 11958a7d6542SBram Moolenaar // jump to ":catch" or ":finally" 11968a7d6542SBram Moolenaar ectx.ec_in_catch = TRUE; 11978a7d6542SBram Moolenaar ectx.ec_iidx = trycmd->tcd_catch_idx; 11988a7d6542SBram Moolenaar } 11998a7d6542SBram Moolenaar else 12008a7d6542SBram Moolenaar { 1201cdd70f09SBram Moolenaar // Not inside try or need to return from current functions. 1202cdd70f09SBram Moolenaar // Push a dummy return value. 1203270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 12048a7d6542SBram Moolenaar goto failed; 12058a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 12068a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 12078a7d6542SBram Moolenaar tv->vval.v_number = 0; 12088a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 1209cdd70f09SBram Moolenaar if (ectx.ec_frame_idx == initial_frame_idx) 1210cdd70f09SBram Moolenaar { 1211cdd70f09SBram Moolenaar // At the toplevel we are done. 1212257cc5eeSBram Moolenaar need_rethrow = TRUE; 1213bf67ea1aSBram Moolenaar if (handle_closure_in_use(&ectx, FALSE) == FAIL) 1214bf67ea1aSBram Moolenaar goto failed; 12158a7d6542SBram Moolenaar goto done; 12168a7d6542SBram Moolenaar } 12178a7d6542SBram Moolenaar 1218bf67ea1aSBram Moolenaar if (func_return(&ectx) == FAIL) 1219bf67ea1aSBram Moolenaar goto failed; 12208a7d6542SBram Moolenaar } 12218a7d6542SBram Moolenaar continue; 12228a7d6542SBram Moolenaar } 12238a7d6542SBram Moolenaar 12248a7d6542SBram Moolenaar iptr = &ectx.ec_instr[ectx.ec_iidx++]; 12258a7d6542SBram Moolenaar switch (iptr->isn_type) 12268a7d6542SBram Moolenaar { 12278a7d6542SBram Moolenaar // execute Ex command line 12288a7d6542SBram Moolenaar case ISN_EXEC: 1229631e8f93SBram Moolenaar { 12306378c4feSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 12318a7d6542SBram Moolenaar do_cmdline_cmd(iptr->isn_arg.string); 1232eeece9e4SBram Moolenaar if (did_emsg) 1233eeece9e4SBram Moolenaar goto on_error; 1234631e8f93SBram Moolenaar } 12358a7d6542SBram Moolenaar break; 12368a7d6542SBram Moolenaar 1237cfe435d7SBram Moolenaar // execute Ex command from pieces on the stack 1238cfe435d7SBram Moolenaar case ISN_EXECCONCAT: 1239cfe435d7SBram Moolenaar { 1240cfe435d7SBram Moolenaar int count = iptr->isn_arg.number; 12417f6f56f4SBram Moolenaar size_t len = 0; 1242cfe435d7SBram Moolenaar int pass; 1243cfe435d7SBram Moolenaar int i; 1244cfe435d7SBram Moolenaar char_u *cmd = NULL; 1245cfe435d7SBram Moolenaar char_u *str; 1246cfe435d7SBram Moolenaar 1247cfe435d7SBram Moolenaar for (pass = 1; pass <= 2; ++pass) 1248cfe435d7SBram Moolenaar { 1249cfe435d7SBram Moolenaar for (i = 0; i < count; ++i) 1250cfe435d7SBram Moolenaar { 1251cfe435d7SBram Moolenaar tv = STACK_TV_BOT(i - count); 1252cfe435d7SBram Moolenaar str = tv->vval.v_string; 1253cfe435d7SBram Moolenaar if (str != NULL && *str != NUL) 1254cfe435d7SBram Moolenaar { 1255cfe435d7SBram Moolenaar if (pass == 2) 1256cfe435d7SBram Moolenaar STRCPY(cmd + len, str); 1257cfe435d7SBram Moolenaar len += STRLEN(str); 1258cfe435d7SBram Moolenaar } 1259cfe435d7SBram Moolenaar if (pass == 2) 1260cfe435d7SBram Moolenaar clear_tv(tv); 1261cfe435d7SBram Moolenaar } 1262cfe435d7SBram Moolenaar if (pass == 1) 1263cfe435d7SBram Moolenaar { 1264cfe435d7SBram Moolenaar cmd = alloc(len + 1); 1265cfe435d7SBram Moolenaar if (cmd == NULL) 1266cfe435d7SBram Moolenaar goto failed; 1267cfe435d7SBram Moolenaar len = 0; 1268cfe435d7SBram Moolenaar } 1269cfe435d7SBram Moolenaar } 1270cfe435d7SBram Moolenaar 12716378c4feSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1272cfe435d7SBram Moolenaar do_cmdline_cmd(cmd); 1273cfe435d7SBram Moolenaar vim_free(cmd); 1274cfe435d7SBram Moolenaar } 1275cfe435d7SBram Moolenaar break; 1276cfe435d7SBram Moolenaar 12778a7d6542SBram Moolenaar // execute :echo {string} ... 12788a7d6542SBram Moolenaar case ISN_ECHO: 12798a7d6542SBram Moolenaar { 12808a7d6542SBram Moolenaar int count = iptr->isn_arg.echo.echo_count; 12818a7d6542SBram Moolenaar int atstart = TRUE; 12828a7d6542SBram Moolenaar int needclr = TRUE; 12838a7d6542SBram Moolenaar 12848a7d6542SBram Moolenaar for (idx = 0; idx < count; ++idx) 12858a7d6542SBram Moolenaar { 12868a7d6542SBram Moolenaar tv = STACK_TV_BOT(idx - count); 12878a7d6542SBram Moolenaar echo_one(tv, iptr->isn_arg.echo.echo_with_white, 12888a7d6542SBram Moolenaar &atstart, &needclr); 12898a7d6542SBram Moolenaar clear_tv(tv); 12908a7d6542SBram Moolenaar } 1291e0807ea4SBram Moolenaar if (needclr) 1292e0807ea4SBram Moolenaar msg_clr_eos(); 12938a7d6542SBram Moolenaar ectx.ec_stack.ga_len -= count; 12948a7d6542SBram Moolenaar } 12958a7d6542SBram Moolenaar break; 12968a7d6542SBram Moolenaar 1297f93c7feaSBram Moolenaar // :execute {string} ... 1298f93c7feaSBram Moolenaar // :echomsg {string} ... 1299f93c7feaSBram Moolenaar // :echoerr {string} ... 1300ad39c094SBram Moolenaar case ISN_EXECUTE: 1301f93c7feaSBram Moolenaar case ISN_ECHOMSG: 1302f93c7feaSBram Moolenaar case ISN_ECHOERR: 1303ad39c094SBram Moolenaar { 1304ad39c094SBram Moolenaar int count = iptr->isn_arg.number; 1305ad39c094SBram Moolenaar garray_T ga; 1306ad39c094SBram Moolenaar char_u buf[NUMBUFLEN]; 1307ad39c094SBram Moolenaar char_u *p; 1308ad39c094SBram Moolenaar int len; 1309ad39c094SBram Moolenaar int failed = FALSE; 1310ad39c094SBram Moolenaar 1311ad39c094SBram Moolenaar ga_init2(&ga, 1, 80); 1312ad39c094SBram Moolenaar for (idx = 0; idx < count; ++idx) 1313ad39c094SBram Moolenaar { 1314ad39c094SBram Moolenaar tv = STACK_TV_BOT(idx - count); 1315e5abf7afSBram Moolenaar if (iptr->isn_type == ISN_EXECUTE) 1316e5abf7afSBram Moolenaar { 1317e5abf7afSBram Moolenaar if (tv->v_type == VAR_CHANNEL 1318e5abf7afSBram Moolenaar || tv->v_type == VAR_JOB) 1319ad39c094SBram Moolenaar { 13207517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1321ad39c094SBram Moolenaar emsg(_(e_inval_string)); 1322ad39c094SBram Moolenaar break; 1323ad39c094SBram Moolenaar } 1324ad39c094SBram Moolenaar else 1325ad39c094SBram Moolenaar p = tv_get_string_buf(tv, buf); 1326e5abf7afSBram Moolenaar } 1327e5abf7afSBram Moolenaar else 1328e5abf7afSBram Moolenaar p = tv_stringify(tv, buf); 1329ad39c094SBram Moolenaar 1330ad39c094SBram Moolenaar len = (int)STRLEN(p); 1331ad39c094SBram Moolenaar if (ga_grow(&ga, len + 2) == FAIL) 1332ad39c094SBram Moolenaar failed = TRUE; 1333ad39c094SBram Moolenaar else 1334ad39c094SBram Moolenaar { 1335ad39c094SBram Moolenaar if (ga.ga_len > 0) 1336ad39c094SBram Moolenaar ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; 1337ad39c094SBram Moolenaar STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); 1338ad39c094SBram Moolenaar ga.ga_len += len; 1339ad39c094SBram Moolenaar } 1340ad39c094SBram Moolenaar clear_tv(tv); 1341ad39c094SBram Moolenaar } 1342ad39c094SBram Moolenaar ectx.ec_stack.ga_len -= count; 1343e5abf7afSBram Moolenaar if (failed) 1344c71ee829SBram Moolenaar { 1345c71ee829SBram Moolenaar ga_clear(&ga); 1346e5abf7afSBram Moolenaar goto on_error; 1347c71ee829SBram Moolenaar } 1348ad39c094SBram Moolenaar 1349e5abf7afSBram Moolenaar if (ga.ga_data != NULL) 1350f93c7feaSBram Moolenaar { 1351f93c7feaSBram Moolenaar if (iptr->isn_type == ISN_EXECUTE) 1352430deb19SBram Moolenaar { 1353430deb19SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1354ad39c094SBram Moolenaar do_cmdline_cmd((char_u *)ga.ga_data); 1355eeece9e4SBram Moolenaar if (did_emsg) 1356c71ee829SBram Moolenaar { 1357c71ee829SBram Moolenaar ga_clear(&ga); 1358eeece9e4SBram Moolenaar goto on_error; 1359430deb19SBram Moolenaar } 1360c71ee829SBram Moolenaar } 1361f93c7feaSBram Moolenaar else 1362f93c7feaSBram Moolenaar { 1363f93c7feaSBram Moolenaar msg_sb_eol(); 1364f93c7feaSBram Moolenaar if (iptr->isn_type == ISN_ECHOMSG) 1365f93c7feaSBram Moolenaar { 1366f93c7feaSBram Moolenaar msg_attr(ga.ga_data, echo_attr); 1367f93c7feaSBram Moolenaar out_flush(); 1368f93c7feaSBram Moolenaar } 1369f93c7feaSBram Moolenaar else 1370f93c7feaSBram Moolenaar { 1371f93c7feaSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1372f93c7feaSBram Moolenaar emsg(ga.ga_data); 1373f93c7feaSBram Moolenaar } 1374f93c7feaSBram Moolenaar } 1375f93c7feaSBram Moolenaar } 1376ad39c094SBram Moolenaar ga_clear(&ga); 1377ad39c094SBram Moolenaar } 1378ad39c094SBram Moolenaar break; 1379ad39c094SBram Moolenaar 13808a7d6542SBram Moolenaar // load local variable or argument 13818a7d6542SBram Moolenaar case ISN_LOAD: 1382270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 13838a7d6542SBram Moolenaar goto failed; 13848a7d6542SBram Moolenaar copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); 13858a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 13868a7d6542SBram Moolenaar break; 13878a7d6542SBram Moolenaar 1388c8cd2b34SBram Moolenaar // load variable or argument from outer scope 1389c8cd2b34SBram Moolenaar case ISN_LOADOUTER: 1390270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 1391c8cd2b34SBram Moolenaar goto failed; 1392c8cd2b34SBram Moolenaar copy_tv(STACK_OUT_TV_VAR(iptr->isn_arg.number), 1393c8cd2b34SBram Moolenaar STACK_TV_BOT(0)); 1394c8cd2b34SBram Moolenaar ++ectx.ec_stack.ga_len; 1395c8cd2b34SBram Moolenaar break; 1396c8cd2b34SBram Moolenaar 13978a7d6542SBram Moolenaar // load v: variable 13988a7d6542SBram Moolenaar case ISN_LOADV: 1399270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 14008a7d6542SBram Moolenaar goto failed; 14018a7d6542SBram Moolenaar copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0)); 14028a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 14038a7d6542SBram Moolenaar break; 14048a7d6542SBram Moolenaar 1405b283a8a6SBram Moolenaar // load s: variable in Vim9 script 14068a7d6542SBram Moolenaar case ISN_LOADSCRIPT: 14078a7d6542SBram Moolenaar { 14084aab88d9SBram Moolenaar scriptref_T *sref = iptr->isn_arg.script.scriptref; 14094aab88d9SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 14104aab88d9SBram Moolenaar + ectx.ec_dfunc_idx; 14114aab88d9SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid); 14128a7d6542SBram Moolenaar svar_T *sv; 14138a7d6542SBram Moolenaar 14144aab88d9SBram Moolenaar if (sref->sref_seq != si->sn_script_seq) 14154aab88d9SBram Moolenaar { 14164aab88d9SBram Moolenaar // The script was reloaded after the function was 14174aab88d9SBram Moolenaar // compiled, the script_idx may not be valid. 14184aab88d9SBram Moolenaar semsg(_(e_script_variable_invalid_after_reload_in_function_str), 14194aab88d9SBram Moolenaar dfunc->df_ufunc->uf_name_exp); 14204aab88d9SBram Moolenaar goto failed; 14214aab88d9SBram Moolenaar } 14224aab88d9SBram Moolenaar sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx; 14233beaf9cdSBram Moolenaar allocate_if_null(sv->sv_tv); 1424270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 14258a7d6542SBram Moolenaar goto failed; 14268a7d6542SBram Moolenaar copy_tv(sv->sv_tv, STACK_TV_BOT(0)); 14278a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 14288a7d6542SBram Moolenaar } 14298a7d6542SBram Moolenaar break; 14308a7d6542SBram Moolenaar 14318a7d6542SBram Moolenaar // load s: variable in old script 14328a7d6542SBram Moolenaar case ISN_LOADS: 14338a7d6542SBram Moolenaar { 1434b283a8a6SBram Moolenaar hashtab_T *ht = &SCRIPT_VARS( 1435b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 1436b283a8a6SBram Moolenaar char_u *name = iptr->isn_arg.loadstore.ls_name; 14378a7d6542SBram Moolenaar dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE); 14380bbf722aSBram Moolenaar 14398a7d6542SBram Moolenaar if (di == NULL) 14408a7d6542SBram Moolenaar { 14417517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1442451c2e35SBram Moolenaar semsg(_(e_undefined_variable_str), name); 1443f0b9f43cSBram Moolenaar goto on_error; 14448a7d6542SBram Moolenaar } 14458a7d6542SBram Moolenaar else 14468a7d6542SBram Moolenaar { 1447270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 14488a7d6542SBram Moolenaar goto failed; 14498a7d6542SBram Moolenaar copy_tv(&di->di_tv, STACK_TV_BOT(0)); 14508a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 14518a7d6542SBram Moolenaar } 14528a7d6542SBram Moolenaar } 14538a7d6542SBram Moolenaar break; 14548a7d6542SBram Moolenaar 1455d3aac291SBram Moolenaar // load g:/b:/w:/t: variable 14568a7d6542SBram Moolenaar case ISN_LOADG: 1457d3aac291SBram Moolenaar case ISN_LOADB: 1458d3aac291SBram Moolenaar case ISN_LOADW: 1459d3aac291SBram Moolenaar case ISN_LOADT: 14608a7d6542SBram Moolenaar { 1461d3aac291SBram Moolenaar dictitem_T *di = NULL; 1462d3aac291SBram Moolenaar hashtab_T *ht = NULL; 1463d3aac291SBram Moolenaar char namespace; 14642f8ce0aeSBram Moolenaar 1465d3aac291SBram Moolenaar switch (iptr->isn_type) 1466d3aac291SBram Moolenaar { 1467d3aac291SBram Moolenaar case ISN_LOADG: 1468d3aac291SBram Moolenaar ht = get_globvar_ht(); 1469d3aac291SBram Moolenaar namespace = 'g'; 1470d3aac291SBram Moolenaar break; 1471d3aac291SBram Moolenaar case ISN_LOADB: 1472d3aac291SBram Moolenaar ht = &curbuf->b_vars->dv_hashtab; 1473d3aac291SBram Moolenaar namespace = 'b'; 1474d3aac291SBram Moolenaar break; 1475d3aac291SBram Moolenaar case ISN_LOADW: 1476d3aac291SBram Moolenaar ht = &curwin->w_vars->dv_hashtab; 1477d3aac291SBram Moolenaar namespace = 'w'; 1478d3aac291SBram Moolenaar break; 1479d3aac291SBram Moolenaar case ISN_LOADT: 1480d3aac291SBram Moolenaar ht = &curtab->tp_vars->dv_hashtab; 1481d3aac291SBram Moolenaar namespace = 't'; 1482d3aac291SBram Moolenaar break; 1483d3aac291SBram Moolenaar default: // Cannot reach here 1484d3aac291SBram Moolenaar goto failed; 1485d3aac291SBram Moolenaar } 1486d3aac291SBram Moolenaar di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE); 14870bbf722aSBram Moolenaar 14888a7d6542SBram Moolenaar if (di == NULL) 14898a7d6542SBram Moolenaar { 14907517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1491451c2e35SBram Moolenaar semsg(_(e_undefined_variable_char_str), 1492d3aac291SBram Moolenaar namespace, iptr->isn_arg.string); 1493f0b9f43cSBram Moolenaar goto on_error; 14948a7d6542SBram Moolenaar } 14958a7d6542SBram Moolenaar else 14968a7d6542SBram Moolenaar { 1497270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 14988a7d6542SBram Moolenaar goto failed; 14998a7d6542SBram Moolenaar copy_tv(&di->di_tv, STACK_TV_BOT(0)); 15008a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 15018a7d6542SBram Moolenaar } 15028a7d6542SBram Moolenaar } 15038a7d6542SBram Moolenaar break; 15048a7d6542SBram Moolenaar 150503290b84SBram Moolenaar // load autoload variable 150603290b84SBram Moolenaar case ISN_LOADAUTO: 150703290b84SBram Moolenaar { 150803290b84SBram Moolenaar char_u *name = iptr->isn_arg.string; 150903290b84SBram Moolenaar 151003290b84SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 151103290b84SBram Moolenaar goto failed; 151203290b84SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 151303290b84SBram Moolenaar if (eval_variable(name, STRLEN(name), 151403290b84SBram Moolenaar STACK_TV_BOT(0), NULL, TRUE, FALSE) == FAIL) 151503290b84SBram Moolenaar goto on_error; 151603290b84SBram Moolenaar ++ectx.ec_stack.ga_len; 151703290b84SBram Moolenaar } 151803290b84SBram Moolenaar break; 151903290b84SBram Moolenaar 15202f8ce0aeSBram Moolenaar // load g:/b:/w:/t: namespace 15212f8ce0aeSBram Moolenaar case ISN_LOADGDICT: 15222f8ce0aeSBram Moolenaar case ISN_LOADBDICT: 15232f8ce0aeSBram Moolenaar case ISN_LOADWDICT: 15242f8ce0aeSBram Moolenaar case ISN_LOADTDICT: 15252f8ce0aeSBram Moolenaar { 15262f8ce0aeSBram Moolenaar dict_T *d = NULL; 15272f8ce0aeSBram Moolenaar 15282f8ce0aeSBram Moolenaar switch (iptr->isn_type) 15292f8ce0aeSBram Moolenaar { 1530682d0a15SBram Moolenaar case ISN_LOADGDICT: d = get_globvar_dict(); break; 1531682d0a15SBram Moolenaar case ISN_LOADBDICT: d = curbuf->b_vars; break; 1532682d0a15SBram Moolenaar case ISN_LOADWDICT: d = curwin->w_vars; break; 1533682d0a15SBram Moolenaar case ISN_LOADTDICT: d = curtab->tp_vars; break; 15342f8ce0aeSBram Moolenaar default: // Cannot reach here 15352f8ce0aeSBram Moolenaar goto failed; 15362f8ce0aeSBram Moolenaar } 15372f8ce0aeSBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 15382f8ce0aeSBram Moolenaar goto failed; 15392f8ce0aeSBram Moolenaar tv = STACK_TV_BOT(0); 15402f8ce0aeSBram Moolenaar tv->v_type = VAR_DICT; 15412f8ce0aeSBram Moolenaar tv->v_lock = 0; 15422f8ce0aeSBram Moolenaar tv->vval.v_dict = d; 15432f8ce0aeSBram Moolenaar ++ectx.ec_stack.ga_len; 15442f8ce0aeSBram Moolenaar } 15452f8ce0aeSBram Moolenaar break; 15462f8ce0aeSBram Moolenaar 15478a7d6542SBram Moolenaar // load &option 15488a7d6542SBram Moolenaar case ISN_LOADOPT: 15498a7d6542SBram Moolenaar { 15508a7d6542SBram Moolenaar typval_T optval; 15518a7d6542SBram Moolenaar char_u *name = iptr->isn_arg.string; 15528a7d6542SBram Moolenaar 1553a8c17704SBram Moolenaar // This is not expected to fail, name is checked during 1554a8c17704SBram Moolenaar // compilation: don't set SOURCING_LNUM. 1555270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 15568a7d6542SBram Moolenaar goto failed; 15579a78e6dfSBram Moolenaar if (eval_option(&name, &optval, TRUE) == FAIL) 155858ceca5cSBram Moolenaar goto failed; 15598a7d6542SBram Moolenaar *STACK_TV_BOT(0) = optval; 15608a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 15618a7d6542SBram Moolenaar } 15628a7d6542SBram Moolenaar break; 15638a7d6542SBram Moolenaar 15648a7d6542SBram Moolenaar // load $ENV 15658a7d6542SBram Moolenaar case ISN_LOADENV: 15668a7d6542SBram Moolenaar { 15678a7d6542SBram Moolenaar typval_T optval; 15688a7d6542SBram Moolenaar char_u *name = iptr->isn_arg.string; 15698a7d6542SBram Moolenaar 1570270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 15718a7d6542SBram Moolenaar goto failed; 15720bbf722aSBram Moolenaar // name is always valid, checked when compiling 15739a78e6dfSBram Moolenaar (void)eval_env_var(&name, &optval, TRUE); 15748a7d6542SBram Moolenaar *STACK_TV_BOT(0) = optval; 15758a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 15768a7d6542SBram Moolenaar } 15778a7d6542SBram Moolenaar break; 15788a7d6542SBram Moolenaar 15798a7d6542SBram Moolenaar // load @register 15808a7d6542SBram Moolenaar case ISN_LOADREG: 1581270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 15828a7d6542SBram Moolenaar goto failed; 15838a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 15848a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 15852f8ce0aeSBram Moolenaar tv->v_lock = 0; 15861e021e63SBram Moolenaar // This may result in NULL, which should be equivalent to an 15871e021e63SBram Moolenaar // empty string. 15888a7d6542SBram Moolenaar tv->vval.v_string = get_reg_contents( 15898a7d6542SBram Moolenaar iptr->isn_arg.number, GREG_EXPR_SRC); 15908a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 15918a7d6542SBram Moolenaar break; 15928a7d6542SBram Moolenaar 15938a7d6542SBram Moolenaar // store local variable 15948a7d6542SBram Moolenaar case ISN_STORE: 15958a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 15968a7d6542SBram Moolenaar tv = STACK_TV_VAR(iptr->isn_arg.number); 15978a7d6542SBram Moolenaar clear_tv(tv); 15988a7d6542SBram Moolenaar *tv = *STACK_TV_BOT(0); 15998a7d6542SBram Moolenaar break; 16008a7d6542SBram Moolenaar 1601b68b346eSBram Moolenaar // store variable or argument in outer scope 1602b68b346eSBram Moolenaar case ISN_STOREOUTER: 1603b68b346eSBram Moolenaar --ectx.ec_stack.ga_len; 1604b68b346eSBram Moolenaar tv = STACK_OUT_TV_VAR(iptr->isn_arg.number); 1605b68b346eSBram Moolenaar clear_tv(tv); 1606b68b346eSBram Moolenaar *tv = *STACK_TV_BOT(0); 1607b68b346eSBram Moolenaar break; 1608b68b346eSBram Moolenaar 1609b283a8a6SBram Moolenaar // store s: variable in old script 1610b283a8a6SBram Moolenaar case ISN_STORES: 1611b283a8a6SBram Moolenaar { 1612b283a8a6SBram Moolenaar hashtab_T *ht = &SCRIPT_VARS( 1613b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 1614b283a8a6SBram Moolenaar char_u *name = iptr->isn_arg.loadstore.ls_name; 16150bbf722aSBram Moolenaar dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE); 1616b283a8a6SBram Moolenaar 1617b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 16180bbf722aSBram Moolenaar if (di == NULL) 16195deeb3f1SBram Moolenaar store_var(name, STACK_TV_BOT(0)); 16200bbf722aSBram Moolenaar else 16210bbf722aSBram Moolenaar { 1622b283a8a6SBram Moolenaar clear_tv(&di->di_tv); 1623b283a8a6SBram Moolenaar di->di_tv = *STACK_TV_BOT(0); 1624b283a8a6SBram Moolenaar } 16250bbf722aSBram Moolenaar } 1626b283a8a6SBram Moolenaar break; 1627b283a8a6SBram Moolenaar 1628b283a8a6SBram Moolenaar // store script-local variable in Vim9 script 16298a7d6542SBram Moolenaar case ISN_STORESCRIPT: 16308a7d6542SBram Moolenaar { 16314aab88d9SBram Moolenaar scriptref_T *sref = iptr->isn_arg.script.scriptref; 16324aab88d9SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 16334aab88d9SBram Moolenaar + ectx.ec_dfunc_idx; 16344aab88d9SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid); 16354aab88d9SBram Moolenaar svar_T *sv; 16368a7d6542SBram Moolenaar 16374aab88d9SBram Moolenaar if (sref->sref_seq != si->sn_script_seq) 16384aab88d9SBram Moolenaar { 16394aab88d9SBram Moolenaar // The script was reloaded after the function was 16404aab88d9SBram Moolenaar // compiled, the script_idx may not be valid. 16414aab88d9SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 16424aab88d9SBram Moolenaar semsg(_(e_script_variable_invalid_after_reload_in_function_str), 16434aab88d9SBram Moolenaar dfunc->df_ufunc->uf_name_exp); 16444aab88d9SBram Moolenaar goto failed; 16454aab88d9SBram Moolenaar } 16464aab88d9SBram Moolenaar sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx; 16478a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 16488a7d6542SBram Moolenaar clear_tv(sv->sv_tv); 16498a7d6542SBram Moolenaar *sv->sv_tv = *STACK_TV_BOT(0); 16508a7d6542SBram Moolenaar } 16518a7d6542SBram Moolenaar break; 16528a7d6542SBram Moolenaar 16538a7d6542SBram Moolenaar // store option 16548a7d6542SBram Moolenaar case ISN_STOREOPT: 16558a7d6542SBram Moolenaar { 16568a7d6542SBram Moolenaar long n = 0; 16578a7d6542SBram Moolenaar char_u *s = NULL; 16588a7d6542SBram Moolenaar char *msg; 16598a7d6542SBram Moolenaar 16608a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 16618a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 16628a7d6542SBram Moolenaar if (tv->v_type == VAR_STRING) 166397a2af39SBram Moolenaar { 16648a7d6542SBram Moolenaar s = tv->vval.v_string; 166597a2af39SBram Moolenaar if (s == NULL) 166697a2af39SBram Moolenaar s = (char_u *)""; 166797a2af39SBram Moolenaar } 16688a7d6542SBram Moolenaar else 1669a6e67e4fSBram Moolenaar // must be VAR_NUMBER, CHECKTYPE makes sure 1670a6e67e4fSBram Moolenaar n = tv->vval.v_number; 16718a7d6542SBram Moolenaar msg = set_option_value(iptr->isn_arg.storeopt.so_name, 16728a7d6542SBram Moolenaar n, s, iptr->isn_arg.storeopt.so_flags); 1673e75ba268SBram Moolenaar clear_tv(tv); 16748a7d6542SBram Moolenaar if (msg != NULL) 16758a7d6542SBram Moolenaar { 16767517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 16778a7d6542SBram Moolenaar emsg(_(msg)); 1678e859312eSBram Moolenaar goto on_error; 16798a7d6542SBram Moolenaar } 16808a7d6542SBram Moolenaar } 16818a7d6542SBram Moolenaar break; 16828a7d6542SBram Moolenaar 1683b283a8a6SBram Moolenaar // store $ENV 1684b283a8a6SBram Moolenaar case ISN_STOREENV: 1685b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 168620431c9dSBram Moolenaar tv = STACK_TV_BOT(0); 168720431c9dSBram Moolenaar vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv)); 168820431c9dSBram Moolenaar clear_tv(tv); 1689b283a8a6SBram Moolenaar break; 1690b283a8a6SBram Moolenaar 1691b283a8a6SBram Moolenaar // store @r 1692b283a8a6SBram Moolenaar case ISN_STOREREG: 1693b283a8a6SBram Moolenaar { 1694b283a8a6SBram Moolenaar int reg = iptr->isn_arg.number; 1695b283a8a6SBram Moolenaar 1696b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 1697401d9ffbSBram Moolenaar tv = STACK_TV_BOT(0); 1698b283a8a6SBram Moolenaar write_reg_contents(reg == '@' ? '"' : reg, 1699401d9ffbSBram Moolenaar tv_get_string(tv), -1, FALSE); 1700401d9ffbSBram Moolenaar clear_tv(tv); 1701b283a8a6SBram Moolenaar } 1702b283a8a6SBram Moolenaar break; 1703b283a8a6SBram Moolenaar 1704b283a8a6SBram Moolenaar // store v: variable 1705b283a8a6SBram Moolenaar case ISN_STOREV: 1706b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 1707b283a8a6SBram Moolenaar if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0)) 1708b283a8a6SBram Moolenaar == FAIL) 1709e859312eSBram Moolenaar // should not happen, type is checked when compiling 1710e859312eSBram Moolenaar goto on_error; 1711b283a8a6SBram Moolenaar break; 1712b283a8a6SBram Moolenaar 1713d3aac291SBram Moolenaar // store g:/b:/w:/t: variable 17148a7d6542SBram Moolenaar case ISN_STOREG: 1715d3aac291SBram Moolenaar case ISN_STOREB: 1716d3aac291SBram Moolenaar case ISN_STOREW: 1717d3aac291SBram Moolenaar case ISN_STORET: 17188a7d6542SBram Moolenaar { 17198a7d6542SBram Moolenaar dictitem_T *di; 1720d3aac291SBram Moolenaar hashtab_T *ht; 17213bdc90b7SBram Moolenaar char_u *name = iptr->isn_arg.string + 2; 17223bdc90b7SBram Moolenaar 1723d3aac291SBram Moolenaar switch (iptr->isn_type) 1724d3aac291SBram Moolenaar { 1725d3aac291SBram Moolenaar case ISN_STOREG: 1726d3aac291SBram Moolenaar ht = get_globvar_ht(); 1727d3aac291SBram Moolenaar break; 1728d3aac291SBram Moolenaar case ISN_STOREB: 1729d3aac291SBram Moolenaar ht = &curbuf->b_vars->dv_hashtab; 1730d3aac291SBram Moolenaar break; 1731d3aac291SBram Moolenaar case ISN_STOREW: 1732d3aac291SBram Moolenaar ht = &curwin->w_vars->dv_hashtab; 1733d3aac291SBram Moolenaar break; 1734d3aac291SBram Moolenaar case ISN_STORET: 1735d3aac291SBram Moolenaar ht = &curtab->tp_vars->dv_hashtab; 1736d3aac291SBram Moolenaar break; 1737d3aac291SBram Moolenaar default: // Cannot reach here 1738d3aac291SBram Moolenaar goto failed; 1739d3aac291SBram Moolenaar } 17408a7d6542SBram Moolenaar 17418a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 17423bdc90b7SBram Moolenaar di = find_var_in_ht(ht, 0, name, TRUE); 17438a7d6542SBram Moolenaar if (di == NULL) 17440bbf722aSBram Moolenaar store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); 17458a7d6542SBram Moolenaar else 17468a7d6542SBram Moolenaar { 17473bdc90b7SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 17483bdc90b7SBram Moolenaar if (var_check_permission(di, name) == FAIL) 17493bdc90b7SBram Moolenaar goto on_error; 17508a7d6542SBram Moolenaar clear_tv(&di->di_tv); 17518a7d6542SBram Moolenaar di->di_tv = *STACK_TV_BOT(0); 17528a7d6542SBram Moolenaar } 17538a7d6542SBram Moolenaar } 17548a7d6542SBram Moolenaar break; 17558a7d6542SBram Moolenaar 175603290b84SBram Moolenaar // store an autoload variable 175703290b84SBram Moolenaar case ISN_STOREAUTO: 175803290b84SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 175903290b84SBram Moolenaar set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE); 176003290b84SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 176103290b84SBram Moolenaar --ectx.ec_stack.ga_len; 176203290b84SBram Moolenaar break; 176303290b84SBram Moolenaar 17648a7d6542SBram Moolenaar // store number in local variable 17658a7d6542SBram Moolenaar case ISN_STORENR: 1766a471eeaeSBram Moolenaar tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx); 17678a7d6542SBram Moolenaar clear_tv(tv); 17688a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 1769a471eeaeSBram Moolenaar tv->vval.v_number = iptr->isn_arg.storenr.stnr_val; 17708a7d6542SBram Moolenaar break; 17718a7d6542SBram Moolenaar 17724f5e3977SBram Moolenaar // store value in list or dict variable 17734f5e3977SBram Moolenaar case ISN_STOREINDEX: 17741cc2a94fSBram Moolenaar { 17754f5e3977SBram Moolenaar vartype_T dest_type = iptr->isn_arg.vartype; 17761cc2a94fSBram Moolenaar typval_T *tv_idx = STACK_TV_BOT(-2); 17774f5e3977SBram Moolenaar typval_T *tv_dest = STACK_TV_BOT(-1); 17784f5e3977SBram Moolenaar int status = OK; 17791cc2a94fSBram Moolenaar 17804f5e3977SBram Moolenaar tv = STACK_TV_BOT(-3); 17810b4c66c6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 17824f5e3977SBram Moolenaar if (dest_type == VAR_ANY) 17834f5e3977SBram Moolenaar { 17844f5e3977SBram Moolenaar dest_type = tv_dest->v_type; 17854f5e3977SBram Moolenaar if (dest_type == VAR_DICT) 17864f5e3977SBram Moolenaar status = do_2string(tv_idx, TRUE); 17874f5e3977SBram Moolenaar else if (dest_type == VAR_LIST 17884f5e3977SBram Moolenaar && tv_idx->v_type != VAR_NUMBER) 17894f5e3977SBram Moolenaar { 17904f5e3977SBram Moolenaar emsg(_(e_number_exp)); 17914f5e3977SBram Moolenaar status = FAIL; 17924f5e3977SBram Moolenaar } 17934f5e3977SBram Moolenaar } 17944f5e3977SBram Moolenaar else if (dest_type != tv_dest->v_type) 17954f5e3977SBram Moolenaar { 17964f5e3977SBram Moolenaar // just in case, should be OK 17974f5e3977SBram Moolenaar semsg(_(e_expected_str_but_got_str), 17984f5e3977SBram Moolenaar vartype_name(dest_type), 17994f5e3977SBram Moolenaar vartype_name(tv_dest->v_type)); 18004f5e3977SBram Moolenaar status = FAIL; 18014f5e3977SBram Moolenaar } 18024f5e3977SBram Moolenaar 18034f5e3977SBram Moolenaar if (status == OK && dest_type == VAR_LIST) 18044f5e3977SBram Moolenaar { 18054f5e3977SBram Moolenaar varnumber_T lidx = tv_idx->vval.v_number; 18064f5e3977SBram Moolenaar list_T *list = tv_dest->vval.v_list; 18074f5e3977SBram Moolenaar 18084f5e3977SBram Moolenaar if (list == NULL) 18094f5e3977SBram Moolenaar { 18104f5e3977SBram Moolenaar emsg(_(e_list_not_set)); 18114f5e3977SBram Moolenaar goto on_error; 18124f5e3977SBram Moolenaar } 18131cc2a94fSBram Moolenaar if (lidx < 0 && list->lv_len + lidx >= 0) 18141cc2a94fSBram Moolenaar // negative index is relative to the end 18151cc2a94fSBram Moolenaar lidx = list->lv_len + lidx; 18161cc2a94fSBram Moolenaar if (lidx < 0 || lidx > list->lv_len) 18171cc2a94fSBram Moolenaar { 18181cc2a94fSBram Moolenaar semsg(_(e_listidx), lidx); 1819e859312eSBram Moolenaar goto on_error; 18201cc2a94fSBram Moolenaar } 18211cc2a94fSBram Moolenaar if (lidx < list->lv_len) 18221cc2a94fSBram Moolenaar { 18231cc2a94fSBram Moolenaar listitem_T *li = list_find(list, lidx); 18241cc2a94fSBram Moolenaar 18250b4c66c6SBram Moolenaar if (error_if_locked(li->li_tv.v_lock, 18260b4c66c6SBram Moolenaar e_cannot_change_list_item)) 18274f5e3977SBram Moolenaar goto on_error; 18281cc2a94fSBram Moolenaar // overwrite existing list item 18291cc2a94fSBram Moolenaar clear_tv(&li->li_tv); 18301cc2a94fSBram Moolenaar li->li_tv = *tv; 18311cc2a94fSBram Moolenaar } 18321cc2a94fSBram Moolenaar else 18331cc2a94fSBram Moolenaar { 18340b4c66c6SBram Moolenaar if (error_if_locked(list->lv_lock, 18350b4c66c6SBram Moolenaar e_cannot_change_list)) 18364f5e3977SBram Moolenaar goto on_error; 1837e859312eSBram Moolenaar // append to list, only fails when out of memory 18381cc2a94fSBram Moolenaar if (list_append_tv(list, tv) == FAIL) 18391cc2a94fSBram Moolenaar goto failed; 18401cc2a94fSBram Moolenaar clear_tv(tv); 18411cc2a94fSBram Moolenaar } 18421cc2a94fSBram Moolenaar } 18434f5e3977SBram Moolenaar else if (status == OK && dest_type == VAR_DICT) 18441cc2a94fSBram Moolenaar { 18454f5e3977SBram Moolenaar char_u *key = tv_idx->vval.v_string; 18464f5e3977SBram Moolenaar dict_T *dict = tv_dest->vval.v_dict; 18471cc2a94fSBram Moolenaar dictitem_T *di; 18481cc2a94fSBram Moolenaar 18490b4c66c6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 18508e4c8c85SBram Moolenaar if (dict == NULL) 18518e4c8c85SBram Moolenaar { 1852bc4c5051SBram Moolenaar emsg(_(e_dictionary_not_set)); 18538e4c8c85SBram Moolenaar goto on_error; 18548e4c8c85SBram Moolenaar } 185558626872SBram Moolenaar if (key == NULL) 185658626872SBram Moolenaar key = (char_u *)""; 18571cc2a94fSBram Moolenaar di = dict_find(dict, key, -1); 18581cc2a94fSBram Moolenaar if (di != NULL) 18591cc2a94fSBram Moolenaar { 18600b4c66c6SBram Moolenaar if (error_if_locked(di->di_tv.v_lock, 18610b4c66c6SBram Moolenaar e_cannot_change_dict_item)) 18624f5e3977SBram Moolenaar goto on_error; 1863e859312eSBram Moolenaar // overwrite existing value 18641cc2a94fSBram Moolenaar clear_tv(&di->di_tv); 18651cc2a94fSBram Moolenaar di->di_tv = *tv; 18661cc2a94fSBram Moolenaar } 18671cc2a94fSBram Moolenaar else 18681cc2a94fSBram Moolenaar { 18690b4c66c6SBram Moolenaar if (error_if_locked(dict->dv_lock, 18700b4c66c6SBram Moolenaar e_cannot_change_dict)) 18714f5e3977SBram Moolenaar goto on_error; 1872e859312eSBram Moolenaar // add to dict, only fails when out of memory 18731cc2a94fSBram Moolenaar if (dict_add_tv(dict, (char *)key, tv) == FAIL) 18741cc2a94fSBram Moolenaar goto failed; 18751cc2a94fSBram Moolenaar clear_tv(tv); 18761cc2a94fSBram Moolenaar } 18774f5e3977SBram Moolenaar } 18784f5e3977SBram Moolenaar else 18794f5e3977SBram Moolenaar { 18804f5e3977SBram Moolenaar status = FAIL; 18814f5e3977SBram Moolenaar semsg(_(e_cannot_index_str), vartype_name(dest_type)); 18824f5e3977SBram Moolenaar } 18834f5e3977SBram Moolenaar 18844f5e3977SBram Moolenaar clear_tv(tv_idx); 18854f5e3977SBram Moolenaar clear_tv(tv_dest); 1886f163bd5eSBram Moolenaar ectx.ec_stack.ga_len -= 3; 18874f5e3977SBram Moolenaar if (status == FAIL) 18884f5e3977SBram Moolenaar { 18894f5e3977SBram Moolenaar clear_tv(tv); 18904f5e3977SBram Moolenaar goto on_error; 18914f5e3977SBram Moolenaar } 18921cc2a94fSBram Moolenaar } 18931cc2a94fSBram Moolenaar break; 18941cc2a94fSBram Moolenaar 18958a7d6542SBram Moolenaar // push constant 18968a7d6542SBram Moolenaar case ISN_PUSHNR: 18978a7d6542SBram Moolenaar case ISN_PUSHBOOL: 18988a7d6542SBram Moolenaar case ISN_PUSHSPEC: 18998a7d6542SBram Moolenaar case ISN_PUSHF: 19008a7d6542SBram Moolenaar case ISN_PUSHS: 19018a7d6542SBram Moolenaar case ISN_PUSHBLOB: 190242a480bfSBram Moolenaar case ISN_PUSHFUNC: 190342a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 190442a480bfSBram Moolenaar case ISN_PUSHJOB: 1905270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 19068a7d6542SBram Moolenaar goto failed; 19078a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 19082f8ce0aeSBram Moolenaar tv->v_lock = 0; 19098a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 19108a7d6542SBram Moolenaar switch (iptr->isn_type) 19118a7d6542SBram Moolenaar { 19128a7d6542SBram Moolenaar case ISN_PUSHNR: 19138a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 19148a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 19158a7d6542SBram Moolenaar break; 19168a7d6542SBram Moolenaar case ISN_PUSHBOOL: 19178a7d6542SBram Moolenaar tv->v_type = VAR_BOOL; 19188a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 19198a7d6542SBram Moolenaar break; 19208a7d6542SBram Moolenaar case ISN_PUSHSPEC: 19218a7d6542SBram Moolenaar tv->v_type = VAR_SPECIAL; 19228a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 19238a7d6542SBram Moolenaar break; 19248a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 19258a7d6542SBram Moolenaar case ISN_PUSHF: 19268a7d6542SBram Moolenaar tv->v_type = VAR_FLOAT; 19278a7d6542SBram Moolenaar tv->vval.v_float = iptr->isn_arg.fnumber; 19288a7d6542SBram Moolenaar break; 19298a7d6542SBram Moolenaar #endif 19308a7d6542SBram Moolenaar case ISN_PUSHBLOB: 19318a7d6542SBram Moolenaar blob_copy(iptr->isn_arg.blob, tv); 19328a7d6542SBram Moolenaar break; 193342a480bfSBram Moolenaar case ISN_PUSHFUNC: 193442a480bfSBram Moolenaar tv->v_type = VAR_FUNC; 1935087d2e15SBram Moolenaar if (iptr->isn_arg.string == NULL) 1936087d2e15SBram Moolenaar tv->vval.v_string = NULL; 1937087d2e15SBram Moolenaar else 1938087d2e15SBram Moolenaar tv->vval.v_string = 1939087d2e15SBram Moolenaar vim_strsave(iptr->isn_arg.string); 194042a480bfSBram Moolenaar break; 194142a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 194242a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 194342a480bfSBram Moolenaar tv->v_type = VAR_CHANNEL; 194442a480bfSBram Moolenaar tv->vval.v_channel = iptr->isn_arg.channel; 194542a480bfSBram Moolenaar if (tv->vval.v_channel != NULL) 194642a480bfSBram Moolenaar ++tv->vval.v_channel->ch_refcount; 194742a480bfSBram Moolenaar #endif 194842a480bfSBram Moolenaar break; 194942a480bfSBram Moolenaar case ISN_PUSHJOB: 195042a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 195142a480bfSBram Moolenaar tv->v_type = VAR_JOB; 195242a480bfSBram Moolenaar tv->vval.v_job = iptr->isn_arg.job; 195342a480bfSBram Moolenaar if (tv->vval.v_job != NULL) 195442a480bfSBram Moolenaar ++tv->vval.v_job->jv_refcount; 195542a480bfSBram Moolenaar #endif 195642a480bfSBram Moolenaar break; 19578a7d6542SBram Moolenaar default: 19588a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 1959e69f6d04SBram Moolenaar tv->vval.v_string = vim_strsave( 1960e69f6d04SBram Moolenaar iptr->isn_arg.string == NULL 1961e69f6d04SBram Moolenaar ? (char_u *)"" : iptr->isn_arg.string); 19628a7d6542SBram Moolenaar } 19638a7d6542SBram Moolenaar break; 19648a7d6542SBram Moolenaar 1965d72c1bf0SBram Moolenaar case ISN_UNLET: 1966d72c1bf0SBram Moolenaar if (do_unlet(iptr->isn_arg.unlet.ul_name, 1967d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_forceit) == FAIL) 1968e859312eSBram Moolenaar goto on_error; 1969d72c1bf0SBram Moolenaar break; 19707bdaea6eSBram Moolenaar case ISN_UNLETENV: 19717bdaea6eSBram Moolenaar vim_unsetenv(iptr->isn_arg.unlet.ul_name); 19727bdaea6eSBram Moolenaar break; 1973d72c1bf0SBram Moolenaar 19740b4c66c6SBram Moolenaar case ISN_LOCKCONST: 19750b4c66c6SBram Moolenaar item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE); 19760b4c66c6SBram Moolenaar break; 19770b4c66c6SBram Moolenaar 19788a7d6542SBram Moolenaar // create a list from items on the stack; uses a single allocation 19798a7d6542SBram Moolenaar // for the list header and the items 19808a7d6542SBram Moolenaar case ISN_NEWLIST: 1981fe270817SBram Moolenaar if (exe_newlist(iptr->isn_arg.number, &ectx) == FAIL) 19828a7d6542SBram Moolenaar goto failed; 19838a7d6542SBram Moolenaar break; 19848a7d6542SBram Moolenaar 19858a7d6542SBram Moolenaar // create a dict from items on the stack 19868a7d6542SBram Moolenaar case ISN_NEWDICT: 19878a7d6542SBram Moolenaar { 19888a7d6542SBram Moolenaar int count = iptr->isn_arg.number; 19898a7d6542SBram Moolenaar dict_T *dict = dict_alloc(); 19908a7d6542SBram Moolenaar dictitem_T *item; 1991c7f7f6dbSBram Moolenaar char_u *key; 19928a7d6542SBram Moolenaar 19938a7d6542SBram Moolenaar if (dict == NULL) 19948a7d6542SBram Moolenaar goto failed; 19958a7d6542SBram Moolenaar for (idx = 0; idx < count; ++idx) 19968a7d6542SBram Moolenaar { 1997e859312eSBram Moolenaar // have already checked key type is VAR_STRING 19988a7d6542SBram Moolenaar tv = STACK_TV_BOT(2 * (idx - count)); 1999e859312eSBram Moolenaar // check key is unique 2000c7f7f6dbSBram Moolenaar key = tv->vval.v_string == NULL 2001c7f7f6dbSBram Moolenaar ? (char_u *)"" : tv->vval.v_string; 2002c7f7f6dbSBram Moolenaar item = dict_find(dict, key, -1); 2003e859312eSBram Moolenaar if (item != NULL) 2004e859312eSBram Moolenaar { 20057517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2006c7f7f6dbSBram Moolenaar semsg(_(e_duplicate_key), key); 2007e859312eSBram Moolenaar dict_unref(dict); 2008e859312eSBram Moolenaar goto on_error; 2009e859312eSBram Moolenaar } 2010c7f7f6dbSBram Moolenaar item = dictitem_alloc(key); 20118a7d6542SBram Moolenaar clear_tv(tv); 20128a7d6542SBram Moolenaar if (item == NULL) 2013e859312eSBram Moolenaar { 2014e859312eSBram Moolenaar dict_unref(dict); 20158a7d6542SBram Moolenaar goto failed; 2016e859312eSBram Moolenaar } 20178a7d6542SBram Moolenaar item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); 20188a7d6542SBram Moolenaar item->di_tv.v_lock = 0; 20198a7d6542SBram Moolenaar if (dict_add(dict, item) == FAIL) 2020e859312eSBram Moolenaar { 2021d032f34aSBram Moolenaar // can this ever happen? 2022e859312eSBram Moolenaar dict_unref(dict); 20238a7d6542SBram Moolenaar goto failed; 20248a7d6542SBram Moolenaar } 2025e859312eSBram Moolenaar } 20268a7d6542SBram Moolenaar 20278a7d6542SBram Moolenaar if (count > 0) 20288a7d6542SBram Moolenaar ectx.ec_stack.ga_len -= 2 * count - 1; 2029270d0388SBram Moolenaar else if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 20308a7d6542SBram Moolenaar goto failed; 20318a7d6542SBram Moolenaar else 20328a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 20338a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 20348a7d6542SBram Moolenaar tv->v_type = VAR_DICT; 20352f8ce0aeSBram Moolenaar tv->v_lock = 0; 20368a7d6542SBram Moolenaar tv->vval.v_dict = dict; 20378a7d6542SBram Moolenaar ++dict->dv_refcount; 20388a7d6542SBram Moolenaar } 20398a7d6542SBram Moolenaar break; 20408a7d6542SBram Moolenaar 20418a7d6542SBram Moolenaar // call a :def function 20428a7d6542SBram Moolenaar case ISN_DCALL: 2043dfa3d552SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 20448a7d6542SBram Moolenaar if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx, 20458a7d6542SBram Moolenaar iptr->isn_arg.dfunc.cdf_argcount, 20468a7d6542SBram Moolenaar &ectx) == FAIL) 2047e859312eSBram Moolenaar goto on_error; 20488a7d6542SBram Moolenaar break; 20498a7d6542SBram Moolenaar 20508a7d6542SBram Moolenaar // call a builtin function 20518a7d6542SBram Moolenaar case ISN_BCALL: 20528a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 20538a7d6542SBram Moolenaar if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx, 20548a7d6542SBram Moolenaar iptr->isn_arg.bfunc.cbf_argcount, 20558a7d6542SBram Moolenaar &ectx) == FAIL) 2056d032f34aSBram Moolenaar goto on_error; 20578a7d6542SBram Moolenaar break; 20588a7d6542SBram Moolenaar 20598a7d6542SBram Moolenaar // call a funcref or partial 20608a7d6542SBram Moolenaar case ISN_PCALL: 20618a7d6542SBram Moolenaar { 20628a7d6542SBram Moolenaar cpfunc_T *pfunc = &iptr->isn_arg.pfunc; 20638a7d6542SBram Moolenaar int r; 20646f5b6dfbSBram Moolenaar typval_T partial_tv; 20658a7d6542SBram Moolenaar 20668a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 20678a7d6542SBram Moolenaar if (pfunc->cpf_top) 20688a7d6542SBram Moolenaar { 20698a7d6542SBram Moolenaar // funcref is above the arguments 20708a7d6542SBram Moolenaar tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1); 20718a7d6542SBram Moolenaar } 20728a7d6542SBram Moolenaar else 20738a7d6542SBram Moolenaar { 20748a7d6542SBram Moolenaar // Get the funcref from the stack. 20758a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 20766f5b6dfbSBram Moolenaar partial_tv = *STACK_TV_BOT(0); 20776f5b6dfbSBram Moolenaar tv = &partial_tv; 20788a7d6542SBram Moolenaar } 20798a7d6542SBram Moolenaar r = call_partial(tv, pfunc->cpf_argcount, &ectx); 20806f5b6dfbSBram Moolenaar if (tv == &partial_tv) 20816f5b6dfbSBram Moolenaar clear_tv(&partial_tv); 20828a7d6542SBram Moolenaar if (r == FAIL) 2083d032f34aSBram Moolenaar goto on_error; 2084bd5da371SBram Moolenaar } 2085bd5da371SBram Moolenaar break; 20868a7d6542SBram Moolenaar 2087bd5da371SBram Moolenaar case ISN_PCALL_END: 2088bd5da371SBram Moolenaar // PCALL finished, arguments have been consumed and replaced by 2089bd5da371SBram Moolenaar // the return value. Now clear the funcref from the stack, 2090bd5da371SBram Moolenaar // and move the return value in its place. 20918a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 2092bd5da371SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 20938a7d6542SBram Moolenaar *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); 20948a7d6542SBram Moolenaar break; 20958a7d6542SBram Moolenaar 20968a7d6542SBram Moolenaar // call a user defined function or funcref/partial 20978a7d6542SBram Moolenaar case ISN_UCALL: 20988a7d6542SBram Moolenaar { 20998a7d6542SBram Moolenaar cufunc_T *cufunc = &iptr->isn_arg.ufunc; 21008a7d6542SBram Moolenaar 21018a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 21028a7d6542SBram Moolenaar if (call_eval_func(cufunc->cuf_name, 21037eeefd4aSBram Moolenaar cufunc->cuf_argcount, &ectx, iptr) == FAIL) 2104d032f34aSBram Moolenaar goto on_error; 21058a7d6542SBram Moolenaar } 21068a7d6542SBram Moolenaar break; 21078a7d6542SBram Moolenaar 21088a7d6542SBram Moolenaar // return from a :def function call 21098a7d6542SBram Moolenaar case ISN_RETURN: 21108a7d6542SBram Moolenaar { 21118cbd6dfcSBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 211220431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 21138cbd6dfcSBram Moolenaar 21148cbd6dfcSBram Moolenaar if (trystack->ga_len > 0) 21158cbd6dfcSBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 21168cbd6dfcSBram Moolenaar + trystack->ga_len - 1; 2117bf67ea1aSBram Moolenaar if (trycmd != NULL 2118bf67ea1aSBram Moolenaar && trycmd->tcd_frame_idx == ectx.ec_frame_idx 21198a7d6542SBram Moolenaar && trycmd->tcd_finally_idx != 0) 21208a7d6542SBram Moolenaar { 21218a7d6542SBram Moolenaar // jump to ":finally" 21228a7d6542SBram Moolenaar ectx.ec_iidx = trycmd->tcd_finally_idx; 21238a7d6542SBram Moolenaar trycmd->tcd_return = TRUE; 21248a7d6542SBram Moolenaar } 21258a7d6542SBram Moolenaar else 2126d032f34aSBram Moolenaar goto func_return; 21278a7d6542SBram Moolenaar } 21288a7d6542SBram Moolenaar break; 21298a7d6542SBram Moolenaar 21308a7d6542SBram Moolenaar // push a function reference to a compiled function 21318a7d6542SBram Moolenaar case ISN_FUNCREF: 21328a7d6542SBram Moolenaar { 2133f112f30aSBram Moolenaar partial_T *pt = ALLOC_CLEAR_ONE(partial_T); 2134f112f30aSBram Moolenaar dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data) 2135f112f30aSBram Moolenaar + iptr->isn_arg.funcref.fr_func; 21368a7d6542SBram Moolenaar 21378a7d6542SBram Moolenaar if (pt == NULL) 21388a7d6542SBram Moolenaar goto failed; 2139270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 2140c8cd2b34SBram Moolenaar { 2141bf67ea1aSBram Moolenaar vim_free(pt); 2142bf67ea1aSBram Moolenaar goto failed; 2143bf67ea1aSBram Moolenaar } 2144f112f30aSBram Moolenaar if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc, 2145f112f30aSBram Moolenaar &ectx) == FAIL) 2146bf67ea1aSBram Moolenaar goto failed; 2147c8cd2b34SBram Moolenaar 21488a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 21498a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 21508a7d6542SBram Moolenaar tv->vval.v_partial = pt; 21518a7d6542SBram Moolenaar tv->v_type = VAR_PARTIAL; 21522f8ce0aeSBram Moolenaar tv->v_lock = 0; 21538a7d6542SBram Moolenaar } 21548a7d6542SBram Moolenaar break; 21558a7d6542SBram Moolenaar 215638ddf333SBram Moolenaar // Create a global function from a lambda. 215738ddf333SBram Moolenaar case ISN_NEWFUNC: 215838ddf333SBram Moolenaar { 215938ddf333SBram Moolenaar newfunc_T *newfunc = &iptr->isn_arg.newfunc; 216038ddf333SBram Moolenaar 2161cd45ed03SBram Moolenaar if (copy_func(newfunc->nf_lambda, newfunc->nf_global, 2162f112f30aSBram Moolenaar &ectx) == FAIL) 2163f112f30aSBram Moolenaar goto failed; 216438ddf333SBram Moolenaar } 216538ddf333SBram Moolenaar break; 216638ddf333SBram Moolenaar 21676abdcf82SBram Moolenaar // List functions 21686abdcf82SBram Moolenaar case ISN_DEF: 21696abdcf82SBram Moolenaar if (iptr->isn_arg.string == NULL) 21706abdcf82SBram Moolenaar list_functions(NULL); 21716abdcf82SBram Moolenaar else 21726abdcf82SBram Moolenaar { 21736abdcf82SBram Moolenaar exarg_T ea; 21746abdcf82SBram Moolenaar 21756abdcf82SBram Moolenaar CLEAR_FIELD(ea); 21766abdcf82SBram Moolenaar ea.cmd = ea.arg = iptr->isn_arg.string; 21776abdcf82SBram Moolenaar define_function(&ea, NULL); 21786abdcf82SBram Moolenaar } 21796abdcf82SBram Moolenaar break; 21806abdcf82SBram Moolenaar 21818a7d6542SBram Moolenaar // jump if a condition is met 21828a7d6542SBram Moolenaar case ISN_JUMP: 21838a7d6542SBram Moolenaar { 21848a7d6542SBram Moolenaar jumpwhen_T when = iptr->isn_arg.jump.jump_when; 21852bb2658bSBram Moolenaar int error = FALSE; 21868a7d6542SBram Moolenaar int jump = TRUE; 21878a7d6542SBram Moolenaar 21888a7d6542SBram Moolenaar if (when != JUMP_ALWAYS) 21898a7d6542SBram Moolenaar { 21908a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 21912bb2658bSBram Moolenaar if (when == JUMP_IF_COND_FALSE 219213106605SBram Moolenaar || when == JUMP_IF_FALSE 21932bb2658bSBram Moolenaar || when == JUMP_IF_COND_TRUE) 21942bb2658bSBram Moolenaar { 21952bb2658bSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 21962bb2658bSBram Moolenaar jump = tv_get_bool_chk(tv, &error); 21972bb2658bSBram Moolenaar if (error) 21982bb2658bSBram Moolenaar goto on_error; 21992bb2658bSBram Moolenaar } 22002bb2658bSBram Moolenaar else 22018a7d6542SBram Moolenaar jump = tv2bool(tv); 22028a7d6542SBram Moolenaar if (when == JUMP_IF_FALSE 22032bb2658bSBram Moolenaar || when == JUMP_AND_KEEP_IF_FALSE 22042bb2658bSBram Moolenaar || when == JUMP_IF_COND_FALSE) 22058a7d6542SBram Moolenaar jump = !jump; 2206777770fbSBram Moolenaar if (when == JUMP_IF_FALSE || !jump) 22078a7d6542SBram Moolenaar { 22088a7d6542SBram Moolenaar // drop the value from the stack 22098a7d6542SBram Moolenaar clear_tv(tv); 22108a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 22118a7d6542SBram Moolenaar } 22128a7d6542SBram Moolenaar } 22138a7d6542SBram Moolenaar if (jump) 22148a7d6542SBram Moolenaar ectx.ec_iidx = iptr->isn_arg.jump.jump_where; 22158a7d6542SBram Moolenaar } 22168a7d6542SBram Moolenaar break; 22178a7d6542SBram Moolenaar 22188a7d6542SBram Moolenaar // top of a for loop 22198a7d6542SBram Moolenaar case ISN_FOR: 22208a7d6542SBram Moolenaar { 22218a7d6542SBram Moolenaar list_T *list = STACK_TV_BOT(-1)->vval.v_list; 22228a7d6542SBram Moolenaar typval_T *idxtv = 22238a7d6542SBram Moolenaar STACK_TV_VAR(iptr->isn_arg.forloop.for_idx); 22248a7d6542SBram Moolenaar 22258a7d6542SBram Moolenaar // push the next item from the list 2226270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 22278a7d6542SBram Moolenaar goto failed; 222877e5dcc3SBram Moolenaar ++idxtv->vval.v_number; 222977e5dcc3SBram Moolenaar if (list == NULL || idxtv->vval.v_number >= list->lv_len) 22308a7d6542SBram Moolenaar // past the end of the list, jump to "endfor" 22318a7d6542SBram Moolenaar ectx.ec_iidx = iptr->isn_arg.forloop.for_end; 22328a7d6542SBram Moolenaar else if (list->lv_first == &range_list_item) 22338a7d6542SBram Moolenaar { 22348a7d6542SBram Moolenaar // non-materialized range() list 22358a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 22368a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 22372f8ce0aeSBram Moolenaar tv->v_lock = 0; 22388a7d6542SBram Moolenaar tv->vval.v_number = list_find_nr( 22398a7d6542SBram Moolenaar list, idxtv->vval.v_number, NULL); 22408a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 22418a7d6542SBram Moolenaar } 22428a7d6542SBram Moolenaar else 22438a7d6542SBram Moolenaar { 22448a7d6542SBram Moolenaar listitem_T *li = list_find(list, idxtv->vval.v_number); 22458a7d6542SBram Moolenaar 22468a7d6542SBram Moolenaar copy_tv(&li->li_tv, STACK_TV_BOT(0)); 22478a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 22488a7d6542SBram Moolenaar } 22498a7d6542SBram Moolenaar } 22508a7d6542SBram Moolenaar break; 22518a7d6542SBram Moolenaar 22528a7d6542SBram Moolenaar // start of ":try" block 22538a7d6542SBram Moolenaar case ISN_TRY: 22548a7d6542SBram Moolenaar { 225520431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 225620431c9dSBram Moolenaar 2257270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_trystack, 1) == FAIL) 22588a7d6542SBram Moolenaar goto failed; 22598a7d6542SBram Moolenaar trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data) 22608a7d6542SBram Moolenaar + ectx.ec_trystack.ga_len; 22618a7d6542SBram Moolenaar ++ectx.ec_trystack.ga_len; 22628a7d6542SBram Moolenaar ++trylevel; 2263bf67ea1aSBram Moolenaar trycmd->tcd_frame_idx = ectx.ec_frame_idx; 22648a7d6542SBram Moolenaar trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch; 22658a7d6542SBram Moolenaar trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally; 2266f575adffSBram Moolenaar trycmd->tcd_caught = FALSE; 22679939f57bSBram Moolenaar trycmd->tcd_return = FALSE; 22688a7d6542SBram Moolenaar } 22698a7d6542SBram Moolenaar break; 22708a7d6542SBram Moolenaar 22718a7d6542SBram Moolenaar case ISN_PUSHEXC: 22728a7d6542SBram Moolenaar if (current_exception == NULL) 22738a7d6542SBram Moolenaar { 22747517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 22758a7d6542SBram Moolenaar iemsg("Evaluating catch while current_exception is NULL"); 22768a7d6542SBram Moolenaar goto failed; 22778a7d6542SBram Moolenaar } 2278270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 22798a7d6542SBram Moolenaar goto failed; 22808a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 22818a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 22828a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 22832f8ce0aeSBram Moolenaar tv->v_lock = 0; 22848a7d6542SBram Moolenaar tv->vval.v_string = vim_strsave( 22858a7d6542SBram Moolenaar (char_u *)current_exception->value); 22868a7d6542SBram Moolenaar break; 22878a7d6542SBram Moolenaar 22888a7d6542SBram Moolenaar case ISN_CATCH: 22898a7d6542SBram Moolenaar { 22908a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 22918a7d6542SBram Moolenaar 229220a76298SBram Moolenaar if (restore_cmdmod) 229320a76298SBram Moolenaar { 229420a76298SBram Moolenaar cmdmod.cmod_filter_regmatch.regprog = NULL; 229520a76298SBram Moolenaar undo_cmdmod(&cmdmod); 229620a76298SBram Moolenaar cmdmod = save_cmdmod; 229720a76298SBram Moolenaar restore_cmdmod = FALSE; 229820a76298SBram Moolenaar } 22998a7d6542SBram Moolenaar if (trystack->ga_len > 0) 23008a7d6542SBram Moolenaar { 230120431c9dSBram Moolenaar trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data) 23028a7d6542SBram Moolenaar + trystack->ga_len - 1; 23038a7d6542SBram Moolenaar trycmd->tcd_caught = TRUE; 23048a7d6542SBram Moolenaar } 23058a7d6542SBram Moolenaar did_emsg = got_int = did_throw = FALSE; 23068a7d6542SBram Moolenaar catch_exception(current_exception); 23078a7d6542SBram Moolenaar } 23088a7d6542SBram Moolenaar break; 23098a7d6542SBram Moolenaar 23108a7d6542SBram Moolenaar // end of ":try" block 23118a7d6542SBram Moolenaar case ISN_ENDTRY: 23128a7d6542SBram Moolenaar { 23138a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 23148a7d6542SBram Moolenaar 23158a7d6542SBram Moolenaar if (trystack->ga_len > 0) 23168a7d6542SBram Moolenaar { 231720431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 231820431c9dSBram Moolenaar 23198a7d6542SBram Moolenaar --trystack->ga_len; 23208a7d6542SBram Moolenaar --trylevel; 232168d130c6SBram Moolenaar ectx.ec_in_catch = FALSE; 23228a7d6542SBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 23238a7d6542SBram Moolenaar + trystack->ga_len; 2324f575adffSBram Moolenaar if (trycmd->tcd_caught && current_exception != NULL) 23258a7d6542SBram Moolenaar { 23268a7d6542SBram Moolenaar // discard the exception 23278a7d6542SBram Moolenaar if (caught_stack == current_exception) 23288a7d6542SBram Moolenaar caught_stack = caught_stack->caught; 23298a7d6542SBram Moolenaar discard_current_exception(); 23308a7d6542SBram Moolenaar } 23318a7d6542SBram Moolenaar 23328a7d6542SBram Moolenaar if (trycmd->tcd_return) 2333d032f34aSBram Moolenaar goto func_return; 23348a7d6542SBram Moolenaar } 23358a7d6542SBram Moolenaar } 23368a7d6542SBram Moolenaar break; 23378a7d6542SBram Moolenaar 23388a7d6542SBram Moolenaar case ISN_THROW: 23398a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 23408a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 23411e021e63SBram Moolenaar if (tv->vval.v_string == NULL 23421e021e63SBram Moolenaar || *skipwhite(tv->vval.v_string) == NUL) 23431e021e63SBram Moolenaar { 2344335e6713SBram Moolenaar vim_free(tv->vval.v_string); 23451dcae599SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 23461e021e63SBram Moolenaar emsg(_(e_throw_with_empty_string)); 23471e021e63SBram Moolenaar goto failed; 23481e021e63SBram Moolenaar } 23491e021e63SBram Moolenaar 23508a7d6542SBram Moolenaar if (throw_exception(tv->vval.v_string, ET_USER, NULL) == FAIL) 23518a7d6542SBram Moolenaar { 23528a7d6542SBram Moolenaar vim_free(tv->vval.v_string); 23538a7d6542SBram Moolenaar goto failed; 23548a7d6542SBram Moolenaar } 23558a7d6542SBram Moolenaar did_throw = TRUE; 23568a7d6542SBram Moolenaar break; 23578a7d6542SBram Moolenaar 23588a7d6542SBram Moolenaar // compare with special values 23598a7d6542SBram Moolenaar case ISN_COMPAREBOOL: 23608a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 23618a7d6542SBram Moolenaar { 23628a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 23638a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 23648a7d6542SBram Moolenaar varnumber_T arg1 = tv1->vval.v_number; 23658a7d6542SBram Moolenaar varnumber_T arg2 = tv2->vval.v_number; 23668a7d6542SBram Moolenaar int res; 23678a7d6542SBram Moolenaar 23688a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 23698a7d6542SBram Moolenaar { 23708a7d6542SBram Moolenaar case EXPR_EQUAL: res = arg1 == arg2; break; 23718a7d6542SBram Moolenaar case EXPR_NEQUAL: res = arg1 != arg2; break; 23728a7d6542SBram Moolenaar default: res = 0; break; 23738a7d6542SBram Moolenaar } 23748a7d6542SBram Moolenaar 23758a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 23768a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 23778a7d6542SBram Moolenaar tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; 23788a7d6542SBram Moolenaar } 23798a7d6542SBram Moolenaar break; 23808a7d6542SBram Moolenaar 23818a7d6542SBram Moolenaar // Operation with two number arguments 23828a7d6542SBram Moolenaar case ISN_OPNR: 23838a7d6542SBram Moolenaar case ISN_COMPARENR: 23848a7d6542SBram Moolenaar { 23858a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 23868a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 23878a7d6542SBram Moolenaar varnumber_T arg1 = tv1->vval.v_number; 23888a7d6542SBram Moolenaar varnumber_T arg2 = tv2->vval.v_number; 23898a7d6542SBram Moolenaar varnumber_T res; 23908a7d6542SBram Moolenaar 23918a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 23928a7d6542SBram Moolenaar { 23938a7d6542SBram Moolenaar case EXPR_MULT: res = arg1 * arg2; break; 23948a7d6542SBram Moolenaar case EXPR_DIV: res = arg1 / arg2; break; 23958a7d6542SBram Moolenaar case EXPR_REM: res = arg1 % arg2; break; 23968a7d6542SBram Moolenaar case EXPR_SUB: res = arg1 - arg2; break; 23978a7d6542SBram Moolenaar case EXPR_ADD: res = arg1 + arg2; break; 23988a7d6542SBram Moolenaar 23998a7d6542SBram Moolenaar case EXPR_EQUAL: res = arg1 == arg2; break; 24008a7d6542SBram Moolenaar case EXPR_NEQUAL: res = arg1 != arg2; break; 24018a7d6542SBram Moolenaar case EXPR_GREATER: res = arg1 > arg2; break; 24028a7d6542SBram Moolenaar case EXPR_GEQUAL: res = arg1 >= arg2; break; 24038a7d6542SBram Moolenaar case EXPR_SMALLER: res = arg1 < arg2; break; 24048a7d6542SBram Moolenaar case EXPR_SEQUAL: res = arg1 <= arg2; break; 24058a7d6542SBram Moolenaar default: res = 0; break; 24068a7d6542SBram Moolenaar } 24078a7d6542SBram Moolenaar 24088a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 24098a7d6542SBram Moolenaar if (iptr->isn_type == ISN_COMPARENR) 24108a7d6542SBram Moolenaar { 24118a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 24128a7d6542SBram Moolenaar tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; 24138a7d6542SBram Moolenaar } 24148a7d6542SBram Moolenaar else 24158a7d6542SBram Moolenaar tv1->vval.v_number = res; 24168a7d6542SBram Moolenaar } 24178a7d6542SBram Moolenaar break; 24188a7d6542SBram Moolenaar 24198a7d6542SBram Moolenaar // Computation with two float arguments 24208a7d6542SBram Moolenaar case ISN_OPFLOAT: 24218a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: 2422a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT 24238a7d6542SBram Moolenaar { 24248a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 24258a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 24268a7d6542SBram Moolenaar float_T arg1 = tv1->vval.v_float; 24278a7d6542SBram Moolenaar float_T arg2 = tv2->vval.v_float; 24288a7d6542SBram Moolenaar float_T res = 0; 24298a7d6542SBram Moolenaar int cmp = FALSE; 24308a7d6542SBram Moolenaar 24318a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 24328a7d6542SBram Moolenaar { 24338a7d6542SBram Moolenaar case EXPR_MULT: res = arg1 * arg2; break; 24348a7d6542SBram Moolenaar case EXPR_DIV: res = arg1 / arg2; break; 24358a7d6542SBram Moolenaar case EXPR_SUB: res = arg1 - arg2; break; 24368a7d6542SBram Moolenaar case EXPR_ADD: res = arg1 + arg2; break; 24378a7d6542SBram Moolenaar 24388a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = arg1 == arg2; break; 24398a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = arg1 != arg2; break; 24408a7d6542SBram Moolenaar case EXPR_GREATER: cmp = arg1 > arg2; break; 24418a7d6542SBram Moolenaar case EXPR_GEQUAL: cmp = arg1 >= arg2; break; 24428a7d6542SBram Moolenaar case EXPR_SMALLER: cmp = arg1 < arg2; break; 24438a7d6542SBram Moolenaar case EXPR_SEQUAL: cmp = arg1 <= arg2; break; 24448a7d6542SBram Moolenaar default: cmp = 0; break; 24458a7d6542SBram Moolenaar } 24468a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 24478a7d6542SBram Moolenaar if (iptr->isn_type == ISN_COMPAREFLOAT) 24488a7d6542SBram Moolenaar { 24498a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 24508a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 24518a7d6542SBram Moolenaar } 24528a7d6542SBram Moolenaar else 24538a7d6542SBram Moolenaar tv1->vval.v_float = res; 24548a7d6542SBram Moolenaar } 2455a5d5953dSBram Moolenaar #endif 24568a7d6542SBram Moolenaar break; 24578a7d6542SBram Moolenaar 24588a7d6542SBram Moolenaar case ISN_COMPARELIST: 24598a7d6542SBram Moolenaar { 24608a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 24618a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 24628a7d6542SBram Moolenaar list_T *arg1 = tv1->vval.v_list; 24638a7d6542SBram Moolenaar list_T *arg2 = tv2->vval.v_list; 24648a7d6542SBram Moolenaar int cmp = FALSE; 24658a7d6542SBram Moolenaar int ic = iptr->isn_arg.op.op_ic; 24668a7d6542SBram Moolenaar 24678a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 24688a7d6542SBram Moolenaar { 24698a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = 24708a7d6542SBram Moolenaar list_equal(arg1, arg2, ic, FALSE); break; 24718a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = 24728a7d6542SBram Moolenaar !list_equal(arg1, arg2, ic, FALSE); break; 24738a7d6542SBram Moolenaar case EXPR_IS: cmp = arg1 == arg2; break; 24748a7d6542SBram Moolenaar case EXPR_ISNOT: cmp = arg1 != arg2; break; 24758a7d6542SBram Moolenaar default: cmp = 0; break; 24768a7d6542SBram Moolenaar } 24778a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 24788a7d6542SBram Moolenaar clear_tv(tv1); 24798a7d6542SBram Moolenaar clear_tv(tv2); 24808a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 24818a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 24828a7d6542SBram Moolenaar } 24838a7d6542SBram Moolenaar break; 24848a7d6542SBram Moolenaar 24858a7d6542SBram Moolenaar case ISN_COMPAREBLOB: 24868a7d6542SBram Moolenaar { 24878a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 24888a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 24898a7d6542SBram Moolenaar blob_T *arg1 = tv1->vval.v_blob; 24908a7d6542SBram Moolenaar blob_T *arg2 = tv2->vval.v_blob; 24918a7d6542SBram Moolenaar int cmp = FALSE; 24928a7d6542SBram Moolenaar 24938a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 24948a7d6542SBram Moolenaar { 24958a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break; 24968a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break; 24978a7d6542SBram Moolenaar case EXPR_IS: cmp = arg1 == arg2; break; 24988a7d6542SBram Moolenaar case EXPR_ISNOT: cmp = arg1 != arg2; break; 24998a7d6542SBram Moolenaar default: cmp = 0; break; 25008a7d6542SBram Moolenaar } 25018a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 25028a7d6542SBram Moolenaar clear_tv(tv1); 25038a7d6542SBram Moolenaar clear_tv(tv2); 25048a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 25058a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 25068a7d6542SBram Moolenaar } 25078a7d6542SBram Moolenaar break; 25088a7d6542SBram Moolenaar 25098a7d6542SBram Moolenaar // TODO: handle separately 25108a7d6542SBram Moolenaar case ISN_COMPARESTRING: 25118a7d6542SBram Moolenaar case ISN_COMPAREDICT: 25128a7d6542SBram Moolenaar case ISN_COMPAREFUNC: 25138a7d6542SBram Moolenaar case ISN_COMPAREANY: 25148a7d6542SBram Moolenaar { 25158a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 25168a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 25178a7d6542SBram Moolenaar exptype_T exptype = iptr->isn_arg.op.op_type; 25188a7d6542SBram Moolenaar int ic = iptr->isn_arg.op.op_ic; 25198a7d6542SBram Moolenaar 2520eb26f433SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 25218a7d6542SBram Moolenaar typval_compare(tv1, tv2, exptype, ic); 25228a7d6542SBram Moolenaar clear_tv(tv2); 25238a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 25248a7d6542SBram Moolenaar } 25258a7d6542SBram Moolenaar break; 25268a7d6542SBram Moolenaar 25278a7d6542SBram Moolenaar case ISN_ADDLIST: 25288a7d6542SBram Moolenaar case ISN_ADDBLOB: 25298a7d6542SBram Moolenaar { 25308a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 25318a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 25328a7d6542SBram Moolenaar 25331dcae599SBram Moolenaar // add two lists or blobs 25348a7d6542SBram Moolenaar if (iptr->isn_type == ISN_ADDLIST) 25358a7d6542SBram Moolenaar eval_addlist(tv1, tv2); 25368a7d6542SBram Moolenaar else 25378a7d6542SBram Moolenaar eval_addblob(tv1, tv2); 25388a7d6542SBram Moolenaar clear_tv(tv2); 25398a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 25408a7d6542SBram Moolenaar } 25418a7d6542SBram Moolenaar break; 25428a7d6542SBram Moolenaar 25431dcae599SBram Moolenaar case ISN_LISTAPPEND: 25441dcae599SBram Moolenaar { 25451dcae599SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 25461dcae599SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 25471dcae599SBram Moolenaar list_T *l = tv1->vval.v_list; 25481dcae599SBram Moolenaar 25491dcae599SBram Moolenaar // add an item to a list 25501dcae599SBram Moolenaar if (l == NULL) 25511dcae599SBram Moolenaar { 25521dcae599SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 25531dcae599SBram Moolenaar emsg(_(e_cannot_add_to_null_list)); 25541dcae599SBram Moolenaar goto on_error; 25551dcae599SBram Moolenaar } 25561dcae599SBram Moolenaar if (list_append_tv(l, tv2) == FAIL) 25571dcae599SBram Moolenaar goto failed; 2558955347ccSBram Moolenaar clear_tv(tv2); 25591dcae599SBram Moolenaar --ectx.ec_stack.ga_len; 25601dcae599SBram Moolenaar } 25611dcae599SBram Moolenaar break; 25621dcae599SBram Moolenaar 256380b0e5eaSBram Moolenaar case ISN_BLOBAPPEND: 256480b0e5eaSBram Moolenaar { 256580b0e5eaSBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 256680b0e5eaSBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 256780b0e5eaSBram Moolenaar blob_T *b = tv1->vval.v_blob; 256880b0e5eaSBram Moolenaar int error = FALSE; 256980b0e5eaSBram Moolenaar varnumber_T n; 257080b0e5eaSBram Moolenaar 257180b0e5eaSBram Moolenaar // add a number to a blob 257280b0e5eaSBram Moolenaar if (b == NULL) 257380b0e5eaSBram Moolenaar { 257480b0e5eaSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 257580b0e5eaSBram Moolenaar emsg(_(e_cannot_add_to_null_blob)); 257680b0e5eaSBram Moolenaar goto on_error; 257780b0e5eaSBram Moolenaar } 257880b0e5eaSBram Moolenaar n = tv_get_number_chk(tv2, &error); 257980b0e5eaSBram Moolenaar if (error) 258080b0e5eaSBram Moolenaar goto on_error; 258180b0e5eaSBram Moolenaar ga_append(&b->bv_ga, (int)n); 258280b0e5eaSBram Moolenaar --ectx.ec_stack.ga_len; 258380b0e5eaSBram Moolenaar } 258480b0e5eaSBram Moolenaar break; 258580b0e5eaSBram Moolenaar 25868a7d6542SBram Moolenaar // Computation with two arguments of unknown type 25878a7d6542SBram Moolenaar case ISN_OPANY: 25888a7d6542SBram Moolenaar { 25898a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 25908a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 25918a7d6542SBram Moolenaar varnumber_T n1, n2; 25928a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 25938a7d6542SBram Moolenaar float_T f1 = 0, f2 = 0; 25948a7d6542SBram Moolenaar #endif 25958a7d6542SBram Moolenaar int error = FALSE; 25968a7d6542SBram Moolenaar 25978a7d6542SBram Moolenaar if (iptr->isn_arg.op.op_type == EXPR_ADD) 25988a7d6542SBram Moolenaar { 25998a7d6542SBram Moolenaar if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST) 26008a7d6542SBram Moolenaar { 26018a7d6542SBram Moolenaar eval_addlist(tv1, tv2); 26028a7d6542SBram Moolenaar clear_tv(tv2); 26038a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 26048a7d6542SBram Moolenaar break; 26058a7d6542SBram Moolenaar } 26068a7d6542SBram Moolenaar else if (tv1->v_type == VAR_BLOB 26078a7d6542SBram Moolenaar && tv2->v_type == VAR_BLOB) 26088a7d6542SBram Moolenaar { 26098a7d6542SBram Moolenaar eval_addblob(tv1, tv2); 26108a7d6542SBram Moolenaar clear_tv(tv2); 26118a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 26128a7d6542SBram Moolenaar break; 26138a7d6542SBram Moolenaar } 26148a7d6542SBram Moolenaar } 26158a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 26168a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT) 26178a7d6542SBram Moolenaar { 26188a7d6542SBram Moolenaar f1 = tv1->vval.v_float; 26198a7d6542SBram Moolenaar n1 = 0; 26208a7d6542SBram Moolenaar } 26218a7d6542SBram Moolenaar else 26228a7d6542SBram Moolenaar #endif 26238a7d6542SBram Moolenaar { 2624f665e97fSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 26258a7d6542SBram Moolenaar n1 = tv_get_number_chk(tv1, &error); 26268a7d6542SBram Moolenaar if (error) 2627d032f34aSBram Moolenaar goto on_error; 26288a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 26298a7d6542SBram Moolenaar if (tv2->v_type == VAR_FLOAT) 26308a7d6542SBram Moolenaar f1 = n1; 26318a7d6542SBram Moolenaar #endif 26328a7d6542SBram Moolenaar } 26338a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 26348a7d6542SBram Moolenaar if (tv2->v_type == VAR_FLOAT) 26358a7d6542SBram Moolenaar { 26368a7d6542SBram Moolenaar f2 = tv2->vval.v_float; 26378a7d6542SBram Moolenaar n2 = 0; 26388a7d6542SBram Moolenaar } 26398a7d6542SBram Moolenaar else 26408a7d6542SBram Moolenaar #endif 26418a7d6542SBram Moolenaar { 26428a7d6542SBram Moolenaar n2 = tv_get_number_chk(tv2, &error); 26438a7d6542SBram Moolenaar if (error) 2644d032f34aSBram Moolenaar goto on_error; 26458a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 26468a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT) 26478a7d6542SBram Moolenaar f2 = n2; 26488a7d6542SBram Moolenaar #endif 26498a7d6542SBram Moolenaar } 26508a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 26518a7d6542SBram Moolenaar // if there is a float on either side the result is a float 26528a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT) 26538a7d6542SBram Moolenaar { 26548a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 26558a7d6542SBram Moolenaar { 26568a7d6542SBram Moolenaar case EXPR_MULT: f1 = f1 * f2; break; 26578a7d6542SBram Moolenaar case EXPR_DIV: f1 = f1 / f2; break; 26588a7d6542SBram Moolenaar case EXPR_SUB: f1 = f1 - f2; break; 26598a7d6542SBram Moolenaar case EXPR_ADD: f1 = f1 + f2; break; 26607517ffdbSBram Moolenaar default: SOURCING_LNUM = iptr->isn_lnum; 26617517ffdbSBram Moolenaar emsg(_(e_modulus)); 2662f0b9f43cSBram Moolenaar goto on_error; 26638a7d6542SBram Moolenaar } 26648a7d6542SBram Moolenaar clear_tv(tv1); 26658a7d6542SBram Moolenaar clear_tv(tv2); 26668a7d6542SBram Moolenaar tv1->v_type = VAR_FLOAT; 26678a7d6542SBram Moolenaar tv1->vval.v_float = f1; 26688a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 26698a7d6542SBram Moolenaar } 26708a7d6542SBram Moolenaar else 26718a7d6542SBram Moolenaar #endif 26728a7d6542SBram Moolenaar { 26738a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 26748a7d6542SBram Moolenaar { 26758a7d6542SBram Moolenaar case EXPR_MULT: n1 = n1 * n2; break; 26768a7d6542SBram Moolenaar case EXPR_DIV: n1 = num_divide(n1, n2); break; 26778a7d6542SBram Moolenaar case EXPR_SUB: n1 = n1 - n2; break; 26788a7d6542SBram Moolenaar case EXPR_ADD: n1 = n1 + n2; break; 26798a7d6542SBram Moolenaar default: n1 = num_modulus(n1, n2); break; 26808a7d6542SBram Moolenaar } 26818a7d6542SBram Moolenaar clear_tv(tv1); 26828a7d6542SBram Moolenaar clear_tv(tv2); 26838a7d6542SBram Moolenaar tv1->v_type = VAR_NUMBER; 26848a7d6542SBram Moolenaar tv1->vval.v_number = n1; 26858a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 26868a7d6542SBram Moolenaar } 26878a7d6542SBram Moolenaar } 26888a7d6542SBram Moolenaar break; 26898a7d6542SBram Moolenaar 26908a7d6542SBram Moolenaar case ISN_CONCAT: 26918a7d6542SBram Moolenaar { 26928a7d6542SBram Moolenaar char_u *str1 = STACK_TV_BOT(-2)->vval.v_string; 26938a7d6542SBram Moolenaar char_u *str2 = STACK_TV_BOT(-1)->vval.v_string; 26948a7d6542SBram Moolenaar char_u *res; 26958a7d6542SBram Moolenaar 26968a7d6542SBram Moolenaar res = concat_str(str1, str2); 26978a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(-2)); 26988a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 26998a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 27008a7d6542SBram Moolenaar STACK_TV_BOT(-1)->vval.v_string = res; 27018a7d6542SBram Moolenaar } 27028a7d6542SBram Moolenaar break; 27038a7d6542SBram Moolenaar 2704bf9d8c37SBram Moolenaar case ISN_STRINDEX: 270511107babSBram Moolenaar case ISN_STRSLICE: 2706bf9d8c37SBram Moolenaar { 270711107babSBram Moolenaar int is_slice = iptr->isn_type == ISN_STRSLICE; 270811107babSBram Moolenaar varnumber_T n1 = 0, n2; 2709bf9d8c37SBram Moolenaar char_u *res; 2710bf9d8c37SBram Moolenaar 2711bf9d8c37SBram Moolenaar // string index: string is at stack-2, index at stack-1 271211107babSBram Moolenaar // string slice: string is at stack-3, first index at 271311107babSBram Moolenaar // stack-2, second index at stack-1 271411107babSBram Moolenaar if (is_slice) 271511107babSBram Moolenaar { 271611107babSBram Moolenaar tv = STACK_TV_BOT(-2); 271711107babSBram Moolenaar n1 = tv->vval.v_number; 271811107babSBram Moolenaar } 271911107babSBram Moolenaar 2720bf9d8c37SBram Moolenaar tv = STACK_TV_BOT(-1); 272111107babSBram Moolenaar n2 = tv->vval.v_number; 2722bf9d8c37SBram Moolenaar 272311107babSBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 2724bf9d8c37SBram Moolenaar tv = STACK_TV_BOT(-1); 272511107babSBram Moolenaar if (is_slice) 272611107babSBram Moolenaar // Slice: Select the characters from the string 272711107babSBram Moolenaar res = string_slice(tv->vval.v_string, n1, n2); 272811107babSBram Moolenaar else 272911107babSBram Moolenaar // Index: The resulting variable is a string of a 273011107babSBram Moolenaar // single character. If the index is too big or 273111107babSBram Moolenaar // negative the result is empty. 273211107babSBram Moolenaar res = char_from_string(tv->vval.v_string, n2); 2733bf9d8c37SBram Moolenaar vim_free(tv->vval.v_string); 2734bf9d8c37SBram Moolenaar tv->vval.v_string = res; 2735bf9d8c37SBram Moolenaar } 2736bf9d8c37SBram Moolenaar break; 2737bf9d8c37SBram Moolenaar 2738bf9d8c37SBram Moolenaar case ISN_LISTINDEX: 2739ed591877SBram Moolenaar case ISN_LISTSLICE: 27408a7d6542SBram Moolenaar { 2741ed591877SBram Moolenaar int is_slice = iptr->isn_type == ISN_LISTSLICE; 27428a7d6542SBram Moolenaar list_T *list; 2743ed591877SBram Moolenaar varnumber_T n1, n2; 27448a7d6542SBram Moolenaar 27458a7d6542SBram Moolenaar // list index: list is at stack-2, index at stack-1 2746ed591877SBram Moolenaar // list slice: list is at stack-3, indexes at stack-2 and 2747ed591877SBram Moolenaar // stack-1 2748ed591877SBram Moolenaar tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); 27498a7d6542SBram Moolenaar list = tv->vval.v_list; 27508a7d6542SBram Moolenaar 27518a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 2752ed591877SBram Moolenaar n1 = n2 = tv->vval.v_number; 27538a7d6542SBram Moolenaar clear_tv(tv); 2754ed591877SBram Moolenaar 2755ed591877SBram Moolenaar if (is_slice) 2756ed591877SBram Moolenaar { 2757ed591877SBram Moolenaar tv = STACK_TV_BOT(-2); 2758ed591877SBram Moolenaar n1 = tv->vval.v_number; 2759ed591877SBram Moolenaar clear_tv(tv); 2760ed591877SBram Moolenaar } 2761ed591877SBram Moolenaar 2762ed591877SBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 2763435d8978SBram Moolenaar tv = STACK_TV_BOT(-1); 27641d634542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2765ed591877SBram Moolenaar if (list_slice_or_index(list, is_slice, n1, n2, tv, TRUE) 2766ed591877SBram Moolenaar == FAIL) 2767ed591877SBram Moolenaar goto on_error; 27688a7d6542SBram Moolenaar } 27698a7d6542SBram Moolenaar break; 27708a7d6542SBram Moolenaar 2771cc673e74SBram Moolenaar case ISN_ANYINDEX: 2772cc673e74SBram Moolenaar case ISN_ANYSLICE: 2773cc673e74SBram Moolenaar { 2774cc673e74SBram Moolenaar int is_slice = iptr->isn_type == ISN_ANYSLICE; 2775cc673e74SBram Moolenaar typval_T *var1, *var2; 2776cc673e74SBram Moolenaar int res; 2777cc673e74SBram Moolenaar 2778cc673e74SBram Moolenaar // index: composite is at stack-2, index at stack-1 2779cc673e74SBram Moolenaar // slice: composite is at stack-3, indexes at stack-2 and 2780cc673e74SBram Moolenaar // stack-1 2781cc673e74SBram Moolenaar tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); 27823affe7a6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2783cc673e74SBram Moolenaar if (check_can_index(tv, TRUE, TRUE) == FAIL) 2784cc673e74SBram Moolenaar goto on_error; 2785cc673e74SBram Moolenaar var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1); 2786cc673e74SBram Moolenaar var2 = is_slice ? STACK_TV_BOT(-1) : NULL; 2787cc673e74SBram Moolenaar res = eval_index_inner(tv, is_slice, 2788cc673e74SBram Moolenaar var1, var2, NULL, -1, TRUE); 2789cc673e74SBram Moolenaar clear_tv(var1); 2790cc673e74SBram Moolenaar if (is_slice) 2791cc673e74SBram Moolenaar clear_tv(var2); 2792cc673e74SBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 2793cc673e74SBram Moolenaar if (res == FAIL) 2794cc673e74SBram Moolenaar goto on_error; 2795cc673e74SBram Moolenaar } 2796cc673e74SBram Moolenaar break; 2797cc673e74SBram Moolenaar 27989af78769SBram Moolenaar case ISN_SLICE: 27999af78769SBram Moolenaar { 28009af78769SBram Moolenaar list_T *list; 28019af78769SBram Moolenaar int count = iptr->isn_arg.number; 28029af78769SBram Moolenaar 2803c5b1c20bSBram Moolenaar // type will have been checked to be a list 28049af78769SBram Moolenaar tv = STACK_TV_BOT(-1); 28059af78769SBram Moolenaar list = tv->vval.v_list; 28069af78769SBram Moolenaar 28079af78769SBram Moolenaar // no error for short list, expect it to be checked earlier 28089af78769SBram Moolenaar if (list != NULL && list->lv_len >= count) 28099af78769SBram Moolenaar { 28109af78769SBram Moolenaar list_T *newlist = list_slice(list, 28119af78769SBram Moolenaar count, list->lv_len - 1); 28129af78769SBram Moolenaar 28139af78769SBram Moolenaar if (newlist != NULL) 28149af78769SBram Moolenaar { 28159af78769SBram Moolenaar list_unref(list); 28169af78769SBram Moolenaar tv->vval.v_list = newlist; 28179af78769SBram Moolenaar ++newlist->lv_refcount; 28189af78769SBram Moolenaar } 28199af78769SBram Moolenaar } 28209af78769SBram Moolenaar } 28219af78769SBram Moolenaar break; 28229af78769SBram Moolenaar 282347a519a9SBram Moolenaar case ISN_GETITEM: 282447a519a9SBram Moolenaar { 282547a519a9SBram Moolenaar listitem_T *li; 282647a519a9SBram Moolenaar int index = iptr->isn_arg.number; 282747a519a9SBram Moolenaar 2828c785b9a7SBram Moolenaar // Get list item: list is at stack-1, push item. 2829c785b9a7SBram Moolenaar // List type and length is checked for when compiling. 283047a519a9SBram Moolenaar tv = STACK_TV_BOT(-1); 2831c785b9a7SBram Moolenaar li = list_find(tv->vval.v_list, index); 283247a519a9SBram Moolenaar 283347a519a9SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 283447a519a9SBram Moolenaar goto failed; 283547a519a9SBram Moolenaar ++ectx.ec_stack.ga_len; 283647a519a9SBram Moolenaar copy_tv(&li->li_tv, STACK_TV_BOT(-1)); 283747a519a9SBram Moolenaar } 283847a519a9SBram Moolenaar break; 283947a519a9SBram Moolenaar 28408a7d6542SBram Moolenaar case ISN_MEMBER: 28418a7d6542SBram Moolenaar { 28428a7d6542SBram Moolenaar dict_T *dict; 28431cc2a94fSBram Moolenaar char_u *key; 28441cc2a94fSBram Moolenaar dictitem_T *di; 284550788ef3SBram Moolenaar typval_T temp_tv; 28461cc2a94fSBram Moolenaar 28471cc2a94fSBram Moolenaar // dict member: dict is at stack-2, key at stack-1 28481cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-2); 28494dac32caSBram Moolenaar // no need to check for VAR_DICT, CHECKTYPE will check. 28501cc2a94fSBram Moolenaar dict = tv->vval.v_dict; 28511cc2a94fSBram Moolenaar 28521cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-1); 28534dac32caSBram Moolenaar // no need to check for VAR_STRING, 2STRING will check. 28541cc2a94fSBram Moolenaar key = tv->vval.v_string; 2855086fc9a5SBram Moolenaar if (key == NULL) 2856086fc9a5SBram Moolenaar key = (char_u *)""; 28574dac32caSBram Moolenaar 28581cc2a94fSBram Moolenaar if ((di = dict_find(dict, key, -1)) == NULL) 28591cc2a94fSBram Moolenaar { 28607517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 28611cc2a94fSBram Moolenaar semsg(_(e_dictkey), key); 28624029cabbSBram Moolenaar 28634029cabbSBram Moolenaar // If :silent! is used we will continue, make sure the 28644029cabbSBram Moolenaar // stack contents makes sense. 28654029cabbSBram Moolenaar clear_tv(tv); 28664029cabbSBram Moolenaar --ectx.ec_stack.ga_len; 28674029cabbSBram Moolenaar tv = STACK_TV_BOT(-1); 28684029cabbSBram Moolenaar clear_tv(tv); 28694029cabbSBram Moolenaar tv->v_type = VAR_NUMBER; 28704029cabbSBram Moolenaar tv->vval.v_number = 0; 2871af0df47aSBram Moolenaar goto on_fatal_error; 28721cc2a94fSBram Moolenaar } 28731cc2a94fSBram Moolenaar clear_tv(tv); 287450788ef3SBram Moolenaar --ectx.ec_stack.ga_len; 2875af0df47aSBram Moolenaar // Clear the dict only after getting the item, to avoid 2876af0df47aSBram Moolenaar // that it makes the item invalid. 287750788ef3SBram Moolenaar tv = STACK_TV_BOT(-1); 287850788ef3SBram Moolenaar temp_tv = *tv; 287950788ef3SBram Moolenaar copy_tv(&di->di_tv, tv); 288050788ef3SBram Moolenaar clear_tv(&temp_tv); 28811cc2a94fSBram Moolenaar } 28821cc2a94fSBram Moolenaar break; 28831cc2a94fSBram Moolenaar 28841cc2a94fSBram Moolenaar // dict member with string key 28851cc2a94fSBram Moolenaar case ISN_STRINGMEMBER: 28861cc2a94fSBram Moolenaar { 28871cc2a94fSBram Moolenaar dict_T *dict; 28888a7d6542SBram Moolenaar dictitem_T *di; 2889fb9d5c51SBram Moolenaar typval_T temp_tv; 28908a7d6542SBram Moolenaar 28918a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 28928a7d6542SBram Moolenaar if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) 28938a7d6542SBram Moolenaar { 28947517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 28958a7d6542SBram Moolenaar emsg(_(e_dictreq)); 2896d032f34aSBram Moolenaar goto on_error; 28978a7d6542SBram Moolenaar } 28988a7d6542SBram Moolenaar dict = tv->vval.v_dict; 28998a7d6542SBram Moolenaar 29008a7d6542SBram Moolenaar if ((di = dict_find(dict, iptr->isn_arg.string, -1)) 29018a7d6542SBram Moolenaar == NULL) 29028a7d6542SBram Moolenaar { 29037517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 29048a7d6542SBram Moolenaar semsg(_(e_dictkey), iptr->isn_arg.string); 2905d032f34aSBram Moolenaar goto on_error; 29068a7d6542SBram Moolenaar } 2907fb9d5c51SBram Moolenaar // Clear the dict after getting the item, to avoid that it 2908fb9d5c51SBram Moolenaar // make the item invalid. 2909fb9d5c51SBram Moolenaar temp_tv = *tv; 29108a7d6542SBram Moolenaar copy_tv(&di->di_tv, tv); 2911fb9d5c51SBram Moolenaar clear_tv(&temp_tv); 29128a7d6542SBram Moolenaar } 29138a7d6542SBram Moolenaar break; 29148a7d6542SBram Moolenaar 29158a7d6542SBram Moolenaar case ISN_NEGATENR: 29168a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 2917c58164c5SBram Moolenaar if (tv->v_type != VAR_NUMBER 2918c58164c5SBram Moolenaar #ifdef FEAT_FLOAT 2919c58164c5SBram Moolenaar && tv->v_type != VAR_FLOAT 2920c58164c5SBram Moolenaar #endif 2921c58164c5SBram Moolenaar ) 2922c58164c5SBram Moolenaar { 29237517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2924c58164c5SBram Moolenaar emsg(_(e_number_exp)); 2925f0b9f43cSBram Moolenaar goto on_error; 2926c58164c5SBram Moolenaar } 2927c58164c5SBram Moolenaar #ifdef FEAT_FLOAT 2928c58164c5SBram Moolenaar if (tv->v_type == VAR_FLOAT) 2929c58164c5SBram Moolenaar tv->vval.v_float = -tv->vval.v_float; 2930c58164c5SBram Moolenaar else 2931c58164c5SBram Moolenaar #endif 29328a7d6542SBram Moolenaar tv->vval.v_number = -tv->vval.v_number; 29338a7d6542SBram Moolenaar break; 29348a7d6542SBram Moolenaar 29358a7d6542SBram Moolenaar case ISN_CHECKNR: 29368a7d6542SBram Moolenaar { 29378a7d6542SBram Moolenaar int error = FALSE; 29388a7d6542SBram Moolenaar 29398a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 29403affe7a6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 29418a7d6542SBram Moolenaar if (check_not_string(tv) == FAIL) 2942f0b9f43cSBram Moolenaar goto on_error; 29438a7d6542SBram Moolenaar (void)tv_get_number_chk(tv, &error); 29448a7d6542SBram Moolenaar if (error) 2945f0b9f43cSBram Moolenaar goto on_error; 29468a7d6542SBram Moolenaar } 29478a7d6542SBram Moolenaar break; 29488a7d6542SBram Moolenaar 29498a7d6542SBram Moolenaar case ISN_CHECKTYPE: 29508a7d6542SBram Moolenaar { 29518a7d6542SBram Moolenaar checktype_T *ct = &iptr->isn_arg.type; 29528a7d6542SBram Moolenaar 29538a7d6542SBram Moolenaar tv = STACK_TV_BOT(ct->ct_off); 29545e654230SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 29555e654230SBram Moolenaar if (check_typval_type(ct->ct_type, tv, 0) == FAIL) 29565e654230SBram Moolenaar goto on_error; 29575e654230SBram Moolenaar 29585e654230SBram Moolenaar // number 0 is FALSE, number 1 is TRUE 29595e654230SBram Moolenaar if (tv->v_type == VAR_NUMBER 29605e654230SBram Moolenaar && ct->ct_type->tt_type == VAR_BOOL 2961dadaddd5SBram Moolenaar && (tv->vval.v_number == 0 2962dadaddd5SBram Moolenaar || tv->vval.v_number == 1)) 2963dadaddd5SBram Moolenaar { 2964dadaddd5SBram Moolenaar tv->v_type = VAR_BOOL; 2965dadaddd5SBram Moolenaar tv->vval.v_number = tv->vval.v_number 2966dadaddd5SBram Moolenaar ? VVAL_TRUE : VVAL_FALSE; 2967dadaddd5SBram Moolenaar } 2968dadaddd5SBram Moolenaar } 29698a7d6542SBram Moolenaar break; 29708a7d6542SBram Moolenaar 29719af78769SBram Moolenaar case ISN_CHECKLEN: 29729af78769SBram Moolenaar { 29739af78769SBram Moolenaar int min_len = iptr->isn_arg.checklen.cl_min_len; 29749af78769SBram Moolenaar list_T *list = NULL; 29759af78769SBram Moolenaar 29769af78769SBram Moolenaar tv = STACK_TV_BOT(-1); 29779af78769SBram Moolenaar if (tv->v_type == VAR_LIST) 29789af78769SBram Moolenaar list = tv->vval.v_list; 29799af78769SBram Moolenaar if (list == NULL || list->lv_len < min_len 29809af78769SBram Moolenaar || (list->lv_len > min_len 29819af78769SBram Moolenaar && !iptr->isn_arg.checklen.cl_more_OK)) 29829af78769SBram Moolenaar { 29837517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2984451c2e35SBram Moolenaar semsg(_(e_expected_nr_items_but_got_nr), 29859af78769SBram Moolenaar min_len, list == NULL ? 0 : list->lv_len); 2986f0b9f43cSBram Moolenaar goto on_error; 29879af78769SBram Moolenaar } 29889af78769SBram Moolenaar } 29899af78769SBram Moolenaar break; 29909af78769SBram Moolenaar 29918a7d6542SBram Moolenaar case ISN_2BOOL: 29922bb2658bSBram Moolenaar case ISN_COND2BOOL: 29938a7d6542SBram Moolenaar { 29948a7d6542SBram Moolenaar int n; 29952bb2658bSBram Moolenaar int error = FALSE; 29968a7d6542SBram Moolenaar 29978a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 29982bb2658bSBram Moolenaar if (iptr->isn_type == ISN_2BOOL) 29992bb2658bSBram Moolenaar { 30008a7d6542SBram Moolenaar n = tv2bool(tv); 30018a7d6542SBram Moolenaar if (iptr->isn_arg.number) // invert 30028a7d6542SBram Moolenaar n = !n; 30032bb2658bSBram Moolenaar } 30042bb2658bSBram Moolenaar else 30052bb2658bSBram Moolenaar { 30062bb2658bSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 30072bb2658bSBram Moolenaar n = tv_get_bool_chk(tv, &error); 30082bb2658bSBram Moolenaar if (error) 30092bb2658bSBram Moolenaar goto on_error; 30102bb2658bSBram Moolenaar } 30118a7d6542SBram Moolenaar clear_tv(tv); 30128a7d6542SBram Moolenaar tv->v_type = VAR_BOOL; 30138a7d6542SBram Moolenaar tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE; 30148a7d6542SBram Moolenaar } 30158a7d6542SBram Moolenaar break; 30168a7d6542SBram Moolenaar 30178a7d6542SBram Moolenaar case ISN_2STRING: 3018418f1df5SBram Moolenaar case ISN_2STRING_ANY: 30194f5e3977SBram Moolenaar if (do_2string(STACK_TV_BOT(iptr->isn_arg.number), 30204f5e3977SBram Moolenaar iptr->isn_type == ISN_2STRING_ANY) == FAIL) 3021418f1df5SBram Moolenaar goto on_error; 30228a7d6542SBram Moolenaar break; 30238a7d6542SBram Moolenaar 302408597875SBram Moolenaar case ISN_RANGE: 302508597875SBram Moolenaar { 302608597875SBram Moolenaar exarg_T ea; 302708597875SBram Moolenaar char *errormsg; 302808597875SBram Moolenaar 302908597875SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 303008597875SBram Moolenaar goto failed; 303108597875SBram Moolenaar ++ectx.ec_stack.ga_len; 303208597875SBram Moolenaar tv = STACK_TV_BOT(-1); 303308597875SBram Moolenaar ea.addr_type = ADDR_LINES; 303408597875SBram Moolenaar ea.cmd = iptr->isn_arg.string; 303508597875SBram Moolenaar if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL) 303608597875SBram Moolenaar goto failed; 303708597875SBram Moolenaar if (ea.addr_count == 0) 303808597875SBram Moolenaar tv->vval.v_number = curwin->w_cursor.lnum; 303908597875SBram Moolenaar else 304008597875SBram Moolenaar tv->vval.v_number = ea.line2; 304108597875SBram Moolenaar } 304208597875SBram Moolenaar break; 304308597875SBram Moolenaar 3044c3516f7eSBram Moolenaar case ISN_PUT: 3045c3516f7eSBram Moolenaar { 3046c3516f7eSBram Moolenaar int regname = iptr->isn_arg.put.put_regname; 3047c3516f7eSBram Moolenaar linenr_T lnum = iptr->isn_arg.put.put_lnum; 3048c3516f7eSBram Moolenaar char_u *expr = NULL; 3049c3516f7eSBram Moolenaar int dir = FORWARD; 3050c3516f7eSBram Moolenaar 3051c3516f7eSBram Moolenaar if (regname == '=') 3052c3516f7eSBram Moolenaar { 3053c3516f7eSBram Moolenaar tv = STACK_TV_BOT(-1); 3054c3516f7eSBram Moolenaar if (tv->v_type == VAR_STRING) 3055c3516f7eSBram Moolenaar expr = tv->vval.v_string; 3056c3516f7eSBram Moolenaar else 3057c3516f7eSBram Moolenaar { 3058c3516f7eSBram Moolenaar expr = typval_tostring(tv); // allocates value 3059c3516f7eSBram Moolenaar clear_tv(tv); 3060c3516f7eSBram Moolenaar } 3061c3516f7eSBram Moolenaar --ectx.ec_stack.ga_len; 3062c3516f7eSBram Moolenaar } 306308597875SBram Moolenaar if (lnum < -2) 306408597875SBram Moolenaar { 306508597875SBram Moolenaar // line number was put on the stack by ISN_RANGE 306608597875SBram Moolenaar tv = STACK_TV_BOT(-1); 306708597875SBram Moolenaar curwin->w_cursor.lnum = tv->vval.v_number; 306808597875SBram Moolenaar if (lnum == LNUM_VARIABLE_RANGE_ABOVE) 306908597875SBram Moolenaar dir = BACKWARD; 307008597875SBram Moolenaar --ectx.ec_stack.ga_len; 307108597875SBram Moolenaar } 307208597875SBram Moolenaar else if (lnum == -2) 3073c3516f7eSBram Moolenaar // :put! above cursor 3074c3516f7eSBram Moolenaar dir = BACKWARD; 3075c3516f7eSBram Moolenaar else if (lnum >= 0) 3076c3516f7eSBram Moolenaar curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum; 3077c3516f7eSBram Moolenaar check_cursor(); 3078c3516f7eSBram Moolenaar do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE); 3079c3516f7eSBram Moolenaar vim_free(expr); 3080c3516f7eSBram Moolenaar } 3081c3516f7eSBram Moolenaar break; 3082c3516f7eSBram Moolenaar 308302194d2bSBram Moolenaar case ISN_CMDMOD: 308402194d2bSBram Moolenaar save_cmdmod = cmdmod; 308502194d2bSBram Moolenaar restore_cmdmod = TRUE; 308602194d2bSBram Moolenaar cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod; 308702194d2bSBram Moolenaar apply_cmdmod(&cmdmod); 3088f4c6e1e7SBram Moolenaar break; 3089f4c6e1e7SBram Moolenaar 309002194d2bSBram Moolenaar case ISN_CMDMOD_REV: 309102194d2bSBram Moolenaar // filter regprog is owned by the instruction, don't free it 309202194d2bSBram Moolenaar cmdmod.cmod_filter_regmatch.regprog = NULL; 309302194d2bSBram Moolenaar undo_cmdmod(&cmdmod); 309402194d2bSBram Moolenaar cmdmod = save_cmdmod; 309502194d2bSBram Moolenaar restore_cmdmod = FALSE; 3096f4c6e1e7SBram Moolenaar break; 3097f4c6e1e7SBram Moolenaar 3098792f786aSBram Moolenaar case ISN_UNPACK: 3099792f786aSBram Moolenaar { 3100792f786aSBram Moolenaar int count = iptr->isn_arg.unpack.unp_count; 3101792f786aSBram Moolenaar int semicolon = iptr->isn_arg.unpack.unp_semicolon; 3102792f786aSBram Moolenaar list_T *l; 3103792f786aSBram Moolenaar listitem_T *li; 3104792f786aSBram Moolenaar int i; 3105792f786aSBram Moolenaar 3106792f786aSBram Moolenaar // Check there is a valid list to unpack. 3107792f786aSBram Moolenaar tv = STACK_TV_BOT(-1); 3108792f786aSBram Moolenaar if (tv->v_type != VAR_LIST) 3109792f786aSBram Moolenaar { 3110792f786aSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3111792f786aSBram Moolenaar emsg(_(e_for_argument_must_be_sequence_of_lists)); 3112792f786aSBram Moolenaar goto on_error; 3113792f786aSBram Moolenaar } 3114792f786aSBram Moolenaar l = tv->vval.v_list; 3115792f786aSBram Moolenaar if (l == NULL 3116792f786aSBram Moolenaar || l->lv_len < (semicolon ? count - 1 : count)) 3117792f786aSBram Moolenaar { 3118792f786aSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3119792f786aSBram Moolenaar emsg(_(e_list_value_does_not_have_enough_items)); 3120792f786aSBram Moolenaar goto on_error; 3121792f786aSBram Moolenaar } 3122792f786aSBram Moolenaar else if (!semicolon && l->lv_len > count) 3123792f786aSBram Moolenaar { 3124792f786aSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3125792f786aSBram Moolenaar emsg(_(e_list_value_has_more_items_than_targets)); 3126792f786aSBram Moolenaar goto on_error; 3127792f786aSBram Moolenaar } 3128792f786aSBram Moolenaar 3129792f786aSBram Moolenaar CHECK_LIST_MATERIALIZE(l); 3130792f786aSBram Moolenaar if (GA_GROW(&ectx.ec_stack, count - 1) == FAIL) 3131792f786aSBram Moolenaar goto failed; 3132792f786aSBram Moolenaar ectx.ec_stack.ga_len += count - 1; 3133792f786aSBram Moolenaar 3134792f786aSBram Moolenaar // Variable after semicolon gets a list with the remaining 3135792f786aSBram Moolenaar // items. 3136792f786aSBram Moolenaar if (semicolon) 3137792f786aSBram Moolenaar { 3138792f786aSBram Moolenaar list_T *rem_list = 3139792f786aSBram Moolenaar list_alloc_with_items(l->lv_len - count + 1); 3140792f786aSBram Moolenaar 3141792f786aSBram Moolenaar if (rem_list == NULL) 3142792f786aSBram Moolenaar goto failed; 3143792f786aSBram Moolenaar tv = STACK_TV_BOT(-count); 3144792f786aSBram Moolenaar tv->vval.v_list = rem_list; 3145792f786aSBram Moolenaar ++rem_list->lv_refcount; 3146792f786aSBram Moolenaar tv->v_lock = 0; 3147792f786aSBram Moolenaar li = l->lv_first; 3148792f786aSBram Moolenaar for (i = 0; i < count - 1; ++i) 3149792f786aSBram Moolenaar li = li->li_next; 3150792f786aSBram Moolenaar for (i = 0; li != NULL; ++i) 3151792f786aSBram Moolenaar { 3152792f786aSBram Moolenaar list_set_item(rem_list, i, &li->li_tv); 3153792f786aSBram Moolenaar li = li->li_next; 3154792f786aSBram Moolenaar } 3155792f786aSBram Moolenaar --count; 3156792f786aSBram Moolenaar } 3157792f786aSBram Moolenaar 3158792f786aSBram Moolenaar // Produce the values in reverse order, first item last. 3159792f786aSBram Moolenaar li = l->lv_first; 3160792f786aSBram Moolenaar for (i = 0; i < count; ++i) 3161792f786aSBram Moolenaar { 3162792f786aSBram Moolenaar tv = STACK_TV_BOT(-i - 1); 3163792f786aSBram Moolenaar copy_tv(&li->li_tv, tv); 3164792f786aSBram Moolenaar li = li->li_next; 3165792f786aSBram Moolenaar } 3166792f786aSBram Moolenaar 3167792f786aSBram Moolenaar list_unref(l); 3168792f786aSBram Moolenaar } 3169792f786aSBram Moolenaar break; 3170792f786aSBram Moolenaar 3171389df259SBram Moolenaar case ISN_SHUFFLE: 3172389df259SBram Moolenaar { 3173389df259SBram Moolenaar typval_T tmp_tv; 3174389df259SBram Moolenaar int item = iptr->isn_arg.shuffle.shfl_item; 3175389df259SBram Moolenaar int up = iptr->isn_arg.shuffle.shfl_up; 3176389df259SBram Moolenaar 3177389df259SBram Moolenaar tmp_tv = *STACK_TV_BOT(-item); 3178389df259SBram Moolenaar for ( ; up > 0 && item > 1; --up) 3179389df259SBram Moolenaar { 3180389df259SBram Moolenaar *STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1); 3181389df259SBram Moolenaar --item; 3182389df259SBram Moolenaar } 3183389df259SBram Moolenaar *STACK_TV_BOT(-item) = tmp_tv; 3184389df259SBram Moolenaar } 3185389df259SBram Moolenaar break; 3186389df259SBram Moolenaar 31878a7d6542SBram Moolenaar case ISN_DROP: 31888a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 31898a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(0)); 31908a7d6542SBram Moolenaar break; 31918a7d6542SBram Moolenaar } 3192f0b9f43cSBram Moolenaar continue; 3193f0b9f43cSBram Moolenaar 3194d032f34aSBram Moolenaar func_return: 31957cbfaa51SBram Moolenaar // Restore previous function. If the frame pointer is where we started 31967cbfaa51SBram Moolenaar // then there is none and we are done. 3197d032f34aSBram Moolenaar if (ectx.ec_frame_idx == initial_frame_idx) 3198d032f34aSBram Moolenaar goto done; 31997cbfaa51SBram Moolenaar 3200d032f34aSBram Moolenaar if (func_return(&ectx) == FAIL) 3201d032f34aSBram Moolenaar // only fails when out of memory 3202d032f34aSBram Moolenaar goto failed; 3203c7db5778SBram Moolenaar continue; 3204d032f34aSBram Moolenaar 3205f0b9f43cSBram Moolenaar on_error: 3206af0df47aSBram Moolenaar // Jump here for an error that does not require aborting execution. 320756602ba1SBram Moolenaar // If "emsg_silent" is set then ignore the error, unless it was set 320856602ba1SBram Moolenaar // when calling the function. 320956602ba1SBram Moolenaar if (did_emsg_cumul + did_emsg == did_emsg_before 321056602ba1SBram Moolenaar && emsg_silent && did_emsg_def == 0) 3211cd030c4bSBram Moolenaar continue; 3212af0df47aSBram Moolenaar on_fatal_error: 3213af0df47aSBram Moolenaar // Jump here for an error that messes up the stack. 3214171fb923SBram Moolenaar // If we are not inside a try-catch started here, abort execution. 3215171fb923SBram Moolenaar if (trylevel <= trylevel_at_start) 3216f0b9f43cSBram Moolenaar goto failed; 32178a7d6542SBram Moolenaar } 32188a7d6542SBram Moolenaar 32198a7d6542SBram Moolenaar done: 32208a7d6542SBram Moolenaar // function finished, get result from the stack. 32218a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 32228a7d6542SBram Moolenaar *rettv = *tv; 32238a7d6542SBram Moolenaar tv->v_type = VAR_UNKNOWN; 32248a7d6542SBram Moolenaar ret = OK; 32258a7d6542SBram Moolenaar 32268a7d6542SBram Moolenaar failed: 32277eeefd4aSBram Moolenaar // When failed need to unwind the call stack. 3228bf67ea1aSBram Moolenaar while (ectx.ec_frame_idx != initial_frame_idx) 32297eeefd4aSBram Moolenaar func_return(&ectx); 3230bf67ea1aSBram Moolenaar 3231c70bdab0SBram Moolenaar // Deal with any remaining closures, they may be in use somewhere. 3232c70bdab0SBram Moolenaar if (ectx.ec_funcrefs.ga_len > 0) 3233f112f30aSBram Moolenaar { 3234c70bdab0SBram Moolenaar handle_closure_in_use(&ectx, FALSE); 3235f112f30aSBram Moolenaar ga_clear(&ectx.ec_funcrefs); // TODO: should not be needed? 3236f112f30aSBram Moolenaar } 3237c70bdab0SBram Moolenaar 3238ee8580e5SBram Moolenaar estack_pop(); 3239ee8580e5SBram Moolenaar current_sctx = save_current_sctx; 3240ee8580e5SBram Moolenaar 3241352134bbSBram Moolenaar if (*msg_list != NULL && saved_msg_list != NULL) 3242352134bbSBram Moolenaar { 3243352134bbSBram Moolenaar msglist_T **plist = saved_msg_list; 3244352134bbSBram Moolenaar 3245352134bbSBram Moolenaar // Append entries from the current msg_list (uncaught exceptions) to 3246352134bbSBram Moolenaar // the saved msg_list. 3247352134bbSBram Moolenaar while (*plist != NULL) 3248352134bbSBram Moolenaar plist = &(*plist)->next; 3249352134bbSBram Moolenaar 3250352134bbSBram Moolenaar *plist = *msg_list; 3251352134bbSBram Moolenaar } 3252352134bbSBram Moolenaar msg_list = saved_msg_list; 3253352134bbSBram Moolenaar 325402194d2bSBram Moolenaar if (restore_cmdmod) 325502194d2bSBram Moolenaar { 325602194d2bSBram Moolenaar cmdmod.cmod_filter_regmatch.regprog = NULL; 325702194d2bSBram Moolenaar undo_cmdmod(&cmdmod); 325802194d2bSBram Moolenaar cmdmod = save_cmdmod; 325902194d2bSBram Moolenaar } 326056602ba1SBram Moolenaar emsg_silent_def = save_emsg_silent_def; 326156602ba1SBram Moolenaar did_emsg_def += save_did_emsg_def; 3262f4c6e1e7SBram Moolenaar 3263ee8580e5SBram Moolenaar failed_early: 3264bf67ea1aSBram Moolenaar // Free all local variables, but not arguments. 32658a7d6542SBram Moolenaar for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx) 32668a7d6542SBram Moolenaar clear_tv(STACK_TV(idx)); 3267bf67ea1aSBram Moolenaar 32688a7d6542SBram Moolenaar vim_free(ectx.ec_stack.ga_data); 326920431c9dSBram Moolenaar vim_free(ectx.ec_trystack.ga_data); 3270682d0a15SBram Moolenaar 327177e5dcc3SBram Moolenaar // Not sure if this is necessary. 327277e5dcc3SBram Moolenaar suppress_errthrow = save_suppress_errthrow; 327377e5dcc3SBram Moolenaar 3274eeece9e4SBram Moolenaar if (ret != OK && did_emsg_cumul + did_emsg == did_emsg_before) 3275451c2e35SBram Moolenaar semsg(_(e_unknown_error_while_executing_str), 3276682d0a15SBram Moolenaar printable_func_name(ufunc)); 32770ba48e8cSBram Moolenaar funcdepth_restore(orig_funcdepth); 32788a7d6542SBram Moolenaar return ret; 32798a7d6542SBram Moolenaar } 32808a7d6542SBram Moolenaar 32818a7d6542SBram Moolenaar /* 32828e7d6223SBram Moolenaar * ":disassemble". 3283777770fbSBram Moolenaar * We don't really need this at runtime, but we do have tests that require it, 3284777770fbSBram Moolenaar * so always include this. 32858a7d6542SBram Moolenaar */ 32868a7d6542SBram Moolenaar void 32878a7d6542SBram Moolenaar ex_disassemble(exarg_T *eap) 32888a7d6542SBram Moolenaar { 328921456cdcSBram Moolenaar char_u *arg = eap->arg; 32900f18b6d1SBram Moolenaar char_u *fname; 32910f18b6d1SBram Moolenaar ufunc_T *ufunc; 32928a7d6542SBram Moolenaar dfunc_T *dfunc; 32938a7d6542SBram Moolenaar isn_T *instr; 32948a7d6542SBram Moolenaar int current; 32958a7d6542SBram Moolenaar int line_idx = 0; 32968a7d6542SBram Moolenaar int prev_current = 0; 32974c17ad94SBram Moolenaar int is_global = FALSE; 32988a7d6542SBram Moolenaar 3299bfd65589SBram Moolenaar if (STRNCMP(arg, "<lambda>", 8) == 0) 3300bfd65589SBram Moolenaar { 3301bfd65589SBram Moolenaar arg += 8; 3302bfd65589SBram Moolenaar (void)getdigits(&arg); 3303bfd65589SBram Moolenaar fname = vim_strnsave(eap->arg, arg - eap->arg); 3304bfd65589SBram Moolenaar } 3305bfd65589SBram Moolenaar else 33064c17ad94SBram Moolenaar fname = trans_function_name(&arg, &is_global, FALSE, 3307b68b346eSBram Moolenaar TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL); 330821456cdcSBram Moolenaar if (fname == NULL) 330921456cdcSBram Moolenaar { 331021456cdcSBram Moolenaar semsg(_(e_invarg2), eap->arg); 331121456cdcSBram Moolenaar return; 331221456cdcSBram Moolenaar } 331321456cdcSBram Moolenaar 33144c17ad94SBram Moolenaar ufunc = find_func(fname, is_global, NULL); 3315a26b9700SBram Moolenaar if (ufunc == NULL) 3316a26b9700SBram Moolenaar { 3317a26b9700SBram Moolenaar char_u *p = untrans_function_name(fname); 3318a26b9700SBram Moolenaar 3319a26b9700SBram Moolenaar if (p != NULL) 3320a26b9700SBram Moolenaar // Try again without making it script-local. 33214c17ad94SBram Moolenaar ufunc = find_func(p, FALSE, NULL); 3322a26b9700SBram Moolenaar } 33230f18b6d1SBram Moolenaar vim_free(fname); 33248a7d6542SBram Moolenaar if (ufunc == NULL) 33258a7d6542SBram Moolenaar { 3326451c2e35SBram Moolenaar semsg(_(e_cannot_find_function_str), eap->arg); 33278a7d6542SBram Moolenaar return; 33288a7d6542SBram Moolenaar } 33290cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_TO_BE_COMPILED 3330822ba247SBram Moolenaar && compile_def_function(ufunc, FALSE, NULL) == FAIL) 3331822ba247SBram Moolenaar return; 33320cb5bcf5SBram Moolenaar if (ufunc->uf_def_status != UF_COMPILED) 33338a7d6542SBram Moolenaar { 3334451c2e35SBram Moolenaar semsg(_(e_function_is_not_compiled_str), eap->arg); 33358a7d6542SBram Moolenaar return; 33368a7d6542SBram Moolenaar } 33378a7d6542SBram Moolenaar if (ufunc->uf_name_exp != NULL) 33388a7d6542SBram Moolenaar msg((char *)ufunc->uf_name_exp); 33398a7d6542SBram Moolenaar else 33408a7d6542SBram Moolenaar msg((char *)ufunc->uf_name); 33418a7d6542SBram Moolenaar 33428a7d6542SBram Moolenaar dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; 33438a7d6542SBram Moolenaar instr = dfunc->df_instr; 33448a7d6542SBram Moolenaar for (current = 0; current < dfunc->df_instr_count; ++current) 33458a7d6542SBram Moolenaar { 33468a7d6542SBram Moolenaar isn_T *iptr = &instr[current]; 3347f2460a3aSBram Moolenaar char *line; 33488a7d6542SBram Moolenaar 33498a7d6542SBram Moolenaar while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len) 33508a7d6542SBram Moolenaar { 33518a7d6542SBram Moolenaar if (current > prev_current) 33528a7d6542SBram Moolenaar { 33538a7d6542SBram Moolenaar msg_puts("\n\n"); 33548a7d6542SBram Moolenaar prev_current = current; 33558a7d6542SBram Moolenaar } 3356f2460a3aSBram Moolenaar line = ((char **)ufunc->uf_lines.ga_data)[line_idx++]; 3357f2460a3aSBram Moolenaar if (line != NULL) 3358f2460a3aSBram Moolenaar msg(line); 33598a7d6542SBram Moolenaar } 33608a7d6542SBram Moolenaar 33618a7d6542SBram Moolenaar switch (iptr->isn_type) 33628a7d6542SBram Moolenaar { 33638a7d6542SBram Moolenaar case ISN_EXEC: 33648a7d6542SBram Moolenaar smsg("%4d EXEC %s", current, iptr->isn_arg.string); 33658a7d6542SBram Moolenaar break; 3366cfe435d7SBram Moolenaar case ISN_EXECCONCAT: 3367cfe435d7SBram Moolenaar smsg("%4d EXECCONCAT %lld", current, 3368cfe435d7SBram Moolenaar (long long)iptr->isn_arg.number); 3369cfe435d7SBram Moolenaar break; 33708a7d6542SBram Moolenaar case ISN_ECHO: 33718a7d6542SBram Moolenaar { 33728a7d6542SBram Moolenaar echo_T *echo = &iptr->isn_arg.echo; 33738a7d6542SBram Moolenaar 33748a7d6542SBram Moolenaar smsg("%4d %s %d", current, 33758a7d6542SBram Moolenaar echo->echo_with_white ? "ECHO" : "ECHON", 33768a7d6542SBram Moolenaar echo->echo_count); 33778a7d6542SBram Moolenaar } 33788a7d6542SBram Moolenaar break; 3379ad39c094SBram Moolenaar case ISN_EXECUTE: 33801082772fSBram Moolenaar smsg("%4d EXECUTE %lld", current, 33811082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 3382ad39c094SBram Moolenaar break; 3383f93c7feaSBram Moolenaar case ISN_ECHOMSG: 3384f93c7feaSBram Moolenaar smsg("%4d ECHOMSG %lld", current, 3385f93c7feaSBram Moolenaar (long long)(iptr->isn_arg.number)); 3386f93c7feaSBram Moolenaar break; 3387f93c7feaSBram Moolenaar case ISN_ECHOERR: 3388f93c7feaSBram Moolenaar smsg("%4d ECHOERR %lld", current, 3389f93c7feaSBram Moolenaar (long long)(iptr->isn_arg.number)); 3390f93c7feaSBram Moolenaar break; 33918a7d6542SBram Moolenaar case ISN_LOAD: 3392c8cd2b34SBram Moolenaar case ISN_LOADOUTER: 3393c8cd2b34SBram Moolenaar { 3394c8cd2b34SBram Moolenaar char *add = iptr->isn_type == ISN_LOAD ? "" : "OUTER"; 3395c8cd2b34SBram Moolenaar 33968a7d6542SBram Moolenaar if (iptr->isn_arg.number < 0) 3397c8cd2b34SBram Moolenaar smsg("%4d LOAD%s arg[%lld]", current, add, 3398c8cd2b34SBram Moolenaar (long long)(iptr->isn_arg.number 3399c8cd2b34SBram Moolenaar + STACK_FRAME_SIZE)); 34008a7d6542SBram Moolenaar else 3401c8cd2b34SBram Moolenaar smsg("%4d LOAD%s $%lld", current, add, 34021082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 3403c8cd2b34SBram Moolenaar } 34048a7d6542SBram Moolenaar break; 34058a7d6542SBram Moolenaar case ISN_LOADV: 34068a7d6542SBram Moolenaar smsg("%4d LOADV v:%s", current, 34078a7d6542SBram Moolenaar get_vim_var_name(iptr->isn_arg.number)); 34088a7d6542SBram Moolenaar break; 34098a7d6542SBram Moolenaar case ISN_LOADSCRIPT: 34108a7d6542SBram Moolenaar { 34114aab88d9SBram Moolenaar scriptref_T *sref = iptr->isn_arg.script.scriptref; 34124aab88d9SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid); 34138a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 34144aab88d9SBram Moolenaar + sref->sref_idx; 34158a7d6542SBram Moolenaar 3416fbbcd003SBram Moolenaar smsg("%4d LOADSCRIPT %s-%d from %s", current, 3417fbbcd003SBram Moolenaar sv->sv_name, 34184aab88d9SBram Moolenaar sref->sref_idx, 3419fbbcd003SBram Moolenaar si->sn_name); 34208a7d6542SBram Moolenaar } 34218a7d6542SBram Moolenaar break; 34228a7d6542SBram Moolenaar case ISN_LOADS: 34238a7d6542SBram Moolenaar { 3424b283a8a6SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 3425b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 34268a7d6542SBram Moolenaar 34278a7d6542SBram Moolenaar smsg("%4d LOADS s:%s from %s", current, 34285deeb3f1SBram Moolenaar iptr->isn_arg.loadstore.ls_name, si->sn_name); 34298a7d6542SBram Moolenaar } 34308a7d6542SBram Moolenaar break; 343103290b84SBram Moolenaar case ISN_LOADAUTO: 343203290b84SBram Moolenaar smsg("%4d LOADAUTO %s", current, iptr->isn_arg.string); 343303290b84SBram Moolenaar break; 34348a7d6542SBram Moolenaar case ISN_LOADG: 34358a7d6542SBram Moolenaar smsg("%4d LOADG g:%s", current, iptr->isn_arg.string); 34368a7d6542SBram Moolenaar break; 3437d3aac291SBram Moolenaar case ISN_LOADB: 3438d3aac291SBram Moolenaar smsg("%4d LOADB b:%s", current, iptr->isn_arg.string); 3439d3aac291SBram Moolenaar break; 3440d3aac291SBram Moolenaar case ISN_LOADW: 3441d3aac291SBram Moolenaar smsg("%4d LOADW w:%s", current, iptr->isn_arg.string); 3442d3aac291SBram Moolenaar break; 3443d3aac291SBram Moolenaar case ISN_LOADT: 3444d3aac291SBram Moolenaar smsg("%4d LOADT t:%s", current, iptr->isn_arg.string); 3445d3aac291SBram Moolenaar break; 34462f8ce0aeSBram Moolenaar case ISN_LOADGDICT: 34472f8ce0aeSBram Moolenaar smsg("%4d LOAD g:", current); 34482f8ce0aeSBram Moolenaar break; 34492f8ce0aeSBram Moolenaar case ISN_LOADBDICT: 34502f8ce0aeSBram Moolenaar smsg("%4d LOAD b:", current); 34512f8ce0aeSBram Moolenaar break; 34522f8ce0aeSBram Moolenaar case ISN_LOADWDICT: 34532f8ce0aeSBram Moolenaar smsg("%4d LOAD w:", current); 34542f8ce0aeSBram Moolenaar break; 34552f8ce0aeSBram Moolenaar case ISN_LOADTDICT: 34562f8ce0aeSBram Moolenaar smsg("%4d LOAD t:", current); 34572f8ce0aeSBram Moolenaar break; 34588a7d6542SBram Moolenaar case ISN_LOADOPT: 34598a7d6542SBram Moolenaar smsg("%4d LOADOPT %s", current, iptr->isn_arg.string); 34608a7d6542SBram Moolenaar break; 34618a7d6542SBram Moolenaar case ISN_LOADENV: 34628a7d6542SBram Moolenaar smsg("%4d LOADENV %s", current, iptr->isn_arg.string); 34638a7d6542SBram Moolenaar break; 34648a7d6542SBram Moolenaar case ISN_LOADREG: 34651082772fSBram Moolenaar smsg("%4d LOADREG @%c", current, (int)(iptr->isn_arg.number)); 34668a7d6542SBram Moolenaar break; 34678a7d6542SBram Moolenaar 34688a7d6542SBram Moolenaar case ISN_STORE: 3469b68b346eSBram Moolenaar case ISN_STOREOUTER: 3470b68b346eSBram Moolenaar { 3471b68b346eSBram Moolenaar char *add = iptr->isn_type == ISN_STORE ? "" : "OUTER"; 3472b68b346eSBram Moolenaar 3473170fcfcfSBram Moolenaar if (iptr->isn_arg.number < 0) 3474b68b346eSBram Moolenaar smsg("%4d STORE%s arg[%lld]", current, add, 3475db99f9f2SBram Moolenaar (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE)); 3476170fcfcfSBram Moolenaar else 3477b68b346eSBram Moolenaar smsg("%4d STORE%s $%lld", current, add, 34781082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 3479b68b346eSBram Moolenaar } 34808a7d6542SBram Moolenaar break; 3481b283a8a6SBram Moolenaar case ISN_STOREV: 3482b283a8a6SBram Moolenaar smsg("%4d STOREV v:%s", current, 3483b283a8a6SBram Moolenaar get_vim_var_name(iptr->isn_arg.number)); 3484b283a8a6SBram Moolenaar break; 348503290b84SBram Moolenaar case ISN_STOREAUTO: 348603290b84SBram Moolenaar smsg("%4d STOREAUTO %s", current, iptr->isn_arg.string); 348703290b84SBram Moolenaar break; 34888a7d6542SBram Moolenaar case ISN_STOREG: 3489b283a8a6SBram Moolenaar smsg("%4d STOREG %s", current, iptr->isn_arg.string); 3490b283a8a6SBram Moolenaar break; 3491d3aac291SBram Moolenaar case ISN_STOREB: 3492d3aac291SBram Moolenaar smsg("%4d STOREB %s", current, iptr->isn_arg.string); 3493d3aac291SBram Moolenaar break; 3494d3aac291SBram Moolenaar case ISN_STOREW: 3495d3aac291SBram Moolenaar smsg("%4d STOREW %s", current, iptr->isn_arg.string); 3496d3aac291SBram Moolenaar break; 3497d3aac291SBram Moolenaar case ISN_STORET: 3498d3aac291SBram Moolenaar smsg("%4d STORET %s", current, iptr->isn_arg.string); 3499d3aac291SBram Moolenaar break; 3500b283a8a6SBram Moolenaar case ISN_STORES: 3501b283a8a6SBram Moolenaar { 3502b283a8a6SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 3503b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 3504b283a8a6SBram Moolenaar 35050bbf722aSBram Moolenaar smsg("%4d STORES %s in %s", current, 35065deeb3f1SBram Moolenaar iptr->isn_arg.loadstore.ls_name, si->sn_name); 3507b283a8a6SBram Moolenaar } 35088a7d6542SBram Moolenaar break; 35098a7d6542SBram Moolenaar case ISN_STORESCRIPT: 35108a7d6542SBram Moolenaar { 35114aab88d9SBram Moolenaar scriptref_T *sref = iptr->isn_arg.script.scriptref; 35124aab88d9SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid); 35138a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 35144aab88d9SBram Moolenaar + sref->sref_idx; 35158a7d6542SBram Moolenaar 3516fbbcd003SBram Moolenaar smsg("%4d STORESCRIPT %s-%d in %s", current, 3517fbbcd003SBram Moolenaar sv->sv_name, 35184aab88d9SBram Moolenaar sref->sref_idx, 3519fbbcd003SBram Moolenaar si->sn_name); 35208a7d6542SBram Moolenaar } 35218a7d6542SBram Moolenaar break; 35228a7d6542SBram Moolenaar case ISN_STOREOPT: 35238a7d6542SBram Moolenaar smsg("%4d STOREOPT &%s", current, 35248a7d6542SBram Moolenaar iptr->isn_arg.storeopt.so_name); 35258a7d6542SBram Moolenaar break; 3526b283a8a6SBram Moolenaar case ISN_STOREENV: 3527b283a8a6SBram Moolenaar smsg("%4d STOREENV $%s", current, iptr->isn_arg.string); 3528b283a8a6SBram Moolenaar break; 3529b283a8a6SBram Moolenaar case ISN_STOREREG: 35301082772fSBram Moolenaar smsg("%4d STOREREG @%c", current, (int)iptr->isn_arg.number); 3531b283a8a6SBram Moolenaar break; 35328a7d6542SBram Moolenaar case ISN_STORENR: 35338a7d6542SBram Moolenaar smsg("%4d STORE %lld in $%d", current, 3534a471eeaeSBram Moolenaar iptr->isn_arg.storenr.stnr_val, 3535a471eeaeSBram Moolenaar iptr->isn_arg.storenr.stnr_idx); 35368a7d6542SBram Moolenaar break; 35378a7d6542SBram Moolenaar 35384f5e3977SBram Moolenaar case ISN_STOREINDEX: 35394f5e3977SBram Moolenaar switch (iptr->isn_arg.vartype) 35404f5e3977SBram Moolenaar { 35414f5e3977SBram Moolenaar case VAR_LIST: 35421cc2a94fSBram Moolenaar smsg("%4d STORELIST", current); 35431cc2a94fSBram Moolenaar break; 35444f5e3977SBram Moolenaar case VAR_DICT: 35451cc2a94fSBram Moolenaar smsg("%4d STOREDICT", current); 35461cc2a94fSBram Moolenaar break; 35474f5e3977SBram Moolenaar case VAR_ANY: 35484f5e3977SBram Moolenaar smsg("%4d STOREINDEX", current); 35494f5e3977SBram Moolenaar break; 35504f5e3977SBram Moolenaar default: break; 35514f5e3977SBram Moolenaar } 35524f5e3977SBram Moolenaar break; 35531cc2a94fSBram Moolenaar 35548a7d6542SBram Moolenaar // constants 35558a7d6542SBram Moolenaar case ISN_PUSHNR: 35561082772fSBram Moolenaar smsg("%4d PUSHNR %lld", current, 35571082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 35588a7d6542SBram Moolenaar break; 35598a7d6542SBram Moolenaar case ISN_PUSHBOOL: 35608a7d6542SBram Moolenaar case ISN_PUSHSPEC: 35618a7d6542SBram Moolenaar smsg("%4d PUSH %s", current, 35628a7d6542SBram Moolenaar get_var_special_name(iptr->isn_arg.number)); 35638a7d6542SBram Moolenaar break; 35648a7d6542SBram Moolenaar case ISN_PUSHF: 3565a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT 35668a7d6542SBram Moolenaar smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber); 3567a5d5953dSBram Moolenaar #endif 35688a7d6542SBram Moolenaar break; 35698a7d6542SBram Moolenaar case ISN_PUSHS: 35708a7d6542SBram Moolenaar smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string); 35718a7d6542SBram Moolenaar break; 35728a7d6542SBram Moolenaar case ISN_PUSHBLOB: 35738a7d6542SBram Moolenaar { 35748a7d6542SBram Moolenaar char_u *r; 35758a7d6542SBram Moolenaar char_u numbuf[NUMBUFLEN]; 35768a7d6542SBram Moolenaar char_u *tofree; 35778a7d6542SBram Moolenaar 35788a7d6542SBram Moolenaar r = blob2string(iptr->isn_arg.blob, &tofree, numbuf); 3579ff80cb68SBram Moolenaar smsg("%4d PUSHBLOB %s", current, r); 35808a7d6542SBram Moolenaar vim_free(tofree); 35818a7d6542SBram Moolenaar } 35828a7d6542SBram Moolenaar break; 358342a480bfSBram Moolenaar case ISN_PUSHFUNC: 3584087d2e15SBram Moolenaar { 3585087d2e15SBram Moolenaar char *name = (char *)iptr->isn_arg.string; 3586087d2e15SBram Moolenaar 3587087d2e15SBram Moolenaar smsg("%4d PUSHFUNC \"%s\"", current, 3588087d2e15SBram Moolenaar name == NULL ? "[none]" : name); 3589087d2e15SBram Moolenaar } 359042a480bfSBram Moolenaar break; 359142a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 359242a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 359342a480bfSBram Moolenaar { 359442a480bfSBram Moolenaar channel_T *channel = iptr->isn_arg.channel; 359542a480bfSBram Moolenaar 359642a480bfSBram Moolenaar smsg("%4d PUSHCHANNEL %d", current, 359742a480bfSBram Moolenaar channel == NULL ? 0 : channel->ch_id); 359842a480bfSBram Moolenaar } 359942a480bfSBram Moolenaar #endif 360042a480bfSBram Moolenaar break; 360142a480bfSBram Moolenaar case ISN_PUSHJOB: 360242a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 360342a480bfSBram Moolenaar { 360442a480bfSBram Moolenaar typval_T tv; 360542a480bfSBram Moolenaar char_u *name; 360642a480bfSBram Moolenaar 360742a480bfSBram Moolenaar tv.v_type = VAR_JOB; 360842a480bfSBram Moolenaar tv.vval.v_job = iptr->isn_arg.job; 360942a480bfSBram Moolenaar name = tv_get_string(&tv); 3610f51cb4e0SBram Moolenaar smsg("%4d PUSHJOB \"%s\"", current, name); 361142a480bfSBram Moolenaar } 361242a480bfSBram Moolenaar #endif 361342a480bfSBram Moolenaar break; 36148a7d6542SBram Moolenaar case ISN_PUSHEXC: 36158a7d6542SBram Moolenaar smsg("%4d PUSH v:exception", current); 36168a7d6542SBram Moolenaar break; 3617d72c1bf0SBram Moolenaar case ISN_UNLET: 3618d72c1bf0SBram Moolenaar smsg("%4d UNLET%s %s", current, 3619d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_forceit ? "!" : "", 3620d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_name); 3621d72c1bf0SBram Moolenaar break; 36227bdaea6eSBram Moolenaar case ISN_UNLETENV: 36237bdaea6eSBram Moolenaar smsg("%4d UNLETENV%s $%s", current, 36247bdaea6eSBram Moolenaar iptr->isn_arg.unlet.ul_forceit ? "!" : "", 36257bdaea6eSBram Moolenaar iptr->isn_arg.unlet.ul_name); 36267bdaea6eSBram Moolenaar break; 36270b4c66c6SBram Moolenaar case ISN_LOCKCONST: 36280b4c66c6SBram Moolenaar smsg("%4d LOCKCONST", current); 36290b4c66c6SBram Moolenaar break; 36308a7d6542SBram Moolenaar case ISN_NEWLIST: 36311082772fSBram Moolenaar smsg("%4d NEWLIST size %lld", current, 36321082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 36338a7d6542SBram Moolenaar break; 36348a7d6542SBram Moolenaar case ISN_NEWDICT: 36351082772fSBram Moolenaar smsg("%4d NEWDICT size %lld", current, 36361082772fSBram Moolenaar (long long)(iptr->isn_arg.number)); 36378a7d6542SBram Moolenaar break; 36388a7d6542SBram Moolenaar 36398a7d6542SBram Moolenaar // function call 36408a7d6542SBram Moolenaar case ISN_BCALL: 36418a7d6542SBram Moolenaar { 36428a7d6542SBram Moolenaar cbfunc_T *cbfunc = &iptr->isn_arg.bfunc; 36438a7d6542SBram Moolenaar 36448a7d6542SBram Moolenaar smsg("%4d BCALL %s(argc %d)", current, 36458a7d6542SBram Moolenaar internal_func_name(cbfunc->cbf_idx), 36468a7d6542SBram Moolenaar cbfunc->cbf_argcount); 36478a7d6542SBram Moolenaar } 36488a7d6542SBram Moolenaar break; 36498a7d6542SBram Moolenaar case ISN_DCALL: 36508a7d6542SBram Moolenaar { 36518a7d6542SBram Moolenaar cdfunc_T *cdfunc = &iptr->isn_arg.dfunc; 36528a7d6542SBram Moolenaar dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 36538a7d6542SBram Moolenaar + cdfunc->cdf_idx; 36548a7d6542SBram Moolenaar 36558a7d6542SBram Moolenaar smsg("%4d DCALL %s(argc %d)", current, 36568a7d6542SBram Moolenaar df->df_ufunc->uf_name_exp != NULL 36578a7d6542SBram Moolenaar ? df->df_ufunc->uf_name_exp 36588a7d6542SBram Moolenaar : df->df_ufunc->uf_name, cdfunc->cdf_argcount); 36598a7d6542SBram Moolenaar } 36608a7d6542SBram Moolenaar break; 36618a7d6542SBram Moolenaar case ISN_UCALL: 36628a7d6542SBram Moolenaar { 36638a7d6542SBram Moolenaar cufunc_T *cufunc = &iptr->isn_arg.ufunc; 36648a7d6542SBram Moolenaar 36658a7d6542SBram Moolenaar smsg("%4d UCALL %s(argc %d)", current, 36668a7d6542SBram Moolenaar cufunc->cuf_name, cufunc->cuf_argcount); 36678a7d6542SBram Moolenaar } 36688a7d6542SBram Moolenaar break; 36698a7d6542SBram Moolenaar case ISN_PCALL: 36708a7d6542SBram Moolenaar { 36718a7d6542SBram Moolenaar cpfunc_T *cpfunc = &iptr->isn_arg.pfunc; 36728a7d6542SBram Moolenaar 36738a7d6542SBram Moolenaar smsg("%4d PCALL%s (argc %d)", current, 36748a7d6542SBram Moolenaar cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); 36758a7d6542SBram Moolenaar } 36768a7d6542SBram Moolenaar break; 3677bd5da371SBram Moolenaar case ISN_PCALL_END: 3678bd5da371SBram Moolenaar smsg("%4d PCALL end", current); 3679bd5da371SBram Moolenaar break; 36808a7d6542SBram Moolenaar case ISN_RETURN: 36818a7d6542SBram Moolenaar smsg("%4d RETURN", current); 36828a7d6542SBram Moolenaar break; 36838a7d6542SBram Moolenaar case ISN_FUNCREF: 36848a7d6542SBram Moolenaar { 36855adc55cbSBram Moolenaar funcref_T *funcref = &iptr->isn_arg.funcref; 36868a7d6542SBram Moolenaar dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 36875adc55cbSBram Moolenaar + funcref->fr_func; 36888a7d6542SBram Moolenaar 3689148ce7aeSBram Moolenaar smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name); 36908a7d6542SBram Moolenaar } 36918a7d6542SBram Moolenaar break; 36928a7d6542SBram Moolenaar 369338ddf333SBram Moolenaar case ISN_NEWFUNC: 369438ddf333SBram Moolenaar { 369538ddf333SBram Moolenaar newfunc_T *newfunc = &iptr->isn_arg.newfunc; 369638ddf333SBram Moolenaar 369738ddf333SBram Moolenaar smsg("%4d NEWFUNC %s %s", current, 369838ddf333SBram Moolenaar newfunc->nf_lambda, newfunc->nf_global); 369938ddf333SBram Moolenaar } 370038ddf333SBram Moolenaar break; 370138ddf333SBram Moolenaar 37026abdcf82SBram Moolenaar case ISN_DEF: 37036abdcf82SBram Moolenaar { 37046abdcf82SBram Moolenaar char_u *name = iptr->isn_arg.string; 37056abdcf82SBram Moolenaar 37066abdcf82SBram Moolenaar smsg("%4d DEF %s", current, 37076abdcf82SBram Moolenaar name == NULL ? (char_u *)"" : name); 37086abdcf82SBram Moolenaar } 37096abdcf82SBram Moolenaar break; 37106abdcf82SBram Moolenaar 37118a7d6542SBram Moolenaar case ISN_JUMP: 37128a7d6542SBram Moolenaar { 37138a7d6542SBram Moolenaar char *when = "?"; 37148a7d6542SBram Moolenaar 37158a7d6542SBram Moolenaar switch (iptr->isn_arg.jump.jump_when) 37168a7d6542SBram Moolenaar { 37178a7d6542SBram Moolenaar case JUMP_ALWAYS: 37188a7d6542SBram Moolenaar when = "JUMP"; 37198a7d6542SBram Moolenaar break; 37208a7d6542SBram Moolenaar case JUMP_AND_KEEP_IF_TRUE: 37218a7d6542SBram Moolenaar when = "JUMP_AND_KEEP_IF_TRUE"; 37228a7d6542SBram Moolenaar break; 37238a7d6542SBram Moolenaar case JUMP_IF_FALSE: 37248a7d6542SBram Moolenaar when = "JUMP_IF_FALSE"; 37258a7d6542SBram Moolenaar break; 37268a7d6542SBram Moolenaar case JUMP_AND_KEEP_IF_FALSE: 37278a7d6542SBram Moolenaar when = "JUMP_AND_KEEP_IF_FALSE"; 37288a7d6542SBram Moolenaar break; 37292bb2658bSBram Moolenaar case JUMP_IF_COND_FALSE: 37302bb2658bSBram Moolenaar when = "JUMP_IF_COND_FALSE"; 37312bb2658bSBram Moolenaar break; 37322bb2658bSBram Moolenaar case JUMP_IF_COND_TRUE: 37332bb2658bSBram Moolenaar when = "JUMP_IF_COND_TRUE"; 37342bb2658bSBram Moolenaar break; 37358a7d6542SBram Moolenaar } 37368a677a37SBram Moolenaar smsg("%4d %s -> %d", current, when, 37378a7d6542SBram Moolenaar iptr->isn_arg.jump.jump_where); 37388a7d6542SBram Moolenaar } 37398a7d6542SBram Moolenaar break; 37408a7d6542SBram Moolenaar 37418a7d6542SBram Moolenaar case ISN_FOR: 37428a7d6542SBram Moolenaar { 37438a7d6542SBram Moolenaar forloop_T *forloop = &iptr->isn_arg.forloop; 37448a7d6542SBram Moolenaar 37458a7d6542SBram Moolenaar smsg("%4d FOR $%d -> %d", current, 37468a7d6542SBram Moolenaar forloop->for_idx, forloop->for_end); 37478a7d6542SBram Moolenaar } 37488a7d6542SBram Moolenaar break; 37498a7d6542SBram Moolenaar 37508a7d6542SBram Moolenaar case ISN_TRY: 37518a7d6542SBram Moolenaar { 37528a7d6542SBram Moolenaar try_T *try = &iptr->isn_arg.try; 37538a7d6542SBram Moolenaar 37548a7d6542SBram Moolenaar smsg("%4d TRY catch -> %d, finally -> %d", current, 37558a7d6542SBram Moolenaar try->try_catch, try->try_finally); 37568a7d6542SBram Moolenaar } 37578a7d6542SBram Moolenaar break; 37588a7d6542SBram Moolenaar case ISN_CATCH: 37598a7d6542SBram Moolenaar // TODO 37608a7d6542SBram Moolenaar smsg("%4d CATCH", current); 37618a7d6542SBram Moolenaar break; 37628a7d6542SBram Moolenaar case ISN_ENDTRY: 37638a7d6542SBram Moolenaar smsg("%4d ENDTRY", current); 37648a7d6542SBram Moolenaar break; 37658a7d6542SBram Moolenaar case ISN_THROW: 37668a7d6542SBram Moolenaar smsg("%4d THROW", current); 37678a7d6542SBram Moolenaar break; 37688a7d6542SBram Moolenaar 37698a7d6542SBram Moolenaar // expression operations on number 37708a7d6542SBram Moolenaar case ISN_OPNR: 37718a7d6542SBram Moolenaar case ISN_OPFLOAT: 37728a7d6542SBram Moolenaar case ISN_OPANY: 37738a7d6542SBram Moolenaar { 37748a7d6542SBram Moolenaar char *what; 37758a7d6542SBram Moolenaar char *ins; 37768a7d6542SBram Moolenaar 37778a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 37788a7d6542SBram Moolenaar { 37798a7d6542SBram Moolenaar case EXPR_MULT: what = "*"; break; 37808a7d6542SBram Moolenaar case EXPR_DIV: what = "/"; break; 37818a7d6542SBram Moolenaar case EXPR_REM: what = "%"; break; 37828a7d6542SBram Moolenaar case EXPR_SUB: what = "-"; break; 37838a7d6542SBram Moolenaar case EXPR_ADD: what = "+"; break; 37848a7d6542SBram Moolenaar default: what = "???"; break; 37858a7d6542SBram Moolenaar } 37868a7d6542SBram Moolenaar switch (iptr->isn_type) 37878a7d6542SBram Moolenaar { 37888a7d6542SBram Moolenaar case ISN_OPNR: ins = "OPNR"; break; 37898a7d6542SBram Moolenaar case ISN_OPFLOAT: ins = "OPFLOAT"; break; 37908a7d6542SBram Moolenaar case ISN_OPANY: ins = "OPANY"; break; 37918a7d6542SBram Moolenaar default: ins = "???"; break; 37928a7d6542SBram Moolenaar } 37938a7d6542SBram Moolenaar smsg("%4d %s %s", current, ins, what); 37948a7d6542SBram Moolenaar } 37958a7d6542SBram Moolenaar break; 37968a7d6542SBram Moolenaar 37978a7d6542SBram Moolenaar case ISN_COMPAREBOOL: 37988a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 37998a7d6542SBram Moolenaar case ISN_COMPARENR: 38008a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: 38018a7d6542SBram Moolenaar case ISN_COMPARESTRING: 38028a7d6542SBram Moolenaar case ISN_COMPAREBLOB: 38038a7d6542SBram Moolenaar case ISN_COMPARELIST: 38048a7d6542SBram Moolenaar case ISN_COMPAREDICT: 38058a7d6542SBram Moolenaar case ISN_COMPAREFUNC: 38068a7d6542SBram Moolenaar case ISN_COMPAREANY: 38078a7d6542SBram Moolenaar { 38088a7d6542SBram Moolenaar char *p; 38098a7d6542SBram Moolenaar char buf[10]; 38108a7d6542SBram Moolenaar char *type; 38118a7d6542SBram Moolenaar 38128a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 38138a7d6542SBram Moolenaar { 38148a7d6542SBram Moolenaar case EXPR_EQUAL: p = "=="; break; 38158a7d6542SBram Moolenaar case EXPR_NEQUAL: p = "!="; break; 38168a7d6542SBram Moolenaar case EXPR_GREATER: p = ">"; break; 38178a7d6542SBram Moolenaar case EXPR_GEQUAL: p = ">="; break; 38188a7d6542SBram Moolenaar case EXPR_SMALLER: p = "<"; break; 38198a7d6542SBram Moolenaar case EXPR_SEQUAL: p = "<="; break; 38208a7d6542SBram Moolenaar case EXPR_MATCH: p = "=~"; break; 38218a7d6542SBram Moolenaar case EXPR_IS: p = "is"; break; 38228a7d6542SBram Moolenaar case EXPR_ISNOT: p = "isnot"; break; 38238a7d6542SBram Moolenaar case EXPR_NOMATCH: p = "!~"; break; 38248a7d6542SBram Moolenaar default: p = "???"; break; 38258a7d6542SBram Moolenaar } 38268a7d6542SBram Moolenaar STRCPY(buf, p); 38278a7d6542SBram Moolenaar if (iptr->isn_arg.op.op_ic == TRUE) 38288a7d6542SBram Moolenaar strcat(buf, "?"); 38298a7d6542SBram Moolenaar switch(iptr->isn_type) 38308a7d6542SBram Moolenaar { 38318a7d6542SBram Moolenaar case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break; 38328a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 38338a7d6542SBram Moolenaar type = "COMPARESPECIAL"; break; 38348a7d6542SBram Moolenaar case ISN_COMPARENR: type = "COMPARENR"; break; 38358a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break; 38368a7d6542SBram Moolenaar case ISN_COMPARESTRING: 38378a7d6542SBram Moolenaar type = "COMPARESTRING"; break; 38388a7d6542SBram Moolenaar case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break; 38398a7d6542SBram Moolenaar case ISN_COMPARELIST: type = "COMPARELIST"; break; 38408a7d6542SBram Moolenaar case ISN_COMPAREDICT: type = "COMPAREDICT"; break; 38418a7d6542SBram Moolenaar case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break; 38428a7d6542SBram Moolenaar case ISN_COMPAREANY: type = "COMPAREANY"; break; 38438a7d6542SBram Moolenaar default: type = "???"; break; 38448a7d6542SBram Moolenaar } 38458a7d6542SBram Moolenaar 38468a7d6542SBram Moolenaar smsg("%4d %s %s", current, type, buf); 38478a7d6542SBram Moolenaar } 38488a7d6542SBram Moolenaar break; 38498a7d6542SBram Moolenaar 38508a7d6542SBram Moolenaar case ISN_ADDLIST: smsg("%4d ADDLIST", current); break; 38518a7d6542SBram Moolenaar case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break; 38528a7d6542SBram Moolenaar 38538a7d6542SBram Moolenaar // expression operations 38548a7d6542SBram Moolenaar case ISN_CONCAT: smsg("%4d CONCAT", current); break; 3855bf9d8c37SBram Moolenaar case ISN_STRINDEX: smsg("%4d STRINDEX", current); break; 385611107babSBram Moolenaar case ISN_STRSLICE: smsg("%4d STRSLICE", current); break; 38571dcae599SBram Moolenaar case ISN_LISTAPPEND: smsg("%4d LISTAPPEND", current); break; 385880b0e5eaSBram Moolenaar case ISN_BLOBAPPEND: smsg("%4d BLOBAPPEND", current); break; 3859bf9d8c37SBram Moolenaar case ISN_LISTINDEX: smsg("%4d LISTINDEX", current); break; 3860ed591877SBram Moolenaar case ISN_LISTSLICE: smsg("%4d LISTSLICE", current); break; 3861cc673e74SBram Moolenaar case ISN_ANYINDEX: smsg("%4d ANYINDEX", current); break; 3862cc673e74SBram Moolenaar case ISN_ANYSLICE: smsg("%4d ANYSLICE", current); break; 38639af78769SBram Moolenaar case ISN_SLICE: smsg("%4d SLICE %lld", 38649af78769SBram Moolenaar current, iptr->isn_arg.number); break; 386547a519a9SBram Moolenaar case ISN_GETITEM: smsg("%4d ITEM %lld", 386647a519a9SBram Moolenaar current, iptr->isn_arg.number); break; 38671cc2a94fSBram Moolenaar case ISN_MEMBER: smsg("%4d MEMBER", current); break; 38681cc2a94fSBram Moolenaar case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current, 38698a7d6542SBram Moolenaar iptr->isn_arg.string); break; 38708a7d6542SBram Moolenaar case ISN_NEGATENR: smsg("%4d NEGATENR", current); break; 38718a7d6542SBram Moolenaar 38728a7d6542SBram Moolenaar case ISN_CHECKNR: smsg("%4d CHECKNR", current); break; 38735e654230SBram Moolenaar case ISN_CHECKTYPE: 38745e654230SBram Moolenaar { 38755e654230SBram Moolenaar char *tofree; 38765e654230SBram Moolenaar 38775e654230SBram Moolenaar smsg("%4d CHECKTYPE %s stack[%d]", current, 38785e654230SBram Moolenaar type_name(iptr->isn_arg.type.ct_type, &tofree), 38798a7d6542SBram Moolenaar iptr->isn_arg.type.ct_off); 38805e654230SBram Moolenaar vim_free(tofree); 38818a7d6542SBram Moolenaar break; 38825e654230SBram Moolenaar } 38839af78769SBram Moolenaar case ISN_CHECKLEN: smsg("%4d CHECKLEN %s%d", current, 38849af78769SBram Moolenaar iptr->isn_arg.checklen.cl_more_OK ? ">= " : "", 38859af78769SBram Moolenaar iptr->isn_arg.checklen.cl_min_len); 38869af78769SBram Moolenaar break; 38872bb2658bSBram Moolenaar case ISN_COND2BOOL: smsg("%4d COND2BOOL", current); break; 38888a7d6542SBram Moolenaar case ISN_2BOOL: if (iptr->isn_arg.number) 38898a7d6542SBram Moolenaar smsg("%4d INVERT (!val)", current); 38908a7d6542SBram Moolenaar else 38918a7d6542SBram Moolenaar smsg("%4d 2BOOL (!!val)", current); 38928a7d6542SBram Moolenaar break; 3893db99f9f2SBram Moolenaar case ISN_2STRING: smsg("%4d 2STRING stack[%lld]", current, 3894db99f9f2SBram Moolenaar (long long)(iptr->isn_arg.number)); 38958a7d6542SBram Moolenaar break; 3896418f1df5SBram Moolenaar case ISN_2STRING_ANY: smsg("%4d 2STRING_ANY stack[%lld]", current, 3897418f1df5SBram Moolenaar (long long)(iptr->isn_arg.number)); 3898418f1df5SBram Moolenaar break; 389908597875SBram Moolenaar case ISN_RANGE: smsg("%4d RANGE %s", current, iptr->isn_arg.string); 390008597875SBram Moolenaar break; 3901c3516f7eSBram Moolenaar case ISN_PUT: 390208597875SBram Moolenaar if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE_ABOVE) 390308597875SBram Moolenaar smsg("%4d PUT %c above range", 390408597875SBram Moolenaar current, iptr->isn_arg.put.put_regname); 390508597875SBram Moolenaar else if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE) 390608597875SBram Moolenaar smsg("%4d PUT %c range", 390708597875SBram Moolenaar current, iptr->isn_arg.put.put_regname); 390808597875SBram Moolenaar else 390908597875SBram Moolenaar smsg("%4d PUT %c %ld", current, 391008597875SBram Moolenaar iptr->isn_arg.put.put_regname, 3911c3516f7eSBram Moolenaar (long)iptr->isn_arg.put.put_lnum); 3912c3516f7eSBram Moolenaar break; 39138a7d6542SBram Moolenaar 391402194d2bSBram Moolenaar // TODO: summarize modifiers 391502194d2bSBram Moolenaar case ISN_CMDMOD: 391602194d2bSBram Moolenaar { 391702194d2bSBram Moolenaar char_u *buf; 3918a360dbe3SBram Moolenaar size_t len = produce_cmdmods( 391902194d2bSBram Moolenaar NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE); 392002194d2bSBram Moolenaar 392102194d2bSBram Moolenaar buf = alloc(len + 1); 392202194d2bSBram Moolenaar if (buf != NULL) 392302194d2bSBram Moolenaar { 392402194d2bSBram Moolenaar (void)produce_cmdmods( 392502194d2bSBram Moolenaar buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE); 392602194d2bSBram Moolenaar smsg("%4d CMDMOD %s", current, buf); 392702194d2bSBram Moolenaar vim_free(buf); 392802194d2bSBram Moolenaar } 392902194d2bSBram Moolenaar break; 393002194d2bSBram Moolenaar } 393102194d2bSBram Moolenaar case ISN_CMDMOD_REV: smsg("%4d CMDMOD_REV", current); break; 3932f4c6e1e7SBram Moolenaar 3933792f786aSBram Moolenaar case ISN_UNPACK: smsg("%4d UNPACK %d%s", current, 3934792f786aSBram Moolenaar iptr->isn_arg.unpack.unp_count, 3935792f786aSBram Moolenaar iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : ""); 3936792f786aSBram Moolenaar break; 3937389df259SBram Moolenaar case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current, 3938389df259SBram Moolenaar iptr->isn_arg.shuffle.shfl_item, 3939389df259SBram Moolenaar iptr->isn_arg.shuffle.shfl_up); 3940389df259SBram Moolenaar break; 39418a7d6542SBram Moolenaar case ISN_DROP: smsg("%4d DROP", current); break; 39428a7d6542SBram Moolenaar } 3943793dcc54SBram Moolenaar 3944793dcc54SBram Moolenaar out_flush(); // output one line at a time 3945793dcc54SBram Moolenaar ui_breakcheck(); 3946793dcc54SBram Moolenaar if (got_int) 3947793dcc54SBram Moolenaar break; 39488a7d6542SBram Moolenaar } 39498a7d6542SBram Moolenaar } 39508a7d6542SBram Moolenaar 39518a7d6542SBram Moolenaar /* 395213106605SBram Moolenaar * Return TRUE when "tv" is not falsy: non-zero, non-empty string, non-empty 39538a7d6542SBram Moolenaar * list, etc. Mostly like what JavaScript does, except that empty list and 39548a7d6542SBram Moolenaar * empty dictionary are FALSE. 39558a7d6542SBram Moolenaar */ 39568a7d6542SBram Moolenaar int 39578a7d6542SBram Moolenaar tv2bool(typval_T *tv) 39588a7d6542SBram Moolenaar { 39598a7d6542SBram Moolenaar switch (tv->v_type) 39608a7d6542SBram Moolenaar { 39618a7d6542SBram Moolenaar case VAR_NUMBER: 39628a7d6542SBram Moolenaar return tv->vval.v_number != 0; 39638a7d6542SBram Moolenaar case VAR_FLOAT: 39648a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 39658a7d6542SBram Moolenaar return tv->vval.v_float != 0.0; 39668a7d6542SBram Moolenaar #else 39678a7d6542SBram Moolenaar break; 39688a7d6542SBram Moolenaar #endif 39698a7d6542SBram Moolenaar case VAR_PARTIAL: 39708a7d6542SBram Moolenaar return tv->vval.v_partial != NULL; 39718a7d6542SBram Moolenaar case VAR_FUNC: 39728a7d6542SBram Moolenaar case VAR_STRING: 39738a7d6542SBram Moolenaar return tv->vval.v_string != NULL && *tv->vval.v_string != NUL; 39748a7d6542SBram Moolenaar case VAR_LIST: 39758a7d6542SBram Moolenaar return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0; 39768a7d6542SBram Moolenaar case VAR_DICT: 39778a7d6542SBram Moolenaar return tv->vval.v_dict != NULL 39788a7d6542SBram Moolenaar && tv->vval.v_dict->dv_hashtab.ht_used > 0; 39798a7d6542SBram Moolenaar case VAR_BOOL: 39808a7d6542SBram Moolenaar case VAR_SPECIAL: 39818a7d6542SBram Moolenaar return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE; 39828a7d6542SBram Moolenaar case VAR_JOB: 39838a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL 39848a7d6542SBram Moolenaar return tv->vval.v_job != NULL; 39858a7d6542SBram Moolenaar #else 39868a7d6542SBram Moolenaar break; 39878a7d6542SBram Moolenaar #endif 39888a7d6542SBram Moolenaar case VAR_CHANNEL: 39898a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL 39908a7d6542SBram Moolenaar return tv->vval.v_channel != NULL; 39918a7d6542SBram Moolenaar #else 39928a7d6542SBram Moolenaar break; 39938a7d6542SBram Moolenaar #endif 39948a7d6542SBram Moolenaar case VAR_BLOB: 39958a7d6542SBram Moolenaar return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0; 39968a7d6542SBram Moolenaar case VAR_UNKNOWN: 39974c683750SBram Moolenaar case VAR_ANY: 39988a7d6542SBram Moolenaar case VAR_VOID: 39998a7d6542SBram Moolenaar break; 40008a7d6542SBram Moolenaar } 40018a7d6542SBram Moolenaar return FALSE; 40028a7d6542SBram Moolenaar } 40038a7d6542SBram Moolenaar 4004ea2d407fSBram Moolenaar void 4005ea2d407fSBram Moolenaar emsg_using_string_as(typval_T *tv, int as_number) 4006ea2d407fSBram Moolenaar { 4007ea2d407fSBram Moolenaar semsg(_(as_number ? e_using_string_as_number_str 4008ea2d407fSBram Moolenaar : e_using_string_as_bool_str), 4009ea2d407fSBram Moolenaar tv->vval.v_string == NULL 4010ea2d407fSBram Moolenaar ? (char_u *)"" : tv->vval.v_string); 4011ea2d407fSBram Moolenaar } 4012ea2d407fSBram Moolenaar 40138a7d6542SBram Moolenaar /* 40148a7d6542SBram Moolenaar * If "tv" is a string give an error and return FAIL. 40158a7d6542SBram Moolenaar */ 40168a7d6542SBram Moolenaar int 40178a7d6542SBram Moolenaar check_not_string(typval_T *tv) 40188a7d6542SBram Moolenaar { 40198a7d6542SBram Moolenaar if (tv->v_type == VAR_STRING) 40208a7d6542SBram Moolenaar { 4021ea2d407fSBram Moolenaar emsg_using_string_as(tv, TRUE); 40228a7d6542SBram Moolenaar clear_tv(tv); 40238a7d6542SBram Moolenaar return FAIL; 40248a7d6542SBram Moolenaar } 40258a7d6542SBram Moolenaar return OK; 40268a7d6542SBram Moolenaar } 40278a7d6542SBram Moolenaar 40288a7d6542SBram Moolenaar 40298a7d6542SBram Moolenaar #endif // FEAT_EVAL 4030