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 { 27d9d7789bSBram Moolenaar int tcd_frame_idx; // ec_frame_idx at ISN_TRY 28d9d7789bSBram Moolenaar int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY 297e82c5f3SBram Moolenaar int tcd_catch_idx; // instruction of the first :catch or :finally 307e82c5f3SBram Moolenaar int tcd_finally_idx; // instruction of the :finally block or zero 317e82c5f3SBram Moolenaar int tcd_endtry_idx; // instruction of the :endtry 328a7d6542SBram Moolenaar int tcd_caught; // catch block entered 33c150c09eSBram Moolenaar int tcd_cont; // :continue encountered, jump here 348a7d6542SBram Moolenaar int tcd_return; // when TRUE return from end of :finally 358a7d6542SBram Moolenaar } trycmd_T; 368a7d6542SBram Moolenaar 378a7d6542SBram Moolenaar 388a7d6542SBram Moolenaar // A stack is used to store: 398a7d6542SBram Moolenaar // - arguments passed to a :def function 408a7d6542SBram Moolenaar // - info about the calling function, to use when returning 418a7d6542SBram Moolenaar // - local variables 428a7d6542SBram Moolenaar // - temporary values 438a7d6542SBram Moolenaar // 448a7d6542SBram Moolenaar // In detail (FP == Frame Pointer): 458a7d6542SBram Moolenaar // arg1 first argument from caller (if present) 468a7d6542SBram Moolenaar // arg2 second argument from caller (if present) 478a7d6542SBram Moolenaar // extra_arg1 any missing optional argument default value 488a7d6542SBram Moolenaar // FP -> cur_func calling function 498a7d6542SBram Moolenaar // current previous instruction pointer 508a7d6542SBram Moolenaar // frame_ptr previous Frame Pointer 518a7d6542SBram Moolenaar // var1 space for local variable 528a7d6542SBram Moolenaar // var2 space for local variable 538a7d6542SBram Moolenaar // .... fixed space for max. number of local variables 548a7d6542SBram Moolenaar // temp temporary values 558a7d6542SBram Moolenaar // .... flexible space for temporary values (can grow big) 568a7d6542SBram Moolenaar 578a7d6542SBram Moolenaar /* 588a7d6542SBram Moolenaar * Execution context. 598a7d6542SBram Moolenaar */ 60cd45ed03SBram Moolenaar struct ectx_S { 618a7d6542SBram Moolenaar garray_T ec_stack; // stack of typval_T values 62bf67ea1aSBram Moolenaar int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx 638a7d6542SBram Moolenaar 640186e586SBram Moolenaar outer_T *ec_outer; // outer scope used for closures, allocated 65c8cd2b34SBram Moolenaar 668a7d6542SBram Moolenaar garray_T ec_trystack; // stack of trycmd_T values 678a7d6542SBram Moolenaar int ec_in_catch; // when TRUE in catch or finally block 688a7d6542SBram Moolenaar 698a7d6542SBram Moolenaar int ec_dfunc_idx; // current function index 708a7d6542SBram Moolenaar isn_T *ec_instr; // array with instructions 718a7d6542SBram Moolenaar int ec_iidx; // index in ec_instr: instruction to execute 72148ce7aeSBram Moolenaar 73148ce7aeSBram Moolenaar garray_T ec_funcrefs; // partials that might be a closure 74cd45ed03SBram Moolenaar }; 758a7d6542SBram Moolenaar 7612d26531SBram Moolenaar #ifdef FEAT_PROFILE 7712d26531SBram Moolenaar // stack of profinfo_T used when profiling. 7812d26531SBram Moolenaar static garray_T profile_info_ga = {0, 0, sizeof(profinfo_T), 20, NULL}; 7912d26531SBram Moolenaar #endif 8012d26531SBram Moolenaar 818a7d6542SBram Moolenaar // Get pointer to item relative to the bottom of the stack, -1 is the last one. 8211107babSBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx)) 838a7d6542SBram Moolenaar 84418f1df5SBram Moolenaar void 85418f1df5SBram Moolenaar to_string_error(vartype_T vartype) 86418f1df5SBram Moolenaar { 87451c2e35SBram Moolenaar semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype)); 88418f1df5SBram Moolenaar } 89418f1df5SBram Moolenaar 908a7d6542SBram Moolenaar /* 91170fcfcfSBram Moolenaar * Return the number of arguments, including optional arguments and any vararg. 928a7d6542SBram Moolenaar */ 938a7d6542SBram Moolenaar static int 948a7d6542SBram Moolenaar ufunc_argcount(ufunc_T *ufunc) 958a7d6542SBram Moolenaar { 968a7d6542SBram Moolenaar return ufunc->uf_args.ga_len + (ufunc->uf_va_name != NULL ? 1 : 0); 978a7d6542SBram Moolenaar } 988a7d6542SBram Moolenaar 998a7d6542SBram Moolenaar /* 100170fcfcfSBram Moolenaar * Set the instruction index, depending on omitted arguments, where the default 101170fcfcfSBram Moolenaar * values are to be computed. If all optional arguments are present, start 102170fcfcfSBram Moolenaar * with the function body. 103170fcfcfSBram Moolenaar * The expression evaluation is at the start of the instructions: 104170fcfcfSBram Moolenaar * 0 -> EVAL default1 105170fcfcfSBram Moolenaar * STORE arg[-2] 106170fcfcfSBram Moolenaar * 1 -> EVAL default2 107170fcfcfSBram Moolenaar * STORE arg[-1] 108170fcfcfSBram Moolenaar * 2 -> function body 109170fcfcfSBram Moolenaar */ 110170fcfcfSBram Moolenaar static void 111170fcfcfSBram Moolenaar init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx) 112170fcfcfSBram Moolenaar { 113170fcfcfSBram Moolenaar if (ufunc->uf_def_args.ga_len == 0) 114170fcfcfSBram Moolenaar ectx->ec_iidx = 0; 115170fcfcfSBram Moolenaar else 116170fcfcfSBram Moolenaar { 117170fcfcfSBram Moolenaar int defcount = ufunc->uf_args.ga_len - argcount; 118170fcfcfSBram Moolenaar 119170fcfcfSBram Moolenaar // If there is a varargs argument defcount can be negative, no defaults 120170fcfcfSBram Moolenaar // to evaluate then. 121170fcfcfSBram Moolenaar if (defcount < 0) 122170fcfcfSBram Moolenaar defcount = 0; 123170fcfcfSBram Moolenaar ectx->ec_iidx = ufunc->uf_def_arg_idx[ 124170fcfcfSBram Moolenaar ufunc->uf_def_args.ga_len - defcount]; 125170fcfcfSBram Moolenaar } 126170fcfcfSBram Moolenaar } 127170fcfcfSBram Moolenaar 128170fcfcfSBram Moolenaar /* 129fe270817SBram Moolenaar * Create a new list from "count" items at the bottom of the stack. 130fe270817SBram Moolenaar * When "count" is zero an empty list is added to the stack. 131fe270817SBram Moolenaar */ 132fe270817SBram Moolenaar static int 133fe270817SBram Moolenaar exe_newlist(int count, ectx_T *ectx) 134fe270817SBram Moolenaar { 135fe270817SBram Moolenaar list_T *list = list_alloc_with_items(count); 136fe270817SBram Moolenaar int idx; 137fe270817SBram Moolenaar typval_T *tv; 138fe270817SBram Moolenaar 139fe270817SBram Moolenaar if (list == NULL) 140fe270817SBram Moolenaar return FAIL; 141fe270817SBram Moolenaar for (idx = 0; idx < count; ++idx) 142fe270817SBram Moolenaar list_set_item(list, idx, STACK_TV_BOT(idx - count)); 143fe270817SBram Moolenaar 144fe270817SBram Moolenaar if (count > 0) 145fe270817SBram Moolenaar ectx->ec_stack.ga_len -= count - 1; 146270d0388SBram Moolenaar else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) 147fe270817SBram Moolenaar return FAIL; 148fe270817SBram Moolenaar else 149fe270817SBram Moolenaar ++ectx->ec_stack.ga_len; 150fe270817SBram Moolenaar tv = STACK_TV_BOT(-1); 151fe270817SBram Moolenaar tv->v_type = VAR_LIST; 152fe270817SBram Moolenaar tv->vval.v_list = list; 153fe270817SBram Moolenaar ++list->lv_refcount; 154fe270817SBram Moolenaar return OK; 155fe270817SBram Moolenaar } 156fe270817SBram Moolenaar 157fe270817SBram Moolenaar /* 1588a7d6542SBram Moolenaar * Call compiled function "cdf_idx" from compiled code. 159ab360526SBram Moolenaar * This adds a stack frame and sets the instruction pointer to the start of the 160ab360526SBram Moolenaar * called function. 1610186e586SBram Moolenaar * If "pt" is not null use "pt->pt_outer" for ec_outer. 1628a7d6542SBram Moolenaar * 1638a7d6542SBram Moolenaar * Stack has: 1648a7d6542SBram Moolenaar * - current arguments (already there) 1658a7d6542SBram Moolenaar * - omitted optional argument (default values) added here 1668a7d6542SBram Moolenaar * - stack frame: 1678a7d6542SBram Moolenaar * - pointer to calling function 1688a7d6542SBram Moolenaar * - Index of next instruction in calling function 1698a7d6542SBram Moolenaar * - previous frame pointer 1708a7d6542SBram Moolenaar * - reserved space for local variables 1718a7d6542SBram Moolenaar */ 1728a7d6542SBram Moolenaar static int 1730186e586SBram Moolenaar call_dfunc(int cdf_idx, partial_T *pt, int argcount_arg, ectx_T *ectx) 1748a7d6542SBram Moolenaar { 1751378fbc4SBram Moolenaar int argcount = argcount_arg; 1768a7d6542SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + cdf_idx; 1778a7d6542SBram Moolenaar ufunc_T *ufunc = dfunc->df_ufunc; 1781378fbc4SBram Moolenaar int arg_to_add; 1791378fbc4SBram Moolenaar int vararg_count = 0; 180148ce7aeSBram Moolenaar int varcount; 1818a7d6542SBram Moolenaar int idx; 182c620c055SBram Moolenaar estack_T *entry; 1838a7d6542SBram Moolenaar 1848a7d6542SBram Moolenaar if (dfunc->df_deleted) 1858a7d6542SBram Moolenaar { 186cd45ed03SBram Moolenaar // don't use ufunc->uf_name, it may have been freed 187cd45ed03SBram Moolenaar emsg_funcname(e_func_deleted, 188cd45ed03SBram Moolenaar dfunc->df_name == NULL ? (char_u *)"unknown" : dfunc->df_name); 1898a7d6542SBram Moolenaar return FAIL; 1908a7d6542SBram Moolenaar } 1918a7d6542SBram Moolenaar 192e5ea346aSBram Moolenaar #ifdef FEAT_PROFILE 19312d26531SBram Moolenaar if (do_profiling == PROF_YES) 19412d26531SBram Moolenaar { 19512d26531SBram Moolenaar if (ga_grow(&profile_info_ga, 1) == OK) 19612d26531SBram Moolenaar { 19712d26531SBram Moolenaar profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data) 19812d26531SBram Moolenaar + profile_info_ga.ga_len; 19912d26531SBram Moolenaar ++profile_info_ga.ga_len; 20012d26531SBram Moolenaar CLEAR_POINTER(info); 20112d26531SBram Moolenaar profile_may_start_func(info, ufunc, 20212d26531SBram Moolenaar (((dfunc_T *)def_functions.ga_data) 20312d26531SBram Moolenaar + ectx->ec_dfunc_idx)->df_ufunc); 20412d26531SBram Moolenaar } 20512d26531SBram Moolenaar 206e5ea346aSBram Moolenaar // Profiling might be enabled/disabled along the way. This should not 207e5ea346aSBram Moolenaar // fail, since the function was compiled before and toggling profiling 208e5ea346aSBram Moolenaar // doesn't change any errors. 209e5ea346aSBram Moolenaar if (func_needs_compiling(ufunc, PROFILING(ufunc)) 210e5ea346aSBram Moolenaar && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL) 211e5ea346aSBram Moolenaar == FAIL) 212e5ea346aSBram Moolenaar return FAIL; 21312d26531SBram Moolenaar } 214e5ea346aSBram Moolenaar #endif 215e5ea346aSBram Moolenaar 2161378fbc4SBram Moolenaar if (ufunc->uf_va_name != NULL) 2171378fbc4SBram Moolenaar { 218fe270817SBram Moolenaar // Need to make a list out of the vararg arguments. 2191378fbc4SBram Moolenaar // Stack at time of call with 2 varargs: 2201378fbc4SBram Moolenaar // normal_arg 2211378fbc4SBram Moolenaar // optional_arg 2221378fbc4SBram Moolenaar // vararg_1 2231378fbc4SBram Moolenaar // vararg_2 224fe270817SBram Moolenaar // After creating the list: 2251378fbc4SBram Moolenaar // normal_arg 2261378fbc4SBram Moolenaar // optional_arg 227fe270817SBram Moolenaar // vararg-list 228fe270817SBram Moolenaar // With missing optional arguments we get: 229fe270817SBram Moolenaar // normal_arg 230fe270817SBram Moolenaar // After creating the list 231fe270817SBram Moolenaar // normal_arg 232fe270817SBram Moolenaar // (space for optional_arg) 233fe270817SBram Moolenaar // vararg-list 2341378fbc4SBram Moolenaar vararg_count = argcount - ufunc->uf_args.ga_len; 2351378fbc4SBram Moolenaar if (vararg_count < 0) 2361378fbc4SBram Moolenaar vararg_count = 0; 2371378fbc4SBram Moolenaar else 2381378fbc4SBram Moolenaar argcount -= vararg_count; 239fe270817SBram Moolenaar if (exe_newlist(vararg_count, ectx) == FAIL) 2401378fbc4SBram Moolenaar return FAIL; 241fe270817SBram Moolenaar 242fe270817SBram Moolenaar vararg_count = 1; 2431378fbc4SBram Moolenaar } 2441378fbc4SBram Moolenaar 245fe270817SBram Moolenaar arg_to_add = ufunc->uf_args.ga_len - argcount; 2461378fbc4SBram Moolenaar if (arg_to_add < 0) 2471378fbc4SBram Moolenaar { 24879e8db9aSBram Moolenaar if (arg_to_add == -1) 249451c2e35SBram Moolenaar emsg(_(e_one_argument_too_many)); 25079e8db9aSBram Moolenaar else 251451c2e35SBram Moolenaar semsg(_(e_nr_arguments_too_many), -arg_to_add); 2521378fbc4SBram Moolenaar return FAIL; 2531378fbc4SBram Moolenaar } 254148ce7aeSBram Moolenaar 255148ce7aeSBram Moolenaar // Reserve space for: 256148ce7aeSBram Moolenaar // - missing arguments 257148ce7aeSBram Moolenaar // - stack frame 258148ce7aeSBram Moolenaar // - local variables 259148ce7aeSBram Moolenaar // - if needed: a counter for number of closures created in 260148ce7aeSBram Moolenaar // ectx->ec_funcrefs. 261148ce7aeSBram Moolenaar varcount = dfunc->df_varcount + dfunc->df_has_closure; 262148ce7aeSBram Moolenaar if (ga_grow(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE + varcount) 263148ce7aeSBram Moolenaar == FAIL) 2648a7d6542SBram Moolenaar return FAIL; 2658a7d6542SBram Moolenaar 2660ba48e8cSBram Moolenaar // If depth of calling is getting too high, don't execute the function. 2670ba48e8cSBram Moolenaar if (funcdepth_increment() == FAIL) 2680ba48e8cSBram Moolenaar return FAIL; 2690ba48e8cSBram Moolenaar 270fe270817SBram Moolenaar // Move the vararg-list to below the missing optional arguments. 271fe270817SBram Moolenaar if (vararg_count > 0 && arg_to_add > 0) 272fe270817SBram Moolenaar *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1); 273170fcfcfSBram Moolenaar 274170fcfcfSBram Moolenaar // Reserve space for omitted optional arguments, filled in soon. 2751378fbc4SBram Moolenaar for (idx = 0; idx < arg_to_add; ++idx) 276fe270817SBram Moolenaar STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN; 2771378fbc4SBram Moolenaar ectx->ec_stack.ga_len += arg_to_add; 2788a7d6542SBram Moolenaar 2798a7d6542SBram Moolenaar // Store current execution state in stack frame for ISN_RETURN. 2800186e586SBram Moolenaar STACK_TV_BOT(STACK_FRAME_FUNC_OFF)->vval.v_number = ectx->ec_dfunc_idx; 2810186e586SBram Moolenaar STACK_TV_BOT(STACK_FRAME_IIDX_OFF)->vval.v_number = ectx->ec_iidx; 2820186e586SBram Moolenaar STACK_TV_BOT(STACK_FRAME_OUTER_OFF)->vval.v_string = (void *)ectx->ec_outer; 2830186e586SBram Moolenaar STACK_TV_BOT(STACK_FRAME_IDX_OFF)->vval.v_number = ectx->ec_frame_idx; 284bf67ea1aSBram Moolenaar ectx->ec_frame_idx = ectx->ec_stack.ga_len; 2858a7d6542SBram Moolenaar 2868a7d6542SBram Moolenaar // Initialize local variables 287148ce7aeSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 2888a7d6542SBram Moolenaar STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN; 289148ce7aeSBram Moolenaar if (dfunc->df_has_closure) 290148ce7aeSBram Moolenaar { 291148ce7aeSBram Moolenaar typval_T *tv = STACK_TV_BOT(STACK_FRAME_SIZE + dfunc->df_varcount); 292148ce7aeSBram Moolenaar 293148ce7aeSBram Moolenaar tv->v_type = VAR_NUMBER; 294148ce7aeSBram Moolenaar tv->vval.v_number = 0; 295148ce7aeSBram Moolenaar } 296148ce7aeSBram Moolenaar ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount; 2978a7d6542SBram Moolenaar 2980d3de8cbSBram Moolenaar if (pt != NULL || ufunc->uf_partial != NULL 2990d3de8cbSBram Moolenaar || (ufunc->uf_flags & FC_CLOSURE)) 300cd45ed03SBram Moolenaar { 3010186e586SBram Moolenaar outer_T *outer = ALLOC_CLEAR_ONE(outer_T); 3020186e586SBram Moolenaar 3030186e586SBram Moolenaar if (outer == NULL) 3040186e586SBram Moolenaar return FAIL; 3050186e586SBram Moolenaar if (pt != NULL) 306ab360526SBram Moolenaar { 3070186e586SBram Moolenaar *outer = pt->pt_outer; 3080186e586SBram Moolenaar outer->out_up_is_copy = TRUE; 309cd45ed03SBram Moolenaar } 3100186e586SBram Moolenaar else if (ufunc->uf_partial != NULL) 3110186e586SBram Moolenaar { 3120186e586SBram Moolenaar *outer = ufunc->uf_partial->pt_outer; 3130186e586SBram Moolenaar outer->out_up_is_copy = TRUE; 3140186e586SBram Moolenaar } 3150186e586SBram Moolenaar else 3160186e586SBram Moolenaar { 3170186e586SBram Moolenaar outer->out_stack = &ectx->ec_stack; 3180186e586SBram Moolenaar outer->out_frame_idx = ectx->ec_frame_idx; 3190186e586SBram Moolenaar outer->out_up = ectx->ec_outer; 3200186e586SBram Moolenaar } 3210186e586SBram Moolenaar ectx->ec_outer = outer; 3220186e586SBram Moolenaar } 3230186e586SBram Moolenaar else 3240186e586SBram Moolenaar ectx->ec_outer = NULL; 325cd45ed03SBram Moolenaar 3268a7d6542SBram Moolenaar // Set execution state to the start of the called function. 3278a7d6542SBram Moolenaar ectx->ec_dfunc_idx = cdf_idx; 328e5ea346aSBram Moolenaar ectx->ec_instr = INSTRUCTIONS(dfunc); 329b2049903SBram Moolenaar entry = estack_push_ufunc(ufunc, 1); 330c620c055SBram Moolenaar if (entry != NULL) 331c620c055SBram Moolenaar { 332c620c055SBram Moolenaar // Set the script context to the script where the function was defined. 333c620c055SBram Moolenaar // TODO: save more than the SID? 334c620c055SBram Moolenaar entry->es_save_sid = current_sctx.sc_sid; 335c620c055SBram Moolenaar current_sctx.sc_sid = ufunc->uf_script_ctx.sc_sid; 336c620c055SBram Moolenaar } 337170fcfcfSBram Moolenaar 338170fcfcfSBram Moolenaar // Decide where to start execution, handles optional arguments. 339170fcfcfSBram Moolenaar init_instr_idx(ufunc, argcount, ectx); 3408a7d6542SBram Moolenaar 3418a7d6542SBram Moolenaar return OK; 3428a7d6542SBram Moolenaar } 3438a7d6542SBram Moolenaar 3448a7d6542SBram Moolenaar // Get pointer to item in the stack. 3458a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx) 3468a7d6542SBram Moolenaar 3478a7d6542SBram Moolenaar /* 348bf67ea1aSBram Moolenaar * Used when returning from a function: Check if any closure is still 349bf67ea1aSBram Moolenaar * referenced. If so then move the arguments and variables to a separate piece 350bf67ea1aSBram Moolenaar * of stack to be used when the closure is called. 351bf67ea1aSBram Moolenaar * When "free_arguments" is TRUE the arguments are to be freed. 352bf67ea1aSBram Moolenaar * Returns FAIL when out of memory. 353bf67ea1aSBram Moolenaar */ 354bf67ea1aSBram Moolenaar static int 355bf67ea1aSBram Moolenaar handle_closure_in_use(ectx_T *ectx, int free_arguments) 356bf67ea1aSBram Moolenaar { 357bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 358bf67ea1aSBram Moolenaar + ectx->ec_dfunc_idx; 359fdeab65dSBram Moolenaar int argcount; 360fdeab65dSBram Moolenaar int top; 361bf67ea1aSBram Moolenaar int idx; 362bf67ea1aSBram Moolenaar typval_T *tv; 363bf67ea1aSBram Moolenaar int closure_in_use = FALSE; 364148ce7aeSBram Moolenaar garray_T *gap = &ectx->ec_funcrefs; 365148ce7aeSBram Moolenaar varnumber_T closure_count; 366bf67ea1aSBram Moolenaar 367fdeab65dSBram Moolenaar if (dfunc->df_ufunc == NULL) 368148ce7aeSBram Moolenaar return OK; // function was freed 369148ce7aeSBram Moolenaar if (dfunc->df_has_closure == 0) 370148ce7aeSBram Moolenaar return OK; // no closures 371148ce7aeSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + dfunc->df_varcount); 372148ce7aeSBram Moolenaar closure_count = tv->vval.v_number; 373148ce7aeSBram Moolenaar if (closure_count == 0) 374148ce7aeSBram Moolenaar return OK; // no funcrefs created 375148ce7aeSBram Moolenaar 376fdeab65dSBram Moolenaar argcount = ufunc_argcount(dfunc->df_ufunc); 377fdeab65dSBram Moolenaar top = ectx->ec_frame_idx - argcount; 378fdeab65dSBram Moolenaar 379bf67ea1aSBram Moolenaar // Check if any created closure is still in use. 380148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 381bf67ea1aSBram Moolenaar { 382c70bdab0SBram Moolenaar partial_T *pt; 383c70bdab0SBram Moolenaar int off = gap->ga_len - closure_count + idx; 384148ce7aeSBram Moolenaar 385c70bdab0SBram Moolenaar if (off < 0) 386c70bdab0SBram Moolenaar continue; // count is off or already done 387c70bdab0SBram Moolenaar pt = ((partial_T **)gap->ga_data)[off]; 388148ce7aeSBram Moolenaar if (pt->pt_refcount > 1) 389221fcc74SBram Moolenaar { 390148ce7aeSBram Moolenaar int refcount = pt->pt_refcount; 391221fcc74SBram Moolenaar int i; 392221fcc74SBram Moolenaar 393f821ddaaSBram Moolenaar // A Reference in a local variables doesn't count, it gets 394221fcc74SBram Moolenaar // unreferenced on return. 395221fcc74SBram Moolenaar for (i = 0; i < dfunc->df_varcount; ++i) 396221fcc74SBram Moolenaar { 397221fcc74SBram Moolenaar typval_T *stv = STACK_TV(ectx->ec_frame_idx 398221fcc74SBram Moolenaar + STACK_FRAME_SIZE + i); 399148ce7aeSBram Moolenaar if (stv->v_type == VAR_PARTIAL && pt == stv->vval.v_partial) 400221fcc74SBram Moolenaar --refcount; 401221fcc74SBram Moolenaar } 402221fcc74SBram Moolenaar if (refcount > 1) 403f7779c63SBram Moolenaar { 404bf67ea1aSBram Moolenaar closure_in_use = TRUE; 405f7779c63SBram Moolenaar break; 406f7779c63SBram Moolenaar } 407bf67ea1aSBram Moolenaar } 408221fcc74SBram Moolenaar } 409bf67ea1aSBram Moolenaar 410bf67ea1aSBram Moolenaar if (closure_in_use) 411bf67ea1aSBram Moolenaar { 412bf67ea1aSBram Moolenaar funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T); 413bf67ea1aSBram Moolenaar typval_T *stack; 414bf67ea1aSBram Moolenaar 415bf67ea1aSBram Moolenaar // A closure is using the arguments and/or local variables. 416bf67ea1aSBram Moolenaar // Move them to the called function. 417bf67ea1aSBram Moolenaar if (funcstack == NULL) 418bf67ea1aSBram Moolenaar return FAIL; 41985d5e2b7SBram Moolenaar funcstack->fs_var_offset = argcount + STACK_FRAME_SIZE; 42085d5e2b7SBram Moolenaar funcstack->fs_ga.ga_len = funcstack->fs_var_offset + dfunc->df_varcount; 421bf67ea1aSBram Moolenaar stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len); 422bf67ea1aSBram Moolenaar funcstack->fs_ga.ga_data = stack; 423bf67ea1aSBram Moolenaar if (stack == NULL) 424bf67ea1aSBram Moolenaar { 425bf67ea1aSBram Moolenaar vim_free(funcstack); 426bf67ea1aSBram Moolenaar return FAIL; 427bf67ea1aSBram Moolenaar } 428bf67ea1aSBram Moolenaar 429bf67ea1aSBram Moolenaar // Move or copy the arguments. 430bf67ea1aSBram Moolenaar for (idx = 0; idx < argcount; ++idx) 431bf67ea1aSBram Moolenaar { 432bf67ea1aSBram Moolenaar tv = STACK_TV(top + idx); 433bf67ea1aSBram Moolenaar if (free_arguments) 434bf67ea1aSBram Moolenaar { 435bf67ea1aSBram Moolenaar *(stack + idx) = *tv; 436bf67ea1aSBram Moolenaar tv->v_type = VAR_UNKNOWN; 437bf67ea1aSBram Moolenaar } 438bf67ea1aSBram Moolenaar else 439bf67ea1aSBram Moolenaar copy_tv(tv, stack + idx); 440bf67ea1aSBram Moolenaar } 441bf67ea1aSBram Moolenaar // Move the local variables. 442bf67ea1aSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 443bf67ea1aSBram Moolenaar { 444bf67ea1aSBram Moolenaar tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx); 445f821ddaaSBram Moolenaar 44685d5e2b7SBram Moolenaar // A partial created for a local function, that is also used as a 44785d5e2b7SBram Moolenaar // local variable, has a reference count for the variable, thus 44885d5e2b7SBram Moolenaar // will never go down to zero. When all these refcounts are one 44985d5e2b7SBram Moolenaar // then the funcstack is unused. We need to count how many we have 45085d5e2b7SBram Moolenaar // so we need when to check. 451f821ddaaSBram Moolenaar if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) 452f821ddaaSBram Moolenaar { 453f821ddaaSBram Moolenaar int i; 454f821ddaaSBram Moolenaar 455148ce7aeSBram Moolenaar for (i = 0; i < closure_count; ++i) 45685d5e2b7SBram Moolenaar if (tv->vval.v_partial == ((partial_T **)gap->ga_data)[ 45785d5e2b7SBram Moolenaar gap->ga_len - closure_count + i]) 45885d5e2b7SBram Moolenaar ++funcstack->fs_min_refcount; 459f821ddaaSBram Moolenaar } 460f821ddaaSBram Moolenaar 46185d5e2b7SBram Moolenaar *(stack + funcstack->fs_var_offset + idx) = *tv; 462bf67ea1aSBram Moolenaar tv->v_type = VAR_UNKNOWN; 463bf67ea1aSBram Moolenaar } 464bf67ea1aSBram Moolenaar 465148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 466bf67ea1aSBram Moolenaar { 467148ce7aeSBram Moolenaar partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len 468148ce7aeSBram Moolenaar - closure_count + idx]; 469148ce7aeSBram Moolenaar if (pt->pt_refcount > 1) 470f7779c63SBram Moolenaar { 471bf67ea1aSBram Moolenaar ++funcstack->fs_refcount; 472148ce7aeSBram Moolenaar pt->pt_funcstack = funcstack; 4730186e586SBram Moolenaar pt->pt_outer.out_stack = &funcstack->fs_ga; 4740186e586SBram Moolenaar pt->pt_outer.out_frame_idx = ectx->ec_frame_idx - top; 4750186e586SBram Moolenaar pt->pt_outer.out_up = ectx->ec_outer; 476f7779c63SBram Moolenaar } 477bf67ea1aSBram Moolenaar } 478bf67ea1aSBram Moolenaar } 479148ce7aeSBram Moolenaar 480148ce7aeSBram Moolenaar for (idx = 0; idx < closure_count; ++idx) 481148ce7aeSBram Moolenaar partial_unref(((partial_T **)gap->ga_data)[gap->ga_len 482148ce7aeSBram Moolenaar - closure_count + idx]); 483148ce7aeSBram Moolenaar gap->ga_len -= closure_count; 484148ce7aeSBram Moolenaar if (gap->ga_len == 0) 485148ce7aeSBram Moolenaar ga_clear(gap); 486bf67ea1aSBram Moolenaar 487bf67ea1aSBram Moolenaar return OK; 488bf67ea1aSBram Moolenaar } 489bf67ea1aSBram Moolenaar 490bf67ea1aSBram Moolenaar /* 49185d5e2b7SBram Moolenaar * Called when a partial is freed or its reference count goes down to one. The 49285d5e2b7SBram Moolenaar * funcstack may be the only reference to the partials in the local variables. 49385d5e2b7SBram Moolenaar * Go over all of them, the funcref and can be freed if all partials 49485d5e2b7SBram Moolenaar * referencing the funcstack have a reference count of one. 49585d5e2b7SBram Moolenaar */ 49685d5e2b7SBram Moolenaar void 49785d5e2b7SBram Moolenaar funcstack_check_refcount(funcstack_T *funcstack) 49885d5e2b7SBram Moolenaar { 49985d5e2b7SBram Moolenaar int i; 50085d5e2b7SBram Moolenaar garray_T *gap = &funcstack->fs_ga; 50185d5e2b7SBram Moolenaar int done = 0; 50285d5e2b7SBram Moolenaar 50385d5e2b7SBram Moolenaar if (funcstack->fs_refcount > funcstack->fs_min_refcount) 50485d5e2b7SBram Moolenaar return; 50585d5e2b7SBram Moolenaar for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i) 50685d5e2b7SBram Moolenaar { 50785d5e2b7SBram Moolenaar typval_T *tv = ((typval_T *)gap->ga_data) + i; 50885d5e2b7SBram Moolenaar 50985d5e2b7SBram Moolenaar if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL 51085d5e2b7SBram Moolenaar && tv->vval.v_partial->pt_funcstack == funcstack 51185d5e2b7SBram Moolenaar && tv->vval.v_partial->pt_refcount == 1) 51285d5e2b7SBram Moolenaar ++done; 51385d5e2b7SBram Moolenaar } 51485d5e2b7SBram Moolenaar if (done == funcstack->fs_min_refcount) 51585d5e2b7SBram Moolenaar { 51685d5e2b7SBram Moolenaar typval_T *stack = gap->ga_data; 51785d5e2b7SBram Moolenaar 51885d5e2b7SBram Moolenaar // All partials referencing the funcstack have a reference count of 51985d5e2b7SBram Moolenaar // one, thus the funcstack is no longer of use. 52085d5e2b7SBram Moolenaar for (i = 0; i < gap->ga_len; ++i) 52185d5e2b7SBram Moolenaar clear_tv(stack + i); 52285d5e2b7SBram Moolenaar vim_free(stack); 52385d5e2b7SBram Moolenaar vim_free(funcstack); 52485d5e2b7SBram Moolenaar } 52585d5e2b7SBram Moolenaar } 52685d5e2b7SBram Moolenaar 52785d5e2b7SBram Moolenaar /* 5288a7d6542SBram Moolenaar * Return from the current function. 5298a7d6542SBram Moolenaar */ 530bf67ea1aSBram Moolenaar static int 5318a7d6542SBram Moolenaar func_return(ectx_T *ectx) 5328a7d6542SBram Moolenaar { 5338a7d6542SBram Moolenaar int idx; 53434c54eb6SBram Moolenaar int ret_idx; 535bf67ea1aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 536bf67ea1aSBram Moolenaar + ectx->ec_dfunc_idx; 537bf67ea1aSBram Moolenaar int argcount = ufunc_argcount(dfunc->df_ufunc); 538bf67ea1aSBram Moolenaar int top = ectx->ec_frame_idx - argcount; 539c620c055SBram Moolenaar estack_T *entry; 54012d26531SBram Moolenaar int prev_dfunc_idx = STACK_TV(ectx->ec_frame_idx 54112d26531SBram Moolenaar + STACK_FRAME_FUNC_OFF)->vval.v_number; 54212d26531SBram Moolenaar dfunc_T *prev_dfunc = ((dfunc_T *)def_functions.ga_data) 54312d26531SBram Moolenaar + prev_dfunc_idx; 5448a7d6542SBram Moolenaar 54512d26531SBram Moolenaar #ifdef FEAT_PROFILE 54612d26531SBram Moolenaar if (do_profiling == PROF_YES) 54712d26531SBram Moolenaar { 54812d26531SBram Moolenaar ufunc_T *caller = prev_dfunc->df_ufunc; 54912d26531SBram Moolenaar 55012d26531SBram Moolenaar if (dfunc->df_ufunc->uf_profiling 55112d26531SBram Moolenaar || (caller != NULL && caller->uf_profiling)) 55212d26531SBram Moolenaar { 55312d26531SBram Moolenaar profile_may_end_func(((profinfo_T *)profile_info_ga.ga_data) 55412d26531SBram Moolenaar + profile_info_ga.ga_len - 1, dfunc->df_ufunc, caller); 55512d26531SBram Moolenaar --profile_info_ga.ga_len; 55612d26531SBram Moolenaar } 55712d26531SBram Moolenaar } 55812d26531SBram Moolenaar #endif 5598a7d6542SBram Moolenaar // execution context goes one level up 560c620c055SBram Moolenaar entry = estack_pop(); 561c620c055SBram Moolenaar if (entry != NULL) 562c620c055SBram Moolenaar current_sctx.sc_sid = entry->es_save_sid; 5638a7d6542SBram Moolenaar 564bf67ea1aSBram Moolenaar if (handle_closure_in_use(ectx, TRUE) == FAIL) 565bf67ea1aSBram Moolenaar return FAIL; 566bf67ea1aSBram Moolenaar 567bf67ea1aSBram Moolenaar // Clear the arguments. 568bf67ea1aSBram Moolenaar for (idx = top; idx < ectx->ec_frame_idx; ++idx) 569bf67ea1aSBram Moolenaar clear_tv(STACK_TV(idx)); 570bf67ea1aSBram Moolenaar 571bf67ea1aSBram Moolenaar // Clear local variables and temp values, but not the return value. 572bf67ea1aSBram Moolenaar for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE; 5738a7d6542SBram Moolenaar idx < ectx->ec_stack.ga_len - 1; ++idx) 5748a7d6542SBram Moolenaar clear_tv(STACK_TV(idx)); 575170fcfcfSBram Moolenaar 57634c54eb6SBram Moolenaar // The return value should be on top of the stack. However, when aborting 57734c54eb6SBram Moolenaar // it may not be there and ec_frame_idx is the top of the stack. 57834c54eb6SBram Moolenaar ret_idx = ectx->ec_stack.ga_len - 1; 5790186e586SBram Moolenaar if (ret_idx == ectx->ec_frame_idx + STACK_FRAME_IDX_OFF) 58034c54eb6SBram Moolenaar ret_idx = 0; 58134c54eb6SBram Moolenaar 5820186e586SBram Moolenaar vim_free(ectx->ec_outer); 5830186e586SBram Moolenaar 584170fcfcfSBram Moolenaar // Restore the previous frame. 58512d26531SBram Moolenaar ectx->ec_dfunc_idx = prev_dfunc_idx; 5860186e586SBram Moolenaar ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx 5870186e586SBram Moolenaar + STACK_FRAME_IIDX_OFF)->vval.v_number; 5880186e586SBram Moolenaar ectx->ec_outer = (void *)STACK_TV(ectx->ec_frame_idx 5890186e586SBram Moolenaar + STACK_FRAME_OUTER_OFF)->vval.v_string; 5905366e1aeSBram Moolenaar // restoring ec_frame_idx must be last 5910186e586SBram Moolenaar ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx 5920186e586SBram Moolenaar + STACK_FRAME_IDX_OFF)->vval.v_number; 59312d26531SBram Moolenaar ectx->ec_instr = INSTRUCTIONS(prev_dfunc); 594170fcfcfSBram Moolenaar 59534c54eb6SBram Moolenaar if (ret_idx > 0) 59634c54eb6SBram Moolenaar { 59734c54eb6SBram Moolenaar // Reset the stack to the position before the call, with a spot for the 59834c54eb6SBram Moolenaar // return value, moved there from above the frame. 599170fcfcfSBram Moolenaar ectx->ec_stack.ga_len = top + 1; 60034c54eb6SBram Moolenaar *STACK_TV_BOT(-1) = *STACK_TV(ret_idx); 60134c54eb6SBram Moolenaar } 60234c54eb6SBram Moolenaar else 60334c54eb6SBram Moolenaar // Reset the stack to the position before the call. 60434c54eb6SBram Moolenaar ectx->ec_stack.ga_len = top; 605bf67ea1aSBram Moolenaar 6060ba48e8cSBram Moolenaar funcdepth_decrement(); 607bf67ea1aSBram Moolenaar return OK; 6088a7d6542SBram Moolenaar } 6098a7d6542SBram Moolenaar 6108a7d6542SBram Moolenaar #undef STACK_TV 6118a7d6542SBram Moolenaar 6128a7d6542SBram Moolenaar /* 6138a7d6542SBram Moolenaar * Prepare arguments and rettv for calling a builtin or user function. 6148a7d6542SBram Moolenaar */ 6158a7d6542SBram Moolenaar static int 6168a7d6542SBram Moolenaar call_prepare(int argcount, typval_T *argvars, ectx_T *ectx) 6178a7d6542SBram Moolenaar { 6188a7d6542SBram Moolenaar int idx; 6198a7d6542SBram Moolenaar typval_T *tv; 6208a7d6542SBram Moolenaar 6218a7d6542SBram Moolenaar // Move arguments from bottom of the stack to argvars[] and add terminator. 6228a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 6238a7d6542SBram Moolenaar argvars[idx] = *STACK_TV_BOT(idx - argcount); 6248a7d6542SBram Moolenaar argvars[argcount].v_type = VAR_UNKNOWN; 6258a7d6542SBram Moolenaar 6268a7d6542SBram Moolenaar // Result replaces the arguments on the stack. 6278a7d6542SBram Moolenaar if (argcount > 0) 6288a7d6542SBram Moolenaar ectx->ec_stack.ga_len -= argcount - 1; 629270d0388SBram Moolenaar else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) 6308a7d6542SBram Moolenaar return FAIL; 6318a7d6542SBram Moolenaar else 6328a7d6542SBram Moolenaar ++ectx->ec_stack.ga_len; 6338a7d6542SBram Moolenaar 6348a7d6542SBram Moolenaar // Default return value is zero. 6358a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 6368a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 6378a7d6542SBram Moolenaar tv->vval.v_number = 0; 6388a7d6542SBram Moolenaar 6398a7d6542SBram Moolenaar return OK; 6408a7d6542SBram Moolenaar } 6418a7d6542SBram Moolenaar 64208f7a41bSBram Moolenaar // Ugly global to avoid passing the execution context around through many 64308f7a41bSBram Moolenaar // layers. 64408f7a41bSBram Moolenaar static ectx_T *current_ectx = NULL; 64508f7a41bSBram Moolenaar 6468a7d6542SBram Moolenaar /* 6478a7d6542SBram Moolenaar * Call a builtin function by index. 6488a7d6542SBram Moolenaar */ 6498a7d6542SBram Moolenaar static int 6508a7d6542SBram Moolenaar call_bfunc(int func_idx, int argcount, ectx_T *ectx) 6518a7d6542SBram Moolenaar { 6528a7d6542SBram Moolenaar typval_T argvars[MAX_FUNC_ARGS]; 6538a7d6542SBram Moolenaar int idx; 654171fb923SBram Moolenaar int did_emsg_before = did_emsg; 65508f7a41bSBram Moolenaar ectx_T *prev_ectx = current_ectx; 6568a7d6542SBram Moolenaar 6578a7d6542SBram Moolenaar if (call_prepare(argcount, argvars, ectx) == FAIL) 6588a7d6542SBram Moolenaar return FAIL; 6598a7d6542SBram Moolenaar 66008f7a41bSBram Moolenaar // Call the builtin function. Set "current_ectx" so that when it 66108f7a41bSBram Moolenaar // recursively invokes call_def_function() a closure context can be set. 66208f7a41bSBram Moolenaar current_ectx = ectx; 6638a7d6542SBram Moolenaar call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1)); 66408f7a41bSBram Moolenaar current_ectx = prev_ectx; 6658a7d6542SBram Moolenaar 6668a7d6542SBram Moolenaar // Clear the arguments. 6678a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 6688a7d6542SBram Moolenaar clear_tv(&argvars[idx]); 669015f4267SBram Moolenaar 67057f799e6SBram Moolenaar if (did_emsg > did_emsg_before) 671015f4267SBram Moolenaar return FAIL; 6728a7d6542SBram Moolenaar return OK; 6738a7d6542SBram Moolenaar } 6748a7d6542SBram Moolenaar 6758a7d6542SBram Moolenaar /* 6768a7d6542SBram Moolenaar * Execute a user defined function. 677ab360526SBram Moolenaar * If the function is compiled this will add a stack frame and set the 678ab360526SBram Moolenaar * instruction pointer at the start of the function. 679ab360526SBram Moolenaar * Otherwise the function is called here. 6800186e586SBram Moolenaar * If "pt" is not null use "pt->pt_outer" for ec_outer. 6817eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 6828a7d6542SBram Moolenaar */ 6838a7d6542SBram Moolenaar static int 6840186e586SBram Moolenaar call_ufunc( 6850186e586SBram Moolenaar ufunc_T *ufunc, 6860186e586SBram Moolenaar partial_T *pt, 6870186e586SBram Moolenaar int argcount, 6880186e586SBram Moolenaar ectx_T *ectx, 6890186e586SBram Moolenaar isn_T *iptr) 6908a7d6542SBram Moolenaar { 6918a7d6542SBram Moolenaar typval_T argvars[MAX_FUNC_ARGS]; 6928a7d6542SBram Moolenaar funcexe_T funcexe; 6938a7d6542SBram Moolenaar int error; 6948a7d6542SBram Moolenaar int idx; 69528ee892aSBram Moolenaar int did_emsg_before = did_emsg; 696f002a41dSBram Moolenaar #ifdef FEAT_PROFILE 697b2049903SBram Moolenaar int profiling = do_profiling == PROF_YES && ufunc->uf_profiling; 698f002a41dSBram Moolenaar #else 699f002a41dSBram Moolenaar # define profiling FALSE 700f002a41dSBram Moolenaar #endif 7018a7d6542SBram Moolenaar 702b2049903SBram Moolenaar if (func_needs_compiling(ufunc, profiling) 703b2049903SBram Moolenaar && compile_def_function(ufunc, FALSE, profiling, NULL) == FAIL) 704822ba247SBram Moolenaar return FAIL; 7050cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_COMPILED) 7067eeefd4aSBram Moolenaar { 70752c124d3SBram Moolenaar error = check_user_func_argcount(ufunc, argcount); 7085082471fSBram Moolenaar if (error != FCERR_UNKNOWN) 7095082471fSBram Moolenaar { 7105082471fSBram Moolenaar if (error == FCERR_TOOMANY) 7115082471fSBram Moolenaar semsg(_(e_toomanyarg), ufunc->uf_name); 7125082471fSBram Moolenaar else 7135082471fSBram Moolenaar semsg(_(e_toofewarg), ufunc->uf_name); 7145082471fSBram Moolenaar return FAIL; 7155082471fSBram Moolenaar } 7165082471fSBram Moolenaar 7177eeefd4aSBram Moolenaar // The function has been compiled, can call it quickly. For a function 7187eeefd4aSBram Moolenaar // that was defined later: we can call it directly next time. 719cd45ed03SBram Moolenaar // TODO: what if the function was deleted and then defined again? 7207eeefd4aSBram Moolenaar if (iptr != NULL) 7217eeefd4aSBram Moolenaar { 72220431c9dSBram Moolenaar delete_instr(iptr); 7237eeefd4aSBram Moolenaar iptr->isn_type = ISN_DCALL; 7247eeefd4aSBram Moolenaar iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx; 7257eeefd4aSBram Moolenaar iptr->isn_arg.dfunc.cdf_argcount = argcount; 7267eeefd4aSBram Moolenaar } 7270186e586SBram Moolenaar return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, ectx); 7287eeefd4aSBram Moolenaar } 7298a7d6542SBram Moolenaar 7308a7d6542SBram Moolenaar if (call_prepare(argcount, argvars, ectx) == FAIL) 7318a7d6542SBram Moolenaar return FAIL; 732a80faa89SBram Moolenaar CLEAR_FIELD(funcexe); 7338a7d6542SBram Moolenaar funcexe.evaluate = TRUE; 7348a7d6542SBram Moolenaar 7358a7d6542SBram Moolenaar // Call the user function. Result goes in last position on the stack. 7368a7d6542SBram Moolenaar // TODO: add selfdict if there is one 7378a7d6542SBram Moolenaar error = call_user_func_check(ufunc, argcount, argvars, 7388a7d6542SBram Moolenaar STACK_TV_BOT(-1), &funcexe, NULL); 7398a7d6542SBram Moolenaar 7408a7d6542SBram Moolenaar // Clear the arguments. 7418a7d6542SBram Moolenaar for (idx = 0; idx < argcount; ++idx) 7428a7d6542SBram Moolenaar clear_tv(&argvars[idx]); 7438a7d6542SBram Moolenaar 7448a7d6542SBram Moolenaar if (error != FCERR_NONE) 7458a7d6542SBram Moolenaar { 7468a7d6542SBram Moolenaar user_func_error(error, ufunc->uf_name); 7478a7d6542SBram Moolenaar return FAIL; 7488a7d6542SBram Moolenaar } 74928ee892aSBram Moolenaar if (did_emsg > did_emsg_before) 750ed677f55SBram Moolenaar // Error other than from calling the function itself. 751ed677f55SBram Moolenaar return FAIL; 7528a7d6542SBram Moolenaar return OK; 7538a7d6542SBram Moolenaar } 7548a7d6542SBram Moolenaar 7558a7d6542SBram Moolenaar /* 756a177344dSBram Moolenaar * Return TRUE if an error was given or CTRL-C was pressed. 757a177344dSBram Moolenaar */ 758a177344dSBram Moolenaar static int 759a177344dSBram Moolenaar vim9_aborting(int prev_called_emsg) 760a177344dSBram Moolenaar { 761a177344dSBram Moolenaar return called_emsg > prev_called_emsg || got_int || did_throw; 762a177344dSBram Moolenaar } 763a177344dSBram Moolenaar 764a177344dSBram Moolenaar /* 7658a7d6542SBram Moolenaar * Execute a function by "name". 7668a7d6542SBram Moolenaar * This can be a builtin function or a user function. 7677eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 7688a7d6542SBram Moolenaar * Returns FAIL if not found without an error message. 7698a7d6542SBram Moolenaar */ 7708a7d6542SBram Moolenaar static int 7717eeefd4aSBram Moolenaar call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) 7728a7d6542SBram Moolenaar { 7738a7d6542SBram Moolenaar ufunc_T *ufunc; 7748a7d6542SBram Moolenaar 7758a7d6542SBram Moolenaar if (builtin_function(name, -1)) 7768a7d6542SBram Moolenaar { 7778a7d6542SBram Moolenaar int func_idx = find_internal_func(name); 7788a7d6542SBram Moolenaar 7798a7d6542SBram Moolenaar if (func_idx < 0) 7808a7d6542SBram Moolenaar return FAIL; 781389df259SBram Moolenaar if (check_internal_func(func_idx, argcount) < 0) 7828a7d6542SBram Moolenaar return FAIL; 7838a7d6542SBram Moolenaar return call_bfunc(func_idx, argcount, ectx); 7848a7d6542SBram Moolenaar } 7858a7d6542SBram Moolenaar 7864c17ad94SBram Moolenaar ufunc = find_func(name, FALSE, NULL); 787a177344dSBram Moolenaar 788a177344dSBram Moolenaar if (ufunc == NULL) 789a177344dSBram Moolenaar { 790a177344dSBram Moolenaar int called_emsg_before = called_emsg; 791a177344dSBram Moolenaar 792a177344dSBram Moolenaar if (script_autoload(name, TRUE)) 793a177344dSBram Moolenaar // loaded a package, search for the function again 794a177344dSBram Moolenaar ufunc = find_func(name, FALSE, NULL); 795a177344dSBram Moolenaar if (vim9_aborting(called_emsg_before)) 796a177344dSBram Moolenaar return FAIL; // bail out if loading the script caused an error 797a177344dSBram Moolenaar } 798a177344dSBram Moolenaar 7998a7d6542SBram Moolenaar if (ufunc != NULL) 80004947cc6SBram Moolenaar { 80104947cc6SBram Moolenaar if (ufunc->uf_arg_types != NULL) 80204947cc6SBram Moolenaar { 80304947cc6SBram Moolenaar int i; 80404947cc6SBram Moolenaar typval_T *argv = STACK_TV_BOT(0) - argcount; 80504947cc6SBram Moolenaar 80604947cc6SBram Moolenaar // The function can change at runtime, check that the argument 80704947cc6SBram Moolenaar // types are correct. 80804947cc6SBram Moolenaar for (i = 0; i < argcount; ++i) 80904947cc6SBram Moolenaar { 810e3ffcd99SBram Moolenaar type_T *type = NULL; 81104947cc6SBram Moolenaar 812e3ffcd99SBram Moolenaar if (i < ufunc->uf_args.ga_len) 813e3ffcd99SBram Moolenaar type = ufunc->uf_arg_types[i]; 814e3ffcd99SBram Moolenaar else if (ufunc->uf_va_type != NULL) 815e3ffcd99SBram Moolenaar type = ufunc->uf_va_type->tt_member; 81604947cc6SBram Moolenaar if (type != NULL && check_typval_arg_type(type, 81704947cc6SBram Moolenaar &argv[i], i + 1) == FAIL) 81804947cc6SBram Moolenaar return FAIL; 81904947cc6SBram Moolenaar } 82004947cc6SBram Moolenaar } 82104947cc6SBram Moolenaar 8220186e586SBram Moolenaar return call_ufunc(ufunc, NULL, argcount, ectx, iptr); 82304947cc6SBram Moolenaar } 8248a7d6542SBram Moolenaar 8258a7d6542SBram Moolenaar return FAIL; 8268a7d6542SBram Moolenaar } 8278a7d6542SBram Moolenaar 8288a7d6542SBram Moolenaar static int 829a90afb9aSBram Moolenaar call_partial(typval_T *tv, int argcount_arg, ectx_T *ectx) 8308a7d6542SBram Moolenaar { 831a90afb9aSBram Moolenaar int argcount = argcount_arg; 832bd5da371SBram Moolenaar char_u *name = NULL; 8338a7d6542SBram Moolenaar int called_emsg_before = called_emsg; 834cb6cbf29SBram Moolenaar int res = FAIL; 8358a7d6542SBram Moolenaar 8368a7d6542SBram Moolenaar if (tv->v_type == VAR_PARTIAL) 8378a7d6542SBram Moolenaar { 8388a7d6542SBram Moolenaar partial_T *pt = tv->vval.v_partial; 839a90afb9aSBram Moolenaar int i; 840a90afb9aSBram Moolenaar 841a90afb9aSBram Moolenaar if (pt->pt_argc > 0) 842a90afb9aSBram Moolenaar { 843a90afb9aSBram Moolenaar // Make space for arguments from the partial, shift the "argcount" 844a90afb9aSBram Moolenaar // arguments up. 845a90afb9aSBram Moolenaar if (ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL) 846a90afb9aSBram Moolenaar return FAIL; 847a90afb9aSBram Moolenaar for (i = 1; i <= argcount; ++i) 848a90afb9aSBram Moolenaar *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i); 849a90afb9aSBram Moolenaar ectx->ec_stack.ga_len += pt->pt_argc; 850a90afb9aSBram Moolenaar argcount += pt->pt_argc; 851a90afb9aSBram Moolenaar 852a90afb9aSBram Moolenaar // copy the arguments from the partial onto the stack 853a90afb9aSBram Moolenaar for (i = 0; i < pt->pt_argc; ++i) 854a90afb9aSBram Moolenaar copy_tv(&pt->pt_argv[i], STACK_TV_BOT(-argcount + i)); 855a90afb9aSBram Moolenaar } 8568a7d6542SBram Moolenaar 8578a7d6542SBram Moolenaar if (pt->pt_func != NULL) 8580186e586SBram Moolenaar return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL); 859f7779c63SBram Moolenaar 8608a7d6542SBram Moolenaar name = pt->pt_name; 8618a7d6542SBram Moolenaar } 862bd5da371SBram Moolenaar else if (tv->v_type == VAR_FUNC) 8638a7d6542SBram Moolenaar name = tv->vval.v_string; 86495006e3dSBram Moolenaar if (name != NULL) 86595006e3dSBram Moolenaar { 86695006e3dSBram Moolenaar char_u fname_buf[FLEN_FIXED + 1]; 86795006e3dSBram Moolenaar char_u *tofree = NULL; 86895006e3dSBram Moolenaar int error = FCERR_NONE; 86995006e3dSBram Moolenaar char_u *fname; 87095006e3dSBram Moolenaar 87195006e3dSBram Moolenaar // May need to translate <SNR>123_ to K_SNR. 87295006e3dSBram Moolenaar fname = fname_trans_sid(name, fname_buf, &tofree, &error); 87395006e3dSBram Moolenaar if (error != FCERR_NONE) 87495006e3dSBram Moolenaar res = FAIL; 87595006e3dSBram Moolenaar else 87695006e3dSBram Moolenaar res = call_by_name(fname, argcount, ectx, NULL); 87795006e3dSBram Moolenaar vim_free(tofree); 87895006e3dSBram Moolenaar } 87995006e3dSBram Moolenaar 880cb6cbf29SBram Moolenaar if (res == FAIL) 8818a7d6542SBram Moolenaar { 8828a7d6542SBram Moolenaar if (called_emsg == called_emsg_before) 883015f4267SBram Moolenaar semsg(_(e_unknownfunc), 884015f4267SBram Moolenaar name == NULL ? (char_u *)"[unknown]" : name); 8858a7d6542SBram Moolenaar return FAIL; 8868a7d6542SBram Moolenaar } 8878a7d6542SBram Moolenaar return OK; 8888a7d6542SBram Moolenaar } 8898a7d6542SBram Moolenaar 8908a7d6542SBram Moolenaar /* 8910b4c66c6SBram Moolenaar * Check if "lock" is VAR_LOCKED or VAR_FIXED. If so give an error and return 8920b4c66c6SBram Moolenaar * TRUE. 8930b4c66c6SBram Moolenaar */ 8940b4c66c6SBram Moolenaar static int 8950b4c66c6SBram Moolenaar error_if_locked(int lock, char *error) 8960b4c66c6SBram Moolenaar { 8970b4c66c6SBram Moolenaar if (lock & (VAR_LOCKED | VAR_FIXED)) 8980b4c66c6SBram Moolenaar { 8990b4c66c6SBram Moolenaar emsg(_(error)); 9000b4c66c6SBram Moolenaar return TRUE; 9010b4c66c6SBram Moolenaar } 9020b4c66c6SBram Moolenaar return FALSE; 9030b4c66c6SBram Moolenaar } 9040b4c66c6SBram Moolenaar 9050b4c66c6SBram Moolenaar /* 9065b5ae29bSBram Moolenaar * Give an error if "tv" is not a number and return FAIL. 9075b5ae29bSBram Moolenaar */ 9085b5ae29bSBram Moolenaar static int 9095b5ae29bSBram Moolenaar check_for_number(typval_T *tv) 9105b5ae29bSBram Moolenaar { 9115b5ae29bSBram Moolenaar if (tv->v_type != VAR_NUMBER) 9125b5ae29bSBram Moolenaar { 9135b5ae29bSBram Moolenaar semsg(_(e_expected_str_but_got_str), 9145b5ae29bSBram Moolenaar vartype_name(VAR_NUMBER), vartype_name(tv->v_type)); 9155b5ae29bSBram Moolenaar return FAIL; 9165b5ae29bSBram Moolenaar } 9175b5ae29bSBram Moolenaar return OK; 9185b5ae29bSBram Moolenaar } 9195b5ae29bSBram Moolenaar 9205b5ae29bSBram Moolenaar /* 9210bbf722aSBram Moolenaar * Store "tv" in variable "name". 9220bbf722aSBram Moolenaar * This is for s: and g: variables. 9230bbf722aSBram Moolenaar */ 9240bbf722aSBram Moolenaar static void 9250bbf722aSBram Moolenaar store_var(char_u *name, typval_T *tv) 9260bbf722aSBram Moolenaar { 9270bbf722aSBram Moolenaar funccal_entry_T entry; 9280bbf722aSBram Moolenaar 9290bbf722aSBram Moolenaar save_funccal(&entry); 930f785aa13SBram Moolenaar set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL, 0); 9310bbf722aSBram Moolenaar restore_funccal(); 9320bbf722aSBram Moolenaar } 9330bbf722aSBram Moolenaar 9343beaf9cdSBram Moolenaar /* 9354f5e3977SBram Moolenaar * Convert "tv" to a string. 9364f5e3977SBram Moolenaar * Return FAIL if not allowed. 9374f5e3977SBram Moolenaar */ 9384f5e3977SBram Moolenaar static int 9394f5e3977SBram Moolenaar do_2string(typval_T *tv, int is_2string_any) 9404f5e3977SBram Moolenaar { 9414f5e3977SBram Moolenaar if (tv->v_type != VAR_STRING) 9424f5e3977SBram Moolenaar { 9434f5e3977SBram Moolenaar char_u *str; 9444f5e3977SBram Moolenaar 9454f5e3977SBram Moolenaar if (is_2string_any) 9464f5e3977SBram Moolenaar { 9474f5e3977SBram Moolenaar switch (tv->v_type) 9484f5e3977SBram Moolenaar { 9494f5e3977SBram Moolenaar case VAR_SPECIAL: 9504f5e3977SBram Moolenaar case VAR_BOOL: 9514f5e3977SBram Moolenaar case VAR_NUMBER: 9524f5e3977SBram Moolenaar case VAR_FLOAT: 9534f5e3977SBram Moolenaar case VAR_BLOB: break; 9544f5e3977SBram Moolenaar default: to_string_error(tv->v_type); 9554f5e3977SBram Moolenaar return FAIL; 9564f5e3977SBram Moolenaar } 9574f5e3977SBram Moolenaar } 95834453208SBram Moolenaar str = typval_tostring(tv, TRUE); 9594f5e3977SBram Moolenaar clear_tv(tv); 9604f5e3977SBram Moolenaar tv->v_type = VAR_STRING; 9614f5e3977SBram Moolenaar tv->vval.v_string = str; 9624f5e3977SBram Moolenaar } 9634f5e3977SBram Moolenaar return OK; 9644f5e3977SBram Moolenaar } 9654f5e3977SBram Moolenaar 9664f5e3977SBram Moolenaar /* 9673beaf9cdSBram Moolenaar * When the value of "sv" is a null list of dict, allocate it. 9683beaf9cdSBram Moolenaar */ 9693beaf9cdSBram Moolenaar static void 9703beaf9cdSBram Moolenaar allocate_if_null(typval_T *tv) 9713beaf9cdSBram Moolenaar { 9723beaf9cdSBram Moolenaar switch (tv->v_type) 9733beaf9cdSBram Moolenaar { 9743beaf9cdSBram Moolenaar case VAR_LIST: 9753beaf9cdSBram Moolenaar if (tv->vval.v_list == NULL) 976fef8064bSBram Moolenaar (void)rettv_list_alloc(tv); 9773beaf9cdSBram Moolenaar break; 9783beaf9cdSBram Moolenaar case VAR_DICT: 9793beaf9cdSBram Moolenaar if (tv->vval.v_dict == NULL) 980fef8064bSBram Moolenaar (void)rettv_dict_alloc(tv); 9813beaf9cdSBram Moolenaar break; 9823beaf9cdSBram Moolenaar default: 9833beaf9cdSBram Moolenaar break; 9843beaf9cdSBram Moolenaar } 9853beaf9cdSBram Moolenaar } 986d3aac291SBram Moolenaar 987e7525c55SBram Moolenaar /* 988e7525c55SBram Moolenaar * Return the character "str[index]" where "index" is the character index. If 989e7525c55SBram Moolenaar * "index" is out of range NULL is returned. 990e7525c55SBram Moolenaar */ 991e7525c55SBram Moolenaar char_u * 992e7525c55SBram Moolenaar char_from_string(char_u *str, varnumber_T index) 993e7525c55SBram Moolenaar { 994e7525c55SBram Moolenaar size_t nbyte = 0; 995e7525c55SBram Moolenaar varnumber_T nchar = index; 996e7525c55SBram Moolenaar size_t slen; 997e7525c55SBram Moolenaar 998e7525c55SBram Moolenaar if (str == NULL) 999e7525c55SBram Moolenaar return NULL; 1000e7525c55SBram Moolenaar slen = STRLEN(str); 1001e7525c55SBram Moolenaar 1002e7525c55SBram Moolenaar // do the same as for a list: a negative index counts from the end 1003e7525c55SBram Moolenaar if (index < 0) 1004e7525c55SBram Moolenaar { 1005e7525c55SBram Moolenaar int clen = 0; 1006e7525c55SBram Moolenaar 1007e7525c55SBram Moolenaar for (nbyte = 0; nbyte < slen; ++clen) 1008e7525c55SBram Moolenaar nbyte += MB_CPTR2LEN(str + nbyte); 1009e7525c55SBram Moolenaar nchar = clen + index; 1010e7525c55SBram Moolenaar if (nchar < 0) 1011e7525c55SBram Moolenaar // unlike list: index out of range results in empty string 1012e7525c55SBram Moolenaar return NULL; 1013e7525c55SBram Moolenaar } 1014e7525c55SBram Moolenaar 1015e7525c55SBram Moolenaar for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar) 1016e7525c55SBram Moolenaar nbyte += MB_CPTR2LEN(str + nbyte); 1017e7525c55SBram Moolenaar if (nbyte >= slen) 1018e7525c55SBram Moolenaar return NULL; 1019e7525c55SBram Moolenaar return vim_strnsave(str + nbyte, MB_CPTR2LEN(str + nbyte)); 1020e7525c55SBram Moolenaar } 1021e7525c55SBram Moolenaar 1022e7525c55SBram Moolenaar /* 1023e7525c55SBram Moolenaar * Get the byte index for character index "idx" in string "str" with length 1024e7525c55SBram Moolenaar * "str_len". 1025e7525c55SBram Moolenaar * If going over the end return "str_len". 1026e7525c55SBram Moolenaar * If "idx" is negative count from the end, -1 is the last character. 1027e7525c55SBram Moolenaar * When going over the start return -1. 1028e7525c55SBram Moolenaar */ 1029e7525c55SBram Moolenaar static long 1030e7525c55SBram Moolenaar char_idx2byte(char_u *str, size_t str_len, varnumber_T idx) 1031e7525c55SBram Moolenaar { 1032e7525c55SBram Moolenaar varnumber_T nchar = idx; 1033e7525c55SBram Moolenaar size_t nbyte = 0; 1034e7525c55SBram Moolenaar 1035e7525c55SBram Moolenaar if (nchar >= 0) 1036e7525c55SBram Moolenaar { 1037e7525c55SBram Moolenaar while (nchar > 0 && nbyte < str_len) 1038e7525c55SBram Moolenaar { 1039e7525c55SBram Moolenaar nbyte += MB_CPTR2LEN(str + nbyte); 1040e7525c55SBram Moolenaar --nchar; 1041e7525c55SBram Moolenaar } 1042e7525c55SBram Moolenaar } 1043e7525c55SBram Moolenaar else 1044e7525c55SBram Moolenaar { 1045e7525c55SBram Moolenaar nbyte = str_len; 1046e7525c55SBram Moolenaar while (nchar < 0 && nbyte > 0) 1047e7525c55SBram Moolenaar { 1048e7525c55SBram Moolenaar --nbyte; 1049e7525c55SBram Moolenaar nbyte -= mb_head_off(str, str + nbyte); 1050e7525c55SBram Moolenaar ++nchar; 1051e7525c55SBram Moolenaar } 1052e7525c55SBram Moolenaar if (nchar < 0) 1053e7525c55SBram Moolenaar return -1; 1054e7525c55SBram Moolenaar } 1055e7525c55SBram Moolenaar return (long)nbyte; 1056e7525c55SBram Moolenaar } 1057e7525c55SBram Moolenaar 1058e7525c55SBram Moolenaar /* 1059e7525c55SBram Moolenaar * Return the slice "str[first:last]" using character indexes. 10606601b629SBram Moolenaar * "exclusive" is TRUE for slice(). 1061e7525c55SBram Moolenaar * Return NULL when the result is empty. 1062e7525c55SBram Moolenaar */ 1063e7525c55SBram Moolenaar char_u * 10646601b629SBram Moolenaar string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive) 1065e7525c55SBram Moolenaar { 1066e7525c55SBram Moolenaar long start_byte, end_byte; 1067e7525c55SBram Moolenaar size_t slen; 1068e7525c55SBram Moolenaar 1069e7525c55SBram Moolenaar if (str == NULL) 1070e7525c55SBram Moolenaar return NULL; 1071e7525c55SBram Moolenaar slen = STRLEN(str); 1072e7525c55SBram Moolenaar start_byte = char_idx2byte(str, slen, first); 1073e7525c55SBram Moolenaar if (start_byte < 0) 1074e7525c55SBram Moolenaar start_byte = 0; // first index very negative: use zero 10756601b629SBram Moolenaar if ((last == -1 && !exclusive) || last == VARNUM_MAX) 1076e7525c55SBram Moolenaar end_byte = (long)slen; 1077e7525c55SBram Moolenaar else 1078e7525c55SBram Moolenaar { 1079e7525c55SBram Moolenaar end_byte = char_idx2byte(str, slen, last); 10806601b629SBram Moolenaar if (!exclusive && end_byte >= 0 && end_byte < (long)slen) 1081e7525c55SBram Moolenaar // end index is inclusive 1082e7525c55SBram Moolenaar end_byte += MB_CPTR2LEN(str + end_byte); 1083e7525c55SBram Moolenaar } 1084e7525c55SBram Moolenaar 1085e7525c55SBram Moolenaar if (start_byte >= (long)slen || end_byte <= start_byte) 1086e7525c55SBram Moolenaar return NULL; 1087e7525c55SBram Moolenaar return vim_strnsave(str + start_byte, end_byte - start_byte); 1088e7525c55SBram Moolenaar } 1089e7525c55SBram Moolenaar 109007a65d26SBram Moolenaar static svar_T * 109107a65d26SBram Moolenaar get_script_svar(scriptref_T *sref, ectx_T *ectx) 109207a65d26SBram Moolenaar { 109307a65d26SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid); 109407a65d26SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 109507a65d26SBram Moolenaar + ectx->ec_dfunc_idx; 109607a65d26SBram Moolenaar svar_T *sv; 109707a65d26SBram Moolenaar 109807a65d26SBram Moolenaar if (sref->sref_seq != si->sn_script_seq) 109907a65d26SBram Moolenaar { 110007a65d26SBram Moolenaar // The script was reloaded after the function was 110107a65d26SBram Moolenaar // compiled, the script_idx may not be valid. 110207a65d26SBram Moolenaar semsg(_(e_script_variable_invalid_after_reload_in_function_str), 110307a65d26SBram Moolenaar dfunc->df_ufunc->uf_name_exp); 110407a65d26SBram Moolenaar return NULL; 110507a65d26SBram Moolenaar } 110607a65d26SBram Moolenaar sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx; 110707a65d26SBram Moolenaar if (!equal_type(sv->sv_type, sref->sref_type)) 110807a65d26SBram Moolenaar { 110907a65d26SBram Moolenaar emsg(_(e_script_variable_type_changed)); 111007a65d26SBram Moolenaar return NULL; 111107a65d26SBram Moolenaar } 111207a65d26SBram Moolenaar return sv; 111307a65d26SBram Moolenaar } 111407a65d26SBram Moolenaar 11150bbf722aSBram Moolenaar /* 11168a7d6542SBram Moolenaar * Execute a function by "name". 11178a7d6542SBram Moolenaar * This can be a builtin function, user function or a funcref. 11187eeefd4aSBram Moolenaar * "iptr" can be used to replace the instruction with a more efficient one. 11198a7d6542SBram Moolenaar */ 11208a7d6542SBram Moolenaar static int 11217eeefd4aSBram Moolenaar call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) 11228a7d6542SBram Moolenaar { 11238a7d6542SBram Moolenaar int called_emsg_before = called_emsg; 1124ed677f55SBram Moolenaar int res; 11258a7d6542SBram Moolenaar 1126ed677f55SBram Moolenaar res = call_by_name(name, argcount, ectx, iptr); 1127ed677f55SBram Moolenaar if (res == FAIL && called_emsg == called_emsg_before) 11288a7d6542SBram Moolenaar { 11291df8b3fbSBram Moolenaar dictitem_T *v; 11301df8b3fbSBram Moolenaar 11311df8b3fbSBram Moolenaar v = find_var(name, NULL, FALSE); 11321df8b3fbSBram Moolenaar if (v == NULL) 11331df8b3fbSBram Moolenaar { 11341df8b3fbSBram Moolenaar semsg(_(e_unknownfunc), name); 11358a7d6542SBram Moolenaar return FAIL; 11368a7d6542SBram Moolenaar } 11371df8b3fbSBram Moolenaar if (v->di_tv.v_type != VAR_PARTIAL && v->di_tv.v_type != VAR_FUNC) 11381df8b3fbSBram Moolenaar { 11391df8b3fbSBram Moolenaar semsg(_(e_unknownfunc), name); 11401df8b3fbSBram Moolenaar return FAIL; 11411df8b3fbSBram Moolenaar } 11421df8b3fbSBram Moolenaar return call_partial(&v->di_tv, argcount, ectx); 11431df8b3fbSBram Moolenaar } 1144ed677f55SBram Moolenaar return res; 11458a7d6542SBram Moolenaar } 11468a7d6542SBram Moolenaar 11478a7d6542SBram Moolenaar /* 1148f112f30aSBram Moolenaar * When a function reference is used, fill a partial with the information 1149f112f30aSBram Moolenaar * needed, especially when it is used as a closure. 1150f112f30aSBram Moolenaar */ 1151cd45ed03SBram Moolenaar int 1152f112f30aSBram Moolenaar fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx) 1153f112f30aSBram Moolenaar { 1154f112f30aSBram Moolenaar pt->pt_func = ufunc; 1155f112f30aSBram Moolenaar pt->pt_refcount = 1; 1156f112f30aSBram Moolenaar 11570d3de8cbSBram Moolenaar if (ufunc->uf_flags & FC_CLOSURE) 1158f112f30aSBram Moolenaar { 1159f112f30aSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 1160f112f30aSBram Moolenaar + ectx->ec_dfunc_idx; 1161f112f30aSBram Moolenaar 1162f112f30aSBram Moolenaar // The closure needs to find arguments and local 1163f112f30aSBram Moolenaar // variables in the current stack. 11640186e586SBram Moolenaar pt->pt_outer.out_stack = &ectx->ec_stack; 11650186e586SBram Moolenaar pt->pt_outer.out_frame_idx = ectx->ec_frame_idx; 11660186e586SBram Moolenaar pt->pt_outer.out_up = ectx->ec_outer; 11670186e586SBram Moolenaar pt->pt_outer.out_up_is_copy = TRUE; 1168f112f30aSBram Moolenaar 1169f112f30aSBram Moolenaar // If this function returns and the closure is still 1170f112f30aSBram Moolenaar // being used, we need to make a copy of the context 1171f112f30aSBram Moolenaar // (arguments and local variables). Store a reference 1172f112f30aSBram Moolenaar // to the partial so we can handle that. 1173f112f30aSBram Moolenaar if (ga_grow(&ectx->ec_funcrefs, 1) == FAIL) 1174f112f30aSBram Moolenaar { 1175f112f30aSBram Moolenaar vim_free(pt); 1176f112f30aSBram Moolenaar return FAIL; 1177f112f30aSBram Moolenaar } 1178f112f30aSBram Moolenaar // Extra variable keeps the count of closures created 1179f112f30aSBram Moolenaar // in the current function call. 1180f112f30aSBram Moolenaar ++(((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx 1181f112f30aSBram Moolenaar + STACK_FRAME_SIZE + dfunc->df_varcount)->vval.v_number; 1182f112f30aSBram Moolenaar 1183f112f30aSBram Moolenaar ((partial_T **)ectx->ec_funcrefs.ga_data) 1184f112f30aSBram Moolenaar [ectx->ec_funcrefs.ga_len] = pt; 1185f112f30aSBram Moolenaar ++pt->pt_refcount; 1186f112f30aSBram Moolenaar ++ectx->ec_funcrefs.ga_len; 1187f112f30aSBram Moolenaar } 11880d3de8cbSBram Moolenaar ++ufunc->uf_refcount; 1189f112f30aSBram Moolenaar return OK; 1190f112f30aSBram Moolenaar } 1191f112f30aSBram Moolenaar 1192e5ea346aSBram Moolenaar 1193f112f30aSBram Moolenaar /* 11948a7d6542SBram Moolenaar * Call a "def" function from old Vim script. 11958a7d6542SBram Moolenaar * Return OK or FAIL. 11968a7d6542SBram Moolenaar */ 11978a7d6542SBram Moolenaar int 11988a7d6542SBram Moolenaar call_def_function( 11998a7d6542SBram Moolenaar ufunc_T *ufunc, 120023e03252SBram Moolenaar int argc_arg, // nr of arguments 12018a7d6542SBram Moolenaar typval_T *argv, // arguments 12026f5b6dfbSBram Moolenaar partial_T *partial, // optional partial for context 12038a7d6542SBram Moolenaar typval_T *rettv) // return value 12048a7d6542SBram Moolenaar { 12058a7d6542SBram Moolenaar ectx_T ectx; // execution context 120623e03252SBram Moolenaar int argc = argc_arg; 1207bf67ea1aSBram Moolenaar int initial_frame_idx; 12088a7d6542SBram Moolenaar typval_T *tv; 12098a7d6542SBram Moolenaar int idx; 12108a7d6542SBram Moolenaar int ret = FAIL; 1211170fcfcfSBram Moolenaar int defcount = ufunc->uf_args.ga_len - argc; 1212ee8580e5SBram Moolenaar sctx_T save_current_sctx = current_sctx; 1213270d0388SBram Moolenaar int breakcheck_count = 0; 1214eeece9e4SBram Moolenaar int did_emsg_before = did_emsg_cumul + did_emsg; 121577e5dcc3SBram Moolenaar int save_suppress_errthrow = suppress_errthrow; 1216352134bbSBram Moolenaar msglist_T **saved_msg_list = NULL; 1217352134bbSBram Moolenaar msglist_T *private_msg_list = NULL; 121802194d2bSBram Moolenaar cmdmod_T save_cmdmod; 121902194d2bSBram Moolenaar int restore_cmdmod = FALSE; 1220f904133eSBram Moolenaar int restore_cmdmod_stacklen = 0; 122156602ba1SBram Moolenaar int save_emsg_silent_def = emsg_silent_def; 122256602ba1SBram Moolenaar int save_did_emsg_def = did_emsg_def; 1223171fb923SBram Moolenaar int trylevel_at_start = trylevel; 12240ba48e8cSBram Moolenaar int orig_funcdepth; 1225f785aa13SBram Moolenaar where_T where; 12268a7d6542SBram Moolenaar 12278a7d6542SBram Moolenaar // Get pointer to item in the stack. 12288a7d6542SBram Moolenaar #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) 12298a7d6542SBram Moolenaar 12308a7d6542SBram Moolenaar // Get pointer to item at the bottom of the stack, -1 is the bottom. 12318a7d6542SBram Moolenaar #undef STACK_TV_BOT 12328a7d6542SBram Moolenaar #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx) 12338a7d6542SBram Moolenaar 12341378fbc4SBram Moolenaar // Get pointer to a local variable on the stack. Negative for arguments. 1235bf67ea1aSBram Moolenaar #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx) 12368a7d6542SBram Moolenaar 12370cb5bcf5SBram Moolenaar if (ufunc->uf_def_status == UF_NOT_COMPILED 1238e5ea346aSBram Moolenaar || (func_needs_compiling(ufunc, PROFILING(ufunc)) 1239e5ea346aSBram Moolenaar && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL) 1240b2049903SBram Moolenaar == FAIL)) 124125e0f586SBram Moolenaar { 1242eeece9e4SBram Moolenaar if (did_emsg_cumul + did_emsg == did_emsg_before) 1243451c2e35SBram Moolenaar semsg(_(e_function_is_not_compiled_str), 1244682d0a15SBram Moolenaar printable_func_name(ufunc)); 1245822ba247SBram Moolenaar return FAIL; 124625e0f586SBram Moolenaar } 1247822ba247SBram Moolenaar 124809689a02SBram Moolenaar { 1249822ba247SBram Moolenaar // Check the function was really compiled. 125009689a02SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 125109689a02SBram Moolenaar + ufunc->uf_dfunc_idx; 1252e5ea346aSBram Moolenaar if (INSTRUCTIONS(dfunc) == NULL) 125338ddf333SBram Moolenaar { 125438ddf333SBram Moolenaar iemsg("using call_def_function() on not compiled function"); 125509689a02SBram Moolenaar return FAIL; 125609689a02SBram Moolenaar } 125738ddf333SBram Moolenaar } 12588a7d6542SBram Moolenaar 12590ba48e8cSBram Moolenaar // If depth of calling is getting too high, don't execute the function. 12600ba48e8cSBram Moolenaar orig_funcdepth = funcdepth_get(); 12610ba48e8cSBram Moolenaar if (funcdepth_increment() == FAIL) 12620ba48e8cSBram Moolenaar return FAIL; 12630ba48e8cSBram Moolenaar 12643b6a6eb7SBram Moolenaar CLEAR_FIELD(ectx); 12653b6a6eb7SBram Moolenaar ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; 12663b6a6eb7SBram Moolenaar ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); 12673b6a6eb7SBram Moolenaar if (ga_grow(&ectx.ec_stack, 20) == FAIL) 12680ba48e8cSBram Moolenaar { 12690ba48e8cSBram Moolenaar funcdepth_decrement(); 12703b6a6eb7SBram Moolenaar return FAIL; 12710ba48e8cSBram Moolenaar } 12728a7d6542SBram Moolenaar ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); 1273148ce7aeSBram Moolenaar ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10); 12748a7d6542SBram Moolenaar 1275fc0e8f5cSBram Moolenaar // Put arguments on the stack, but no more than what the function expects. 1276fc0e8f5cSBram Moolenaar // A lambda can be called with more arguments than it uses. 1277fc0e8f5cSBram Moolenaar for (idx = 0; idx < argc 1278fc0e8f5cSBram Moolenaar && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len); 1279fc0e8f5cSBram Moolenaar ++idx) 12808a7d6542SBram Moolenaar { 128165b9545fSBram Moolenaar if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len 1282f785aa13SBram Moolenaar && check_typval_arg_type(ufunc->uf_arg_types[idx], &argv[idx], 12838b565c2cSBram Moolenaar idx + 1) == FAIL) 128465b9545fSBram Moolenaar goto failed_early; 12858a7d6542SBram Moolenaar copy_tv(&argv[idx], STACK_TV_BOT(0)); 12868a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 12878a7d6542SBram Moolenaar } 128823e03252SBram Moolenaar 128923e03252SBram Moolenaar // Turn varargs into a list. Empty list if no args. 129023e03252SBram Moolenaar if (ufunc->uf_va_name != NULL) 129123e03252SBram Moolenaar { 129223e03252SBram Moolenaar int vararg_count = argc - ufunc->uf_args.ga_len; 129323e03252SBram Moolenaar 129423e03252SBram Moolenaar if (vararg_count < 0) 129523e03252SBram Moolenaar vararg_count = 0; 129623e03252SBram Moolenaar else 129723e03252SBram Moolenaar argc -= vararg_count; 129823e03252SBram Moolenaar if (exe_newlist(vararg_count, &ectx) == FAIL) 12991a2f4bf6SBram Moolenaar goto failed_early; 130024aa48b7SBram Moolenaar 130124aa48b7SBram Moolenaar // Check the type of the list items. 130224aa48b7SBram Moolenaar tv = STACK_TV_BOT(-1); 130324aa48b7SBram Moolenaar if (ufunc->uf_va_type != NULL 13042f8cbc4bSBram Moolenaar && ufunc->uf_va_type != &t_any 130524aa48b7SBram Moolenaar && ufunc->uf_va_type->tt_member != &t_any 130624aa48b7SBram Moolenaar && tv->vval.v_list != NULL) 130724aa48b7SBram Moolenaar { 130824aa48b7SBram Moolenaar type_T *expected = ufunc->uf_va_type->tt_member; 130924aa48b7SBram Moolenaar listitem_T *li = tv->vval.v_list->lv_first; 131024aa48b7SBram Moolenaar 131124aa48b7SBram Moolenaar for (idx = 0; idx < vararg_count; ++idx) 131224aa48b7SBram Moolenaar { 1313f785aa13SBram Moolenaar if (check_typval_arg_type(expected, &li->li_tv, 13148b565c2cSBram Moolenaar argc + idx + 1) == FAIL) 131524aa48b7SBram Moolenaar goto failed_early; 131624aa48b7SBram Moolenaar li = li->li_next; 131724aa48b7SBram Moolenaar } 131824aa48b7SBram Moolenaar } 131924aa48b7SBram Moolenaar 132023e03252SBram Moolenaar if (defcount > 0) 132123e03252SBram Moolenaar // Move varargs list to below missing default arguments. 132223e03252SBram Moolenaar *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1); 132323e03252SBram Moolenaar --ectx.ec_stack.ga_len; 132423e03252SBram Moolenaar } 132523e03252SBram Moolenaar 1326170fcfcfSBram Moolenaar // Make space for omitted arguments, will store default value below. 132723e03252SBram Moolenaar // Any varargs list goes after them. 1328170fcfcfSBram Moolenaar if (defcount > 0) 1329170fcfcfSBram Moolenaar for (idx = 0; idx < defcount; ++idx) 1330170fcfcfSBram Moolenaar { 1331170fcfcfSBram Moolenaar STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; 1332170fcfcfSBram Moolenaar ++ectx.ec_stack.ga_len; 1333170fcfcfSBram Moolenaar } 133423e03252SBram Moolenaar if (ufunc->uf_va_name != NULL) 133523e03252SBram Moolenaar ++ectx.ec_stack.ga_len; 13368a7d6542SBram Moolenaar 13378a7d6542SBram Moolenaar // Frame pointer points to just after arguments. 1338bf67ea1aSBram Moolenaar ectx.ec_frame_idx = ectx.ec_stack.ga_len; 1339bf67ea1aSBram Moolenaar initial_frame_idx = ectx.ec_frame_idx; 13408a7d6542SBram Moolenaar 13410d3de8cbSBram Moolenaar { 13420d3de8cbSBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 13430d3de8cbSBram Moolenaar + ufunc->uf_dfunc_idx; 13440d3de8cbSBram Moolenaar ufunc_T *base_ufunc = dfunc->df_ufunc; 13450d3de8cbSBram Moolenaar 13460d3de8cbSBram Moolenaar // "uf_partial" is on the ufunc that "df_ufunc" points to, as is done 13470d3de8cbSBram Moolenaar // by copy_func(). 13480d3de8cbSBram Moolenaar if (partial != NULL || base_ufunc->uf_partial != NULL) 13490186e586SBram Moolenaar { 13500186e586SBram Moolenaar ectx.ec_outer = ALLOC_CLEAR_ONE(outer_T); 13510186e586SBram Moolenaar if (ectx.ec_outer == NULL) 13520186e586SBram Moolenaar goto failed_early; 13536f5b6dfbSBram Moolenaar if (partial != NULL) 13546f5b6dfbSBram Moolenaar { 13550186e586SBram Moolenaar if (partial->pt_outer.out_stack == NULL && current_ectx != NULL) 135608f7a41bSBram Moolenaar { 13570186e586SBram Moolenaar if (current_ectx->ec_outer != NULL) 13580186e586SBram Moolenaar *ectx.ec_outer = *current_ectx->ec_outer; 135908f7a41bSBram Moolenaar } 136008f7a41bSBram Moolenaar else 13610186e586SBram Moolenaar *ectx.ec_outer = partial->pt_outer; 13626f5b6dfbSBram Moolenaar } 13630186e586SBram Moolenaar else 13640d3de8cbSBram Moolenaar *ectx.ec_outer = base_ufunc->uf_partial->pt_outer; 13650186e586SBram Moolenaar ectx.ec_outer->out_up_is_copy = TRUE; 1366f112f30aSBram Moolenaar } 13670d3de8cbSBram Moolenaar } 13686f5b6dfbSBram Moolenaar 13698a7d6542SBram Moolenaar // dummy frame entries 13708a7d6542SBram Moolenaar for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) 13718a7d6542SBram Moolenaar { 13728a7d6542SBram Moolenaar STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; 13738a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 13748a7d6542SBram Moolenaar } 13758a7d6542SBram Moolenaar 1376bd5da371SBram Moolenaar { 1377148ce7aeSBram Moolenaar // Reserve space for local variables and any closure reference count. 1378bd5da371SBram Moolenaar dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 1379bd5da371SBram Moolenaar + ufunc->uf_dfunc_idx; 1380bd5da371SBram Moolenaar 1381148ce7aeSBram Moolenaar for (idx = 0; idx < dfunc->df_varcount; ++idx) 13828a7d6542SBram Moolenaar STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; 1383148ce7aeSBram Moolenaar ectx.ec_stack.ga_len += dfunc->df_varcount; 1384148ce7aeSBram Moolenaar if (dfunc->df_has_closure) 1385148ce7aeSBram Moolenaar { 1386148ce7aeSBram Moolenaar STACK_TV_VAR(idx)->v_type = VAR_NUMBER; 1387148ce7aeSBram Moolenaar STACK_TV_VAR(idx)->vval.v_number = 0; 1388148ce7aeSBram Moolenaar ++ectx.ec_stack.ga_len; 1389148ce7aeSBram Moolenaar } 13908a7d6542SBram Moolenaar 1391e5ea346aSBram Moolenaar ectx.ec_instr = INSTRUCTIONS(dfunc); 1392bd5da371SBram Moolenaar } 1393170fcfcfSBram Moolenaar 1394ee8580e5SBram Moolenaar // Following errors are in the function, not the caller. 1395a26b9700SBram Moolenaar // Commands behave like vim9script. 1396ee8580e5SBram Moolenaar estack_push_ufunc(ufunc, 1); 1397ee8580e5SBram Moolenaar current_sctx = ufunc->uf_script_ctx; 1398a26b9700SBram Moolenaar current_sctx.sc_version = SCRIPT_VERSION_VIM9; 1399a26b9700SBram Moolenaar 1400352134bbSBram Moolenaar // Use a specific location for storing error messages to be converted to an 1401352134bbSBram Moolenaar // exception. 1402352134bbSBram Moolenaar saved_msg_list = msg_list; 1403352134bbSBram Moolenaar msg_list = &private_msg_list; 1404352134bbSBram Moolenaar 140577e5dcc3SBram Moolenaar // Do turn errors into exceptions. 140677e5dcc3SBram Moolenaar suppress_errthrow = FALSE; 140777e5dcc3SBram Moolenaar 140856602ba1SBram Moolenaar // When ":silent!" was used before calling then we still abort the 140956602ba1SBram Moolenaar // function. If ":silent!" is used in the function then we don't. 141056602ba1SBram Moolenaar emsg_silent_def = emsg_silent; 141156602ba1SBram Moolenaar did_emsg_def = 0; 141256602ba1SBram Moolenaar 1413f785aa13SBram Moolenaar where.wt_index = 0; 1414f785aa13SBram Moolenaar where.wt_variable = FALSE; 1415f785aa13SBram Moolenaar 1416170fcfcfSBram Moolenaar // Decide where to start execution, handles optional arguments. 1417170fcfcfSBram Moolenaar init_instr_idx(ufunc, argc, &ectx); 1418170fcfcfSBram Moolenaar 14198a7d6542SBram Moolenaar for (;;) 14208a7d6542SBram Moolenaar { 14218a7d6542SBram Moolenaar isn_T *iptr; 142220431c9dSBram Moolenaar 1423270d0388SBram Moolenaar if (++breakcheck_count >= 100) 1424270d0388SBram Moolenaar { 1425270d0388SBram Moolenaar line_breakcheck(); 1426270d0388SBram Moolenaar breakcheck_count = 0; 1427270d0388SBram Moolenaar } 142820431c9dSBram Moolenaar if (got_int) 142920431c9dSBram Moolenaar { 143020431c9dSBram Moolenaar // Turn CTRL-C into an exception. 143120431c9dSBram Moolenaar got_int = FALSE; 143297acfc78SBram Moolenaar if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL) 143320431c9dSBram Moolenaar goto failed; 143420431c9dSBram Moolenaar did_throw = TRUE; 143520431c9dSBram Moolenaar } 14368a7d6542SBram Moolenaar 1437a26b9700SBram Moolenaar if (did_emsg && msg_list != NULL && *msg_list != NULL) 1438a26b9700SBram Moolenaar { 1439a26b9700SBram Moolenaar // Turn an error message into an exception. 1440a26b9700SBram Moolenaar did_emsg = FALSE; 1441a26b9700SBram Moolenaar if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL) 1442a26b9700SBram Moolenaar goto failed; 1443a26b9700SBram Moolenaar did_throw = TRUE; 1444a26b9700SBram Moolenaar *msg_list = NULL; 1445a26b9700SBram Moolenaar } 1446a26b9700SBram Moolenaar 14478a7d6542SBram Moolenaar if (did_throw && !ectx.ec_in_catch) 14488a7d6542SBram Moolenaar { 14498a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 145020431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 14518a7d6542SBram Moolenaar 14528a7d6542SBram Moolenaar // An exception jumps to the first catch, finally, or returns from 14538a7d6542SBram Moolenaar // the current function. 14548a7d6542SBram Moolenaar if (trystack->ga_len > 0) 14558a7d6542SBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; 1456bf67ea1aSBram Moolenaar if (trycmd != NULL && trycmd->tcd_frame_idx == ectx.ec_frame_idx) 14578a7d6542SBram Moolenaar { 14588a7d6542SBram Moolenaar // jump to ":catch" or ":finally" 14598a7d6542SBram Moolenaar ectx.ec_in_catch = TRUE; 14608a7d6542SBram Moolenaar ectx.ec_iidx = trycmd->tcd_catch_idx; 14618a7d6542SBram Moolenaar } 14628a7d6542SBram Moolenaar else 14638a7d6542SBram Moolenaar { 1464cdd70f09SBram Moolenaar // Not inside try or need to return from current functions. 1465cdd70f09SBram Moolenaar // Push a dummy return value. 1466270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 14678a7d6542SBram Moolenaar goto failed; 14688a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 14698a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 14708a7d6542SBram Moolenaar tv->vval.v_number = 0; 14718a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 1472cdd70f09SBram Moolenaar if (ectx.ec_frame_idx == initial_frame_idx) 1473cdd70f09SBram Moolenaar { 1474cdd70f09SBram Moolenaar // At the toplevel we are done. 1475257cc5eeSBram Moolenaar need_rethrow = TRUE; 1476bf67ea1aSBram Moolenaar if (handle_closure_in_use(&ectx, FALSE) == FAIL) 1477bf67ea1aSBram Moolenaar goto failed; 14788a7d6542SBram Moolenaar goto done; 14798a7d6542SBram Moolenaar } 14808a7d6542SBram Moolenaar 1481bf67ea1aSBram Moolenaar if (func_return(&ectx) == FAIL) 1482bf67ea1aSBram Moolenaar goto failed; 14838a7d6542SBram Moolenaar } 14848a7d6542SBram Moolenaar continue; 14858a7d6542SBram Moolenaar } 14868a7d6542SBram Moolenaar 14878a7d6542SBram Moolenaar iptr = &ectx.ec_instr[ectx.ec_iidx++]; 14888a7d6542SBram Moolenaar switch (iptr->isn_type) 14898a7d6542SBram Moolenaar { 14908a7d6542SBram Moolenaar // execute Ex command line 14918a7d6542SBram Moolenaar case ISN_EXEC: 1492631e8f93SBram Moolenaar { 14939567efa1SBram Moolenaar source_cookie_T cookie; 14949567efa1SBram Moolenaar 14956378c4feSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 14969567efa1SBram Moolenaar // Pass getsourceline to get an error for a missing ":end" 14979567efa1SBram Moolenaar // command. 14989567efa1SBram Moolenaar CLEAR_FIELD(cookie); 14999567efa1SBram Moolenaar cookie.sourcing_lnum = iptr->isn_lnum - 1; 15009567efa1SBram Moolenaar if (do_cmdline(iptr->isn_arg.string, 15019567efa1SBram Moolenaar getsourceline, &cookie, 15029567efa1SBram Moolenaar DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED) 15039567efa1SBram Moolenaar == FAIL 15049567efa1SBram Moolenaar || did_emsg) 1505eeece9e4SBram Moolenaar goto on_error; 1506631e8f93SBram Moolenaar } 15078a7d6542SBram Moolenaar break; 15088a7d6542SBram Moolenaar 1509cfe435d7SBram Moolenaar // execute Ex command from pieces on the stack 1510cfe435d7SBram Moolenaar case ISN_EXECCONCAT: 1511cfe435d7SBram Moolenaar { 1512cfe435d7SBram Moolenaar int count = iptr->isn_arg.number; 15137f6f56f4SBram Moolenaar size_t len = 0; 1514cfe435d7SBram Moolenaar int pass; 1515cfe435d7SBram Moolenaar int i; 1516cfe435d7SBram Moolenaar char_u *cmd = NULL; 1517cfe435d7SBram Moolenaar char_u *str; 1518cfe435d7SBram Moolenaar 1519cfe435d7SBram Moolenaar for (pass = 1; pass <= 2; ++pass) 1520cfe435d7SBram Moolenaar { 1521cfe435d7SBram Moolenaar for (i = 0; i < count; ++i) 1522cfe435d7SBram Moolenaar { 1523cfe435d7SBram Moolenaar tv = STACK_TV_BOT(i - count); 1524cfe435d7SBram Moolenaar str = tv->vval.v_string; 1525cfe435d7SBram Moolenaar if (str != NULL && *str != NUL) 1526cfe435d7SBram Moolenaar { 1527cfe435d7SBram Moolenaar if (pass == 2) 1528cfe435d7SBram Moolenaar STRCPY(cmd + len, str); 1529cfe435d7SBram Moolenaar len += STRLEN(str); 1530cfe435d7SBram Moolenaar } 1531cfe435d7SBram Moolenaar if (pass == 2) 1532cfe435d7SBram Moolenaar clear_tv(tv); 1533cfe435d7SBram Moolenaar } 1534cfe435d7SBram Moolenaar if (pass == 1) 1535cfe435d7SBram Moolenaar { 1536cfe435d7SBram Moolenaar cmd = alloc(len + 1); 1537cfe435d7SBram Moolenaar if (cmd == NULL) 1538cfe435d7SBram Moolenaar goto failed; 1539cfe435d7SBram Moolenaar len = 0; 1540cfe435d7SBram Moolenaar } 1541cfe435d7SBram Moolenaar } 1542cfe435d7SBram Moolenaar 15436378c4feSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1544cfe435d7SBram Moolenaar do_cmdline_cmd(cmd); 1545cfe435d7SBram Moolenaar vim_free(cmd); 1546cfe435d7SBram Moolenaar } 1547cfe435d7SBram Moolenaar break; 1548cfe435d7SBram Moolenaar 15498a7d6542SBram Moolenaar // execute :echo {string} ... 15508a7d6542SBram Moolenaar case ISN_ECHO: 15518a7d6542SBram Moolenaar { 15528a7d6542SBram Moolenaar int count = iptr->isn_arg.echo.echo_count; 15538a7d6542SBram Moolenaar int atstart = TRUE; 15548a7d6542SBram Moolenaar int needclr = TRUE; 15558a7d6542SBram Moolenaar 15568a7d6542SBram Moolenaar for (idx = 0; idx < count; ++idx) 15578a7d6542SBram Moolenaar { 15588a7d6542SBram Moolenaar tv = STACK_TV_BOT(idx - count); 15598a7d6542SBram Moolenaar echo_one(tv, iptr->isn_arg.echo.echo_with_white, 15608a7d6542SBram Moolenaar &atstart, &needclr); 15618a7d6542SBram Moolenaar clear_tv(tv); 15628a7d6542SBram Moolenaar } 1563e0807ea4SBram Moolenaar if (needclr) 1564e0807ea4SBram Moolenaar msg_clr_eos(); 15658a7d6542SBram Moolenaar ectx.ec_stack.ga_len -= count; 15668a7d6542SBram Moolenaar } 15678a7d6542SBram Moolenaar break; 15688a7d6542SBram Moolenaar 1569f93c7feaSBram Moolenaar // :execute {string} ... 1570f93c7feaSBram Moolenaar // :echomsg {string} ... 1571f93c7feaSBram Moolenaar // :echoerr {string} ... 1572ad39c094SBram Moolenaar case ISN_EXECUTE: 1573f93c7feaSBram Moolenaar case ISN_ECHOMSG: 1574f93c7feaSBram Moolenaar case ISN_ECHOERR: 1575ad39c094SBram Moolenaar { 1576ad39c094SBram Moolenaar int count = iptr->isn_arg.number; 1577ad39c094SBram Moolenaar garray_T ga; 1578ad39c094SBram Moolenaar char_u buf[NUMBUFLEN]; 1579ad39c094SBram Moolenaar char_u *p; 1580ad39c094SBram Moolenaar int len; 1581ad39c094SBram Moolenaar int failed = FALSE; 1582ad39c094SBram Moolenaar 1583ad39c094SBram Moolenaar ga_init2(&ga, 1, 80); 1584ad39c094SBram Moolenaar for (idx = 0; idx < count; ++idx) 1585ad39c094SBram Moolenaar { 1586ad39c094SBram Moolenaar tv = STACK_TV_BOT(idx - count); 1587e5abf7afSBram Moolenaar if (iptr->isn_type == ISN_EXECUTE) 1588e5abf7afSBram Moolenaar { 1589e5abf7afSBram Moolenaar if (tv->v_type == VAR_CHANNEL 1590e5abf7afSBram Moolenaar || tv->v_type == VAR_JOB) 1591ad39c094SBram Moolenaar { 15927517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1593ad39c094SBram Moolenaar emsg(_(e_inval_string)); 1594ad39c094SBram Moolenaar break; 1595ad39c094SBram Moolenaar } 1596ad39c094SBram Moolenaar else 1597ad39c094SBram Moolenaar p = tv_get_string_buf(tv, buf); 1598e5abf7afSBram Moolenaar } 1599e5abf7afSBram Moolenaar else 1600e5abf7afSBram Moolenaar p = tv_stringify(tv, buf); 1601ad39c094SBram Moolenaar 1602ad39c094SBram Moolenaar len = (int)STRLEN(p); 1603ad39c094SBram Moolenaar if (ga_grow(&ga, len + 2) == FAIL) 1604ad39c094SBram Moolenaar failed = TRUE; 1605ad39c094SBram Moolenaar else 1606ad39c094SBram Moolenaar { 1607ad39c094SBram Moolenaar if (ga.ga_len > 0) 1608ad39c094SBram Moolenaar ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; 1609ad39c094SBram Moolenaar STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); 1610ad39c094SBram Moolenaar ga.ga_len += len; 1611ad39c094SBram Moolenaar } 1612ad39c094SBram Moolenaar clear_tv(tv); 1613ad39c094SBram Moolenaar } 1614ad39c094SBram Moolenaar ectx.ec_stack.ga_len -= count; 1615e5abf7afSBram Moolenaar if (failed) 1616c71ee829SBram Moolenaar { 1617c71ee829SBram Moolenaar ga_clear(&ga); 1618e5abf7afSBram Moolenaar goto on_error; 1619c71ee829SBram Moolenaar } 1620ad39c094SBram Moolenaar 1621e5abf7afSBram Moolenaar if (ga.ga_data != NULL) 1622f93c7feaSBram Moolenaar { 1623f93c7feaSBram Moolenaar if (iptr->isn_type == ISN_EXECUTE) 1624430deb19SBram Moolenaar { 1625430deb19SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1626ad39c094SBram Moolenaar do_cmdline_cmd((char_u *)ga.ga_data); 1627eeece9e4SBram Moolenaar if (did_emsg) 1628c71ee829SBram Moolenaar { 1629c71ee829SBram Moolenaar ga_clear(&ga); 1630eeece9e4SBram Moolenaar goto on_error; 1631430deb19SBram Moolenaar } 1632c71ee829SBram Moolenaar } 1633f93c7feaSBram Moolenaar else 1634f93c7feaSBram Moolenaar { 1635f93c7feaSBram Moolenaar msg_sb_eol(); 1636f93c7feaSBram Moolenaar if (iptr->isn_type == ISN_ECHOMSG) 1637f93c7feaSBram Moolenaar { 1638f93c7feaSBram Moolenaar msg_attr(ga.ga_data, echo_attr); 1639f93c7feaSBram Moolenaar out_flush(); 1640f93c7feaSBram Moolenaar } 1641f93c7feaSBram Moolenaar else 1642f93c7feaSBram Moolenaar { 1643f93c7feaSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1644f93c7feaSBram Moolenaar emsg(ga.ga_data); 1645f93c7feaSBram Moolenaar } 1646f93c7feaSBram Moolenaar } 1647f93c7feaSBram Moolenaar } 1648ad39c094SBram Moolenaar ga_clear(&ga); 1649ad39c094SBram Moolenaar } 1650ad39c094SBram Moolenaar break; 1651ad39c094SBram Moolenaar 16528a7d6542SBram Moolenaar // load local variable or argument 16538a7d6542SBram Moolenaar case ISN_LOAD: 1654270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 16558a7d6542SBram Moolenaar goto failed; 16568a7d6542SBram Moolenaar copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); 16578a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 16588a7d6542SBram Moolenaar break; 16598a7d6542SBram Moolenaar 16608a7d6542SBram Moolenaar // load v: variable 16618a7d6542SBram Moolenaar case ISN_LOADV: 1662270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 16638a7d6542SBram Moolenaar goto failed; 16648a7d6542SBram Moolenaar copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0)); 16658a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 16668a7d6542SBram Moolenaar break; 16678a7d6542SBram Moolenaar 1668b283a8a6SBram Moolenaar // load s: variable in Vim9 script 16698a7d6542SBram Moolenaar case ISN_LOADSCRIPT: 16708a7d6542SBram Moolenaar { 16714aab88d9SBram Moolenaar scriptref_T *sref = iptr->isn_arg.script.scriptref; 16728a7d6542SBram Moolenaar svar_T *sv; 16738a7d6542SBram Moolenaar 167407a65d26SBram Moolenaar sv = get_script_svar(sref, &ectx); 167507a65d26SBram Moolenaar if (sv == NULL) 16764aab88d9SBram Moolenaar goto failed; 16773beaf9cdSBram Moolenaar allocate_if_null(sv->sv_tv); 1678270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 16798a7d6542SBram Moolenaar goto failed; 16808a7d6542SBram Moolenaar copy_tv(sv->sv_tv, STACK_TV_BOT(0)); 16818a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 16828a7d6542SBram Moolenaar } 16838a7d6542SBram Moolenaar break; 16848a7d6542SBram Moolenaar 16858a7d6542SBram Moolenaar // load s: variable in old script 16868a7d6542SBram Moolenaar case ISN_LOADS: 16878a7d6542SBram Moolenaar { 1688b283a8a6SBram Moolenaar hashtab_T *ht = &SCRIPT_VARS( 1689b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 1690b283a8a6SBram Moolenaar char_u *name = iptr->isn_arg.loadstore.ls_name; 16918a7d6542SBram Moolenaar dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE); 16920bbf722aSBram Moolenaar 16938a7d6542SBram Moolenaar if (di == NULL) 16948a7d6542SBram Moolenaar { 16957517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1696451c2e35SBram Moolenaar semsg(_(e_undefined_variable_str), name); 1697f0b9f43cSBram Moolenaar goto on_error; 16988a7d6542SBram Moolenaar } 16998a7d6542SBram Moolenaar else 17008a7d6542SBram Moolenaar { 1701270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 17028a7d6542SBram Moolenaar goto failed; 17038a7d6542SBram Moolenaar copy_tv(&di->di_tv, STACK_TV_BOT(0)); 17048a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 17058a7d6542SBram Moolenaar } 17068a7d6542SBram Moolenaar } 17078a7d6542SBram Moolenaar break; 17088a7d6542SBram Moolenaar 1709d3aac291SBram Moolenaar // load g:/b:/w:/t: variable 17108a7d6542SBram Moolenaar case ISN_LOADG: 1711d3aac291SBram Moolenaar case ISN_LOADB: 1712d3aac291SBram Moolenaar case ISN_LOADW: 1713d3aac291SBram Moolenaar case ISN_LOADT: 17148a7d6542SBram Moolenaar { 1715d3aac291SBram Moolenaar dictitem_T *di = NULL; 1716d3aac291SBram Moolenaar hashtab_T *ht = NULL; 1717d3aac291SBram Moolenaar char namespace; 17182f8ce0aeSBram Moolenaar 1719d3aac291SBram Moolenaar switch (iptr->isn_type) 1720d3aac291SBram Moolenaar { 1721d3aac291SBram Moolenaar case ISN_LOADG: 1722d3aac291SBram Moolenaar ht = get_globvar_ht(); 1723d3aac291SBram Moolenaar namespace = 'g'; 1724d3aac291SBram Moolenaar break; 1725d3aac291SBram Moolenaar case ISN_LOADB: 1726d3aac291SBram Moolenaar ht = &curbuf->b_vars->dv_hashtab; 1727d3aac291SBram Moolenaar namespace = 'b'; 1728d3aac291SBram Moolenaar break; 1729d3aac291SBram Moolenaar case ISN_LOADW: 1730d3aac291SBram Moolenaar ht = &curwin->w_vars->dv_hashtab; 1731d3aac291SBram Moolenaar namespace = 'w'; 1732d3aac291SBram Moolenaar break; 1733d3aac291SBram Moolenaar case ISN_LOADT: 1734d3aac291SBram Moolenaar ht = &curtab->tp_vars->dv_hashtab; 1735d3aac291SBram Moolenaar namespace = 't'; 1736d3aac291SBram Moolenaar break; 1737d3aac291SBram Moolenaar default: // Cannot reach here 1738d3aac291SBram Moolenaar goto failed; 1739d3aac291SBram Moolenaar } 1740d3aac291SBram Moolenaar di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE); 17410bbf722aSBram Moolenaar 17428a7d6542SBram Moolenaar if (di == NULL) 17438a7d6542SBram Moolenaar { 17447517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 1745451c2e35SBram Moolenaar semsg(_(e_undefined_variable_char_str), 1746d3aac291SBram Moolenaar namespace, iptr->isn_arg.string); 1747f0b9f43cSBram Moolenaar goto on_error; 17488a7d6542SBram Moolenaar } 17498a7d6542SBram Moolenaar else 17508a7d6542SBram Moolenaar { 1751270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 17528a7d6542SBram Moolenaar goto failed; 17538a7d6542SBram Moolenaar copy_tv(&di->di_tv, STACK_TV_BOT(0)); 17548a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 17558a7d6542SBram Moolenaar } 17568a7d6542SBram Moolenaar } 17578a7d6542SBram Moolenaar break; 17588a7d6542SBram Moolenaar 175903290b84SBram Moolenaar // load autoload variable 176003290b84SBram Moolenaar case ISN_LOADAUTO: 176103290b84SBram Moolenaar { 176203290b84SBram Moolenaar char_u *name = iptr->isn_arg.string; 176303290b84SBram Moolenaar 176403290b84SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 176503290b84SBram Moolenaar goto failed; 176603290b84SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 176738a434f7SBram Moolenaar if (eval_variable(name, (int)STRLEN(name), 1768*cb4e80faSBram Moolenaar STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL) 176903290b84SBram Moolenaar goto on_error; 177003290b84SBram Moolenaar ++ectx.ec_stack.ga_len; 177103290b84SBram Moolenaar } 177203290b84SBram Moolenaar break; 177303290b84SBram Moolenaar 17742f8ce0aeSBram Moolenaar // load g:/b:/w:/t: namespace 17752f8ce0aeSBram Moolenaar case ISN_LOADGDICT: 17762f8ce0aeSBram Moolenaar case ISN_LOADBDICT: 17772f8ce0aeSBram Moolenaar case ISN_LOADWDICT: 17782f8ce0aeSBram Moolenaar case ISN_LOADTDICT: 17792f8ce0aeSBram Moolenaar { 17802f8ce0aeSBram Moolenaar dict_T *d = NULL; 17812f8ce0aeSBram Moolenaar 17822f8ce0aeSBram Moolenaar switch (iptr->isn_type) 17832f8ce0aeSBram Moolenaar { 1784682d0a15SBram Moolenaar case ISN_LOADGDICT: d = get_globvar_dict(); break; 1785682d0a15SBram Moolenaar case ISN_LOADBDICT: d = curbuf->b_vars; break; 1786682d0a15SBram Moolenaar case ISN_LOADWDICT: d = curwin->w_vars; break; 1787682d0a15SBram Moolenaar case ISN_LOADTDICT: d = curtab->tp_vars; break; 17882f8ce0aeSBram Moolenaar default: // Cannot reach here 17892f8ce0aeSBram Moolenaar goto failed; 17902f8ce0aeSBram Moolenaar } 17912f8ce0aeSBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 17922f8ce0aeSBram Moolenaar goto failed; 17932f8ce0aeSBram Moolenaar tv = STACK_TV_BOT(0); 17942f8ce0aeSBram Moolenaar tv->v_type = VAR_DICT; 17952f8ce0aeSBram Moolenaar tv->v_lock = 0; 17962f8ce0aeSBram Moolenaar tv->vval.v_dict = d; 17971bd3cb20SBram Moolenaar ++d->dv_refcount; 17982f8ce0aeSBram Moolenaar ++ectx.ec_stack.ga_len; 17992f8ce0aeSBram Moolenaar } 18002f8ce0aeSBram Moolenaar break; 18012f8ce0aeSBram Moolenaar 18028a7d6542SBram Moolenaar // load &option 18038a7d6542SBram Moolenaar case ISN_LOADOPT: 18048a7d6542SBram Moolenaar { 18058a7d6542SBram Moolenaar typval_T optval; 18068a7d6542SBram Moolenaar char_u *name = iptr->isn_arg.string; 18078a7d6542SBram Moolenaar 1808a8c17704SBram Moolenaar // This is not expected to fail, name is checked during 1809a8c17704SBram Moolenaar // compilation: don't set SOURCING_LNUM. 1810270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 18118a7d6542SBram Moolenaar goto failed; 18129a78e6dfSBram Moolenaar if (eval_option(&name, &optval, TRUE) == FAIL) 181358ceca5cSBram Moolenaar goto failed; 18148a7d6542SBram Moolenaar *STACK_TV_BOT(0) = optval; 18158a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 18168a7d6542SBram Moolenaar } 18178a7d6542SBram Moolenaar break; 18188a7d6542SBram Moolenaar 18198a7d6542SBram Moolenaar // load $ENV 18208a7d6542SBram Moolenaar case ISN_LOADENV: 18218a7d6542SBram Moolenaar { 18228a7d6542SBram Moolenaar typval_T optval; 18238a7d6542SBram Moolenaar char_u *name = iptr->isn_arg.string; 18248a7d6542SBram Moolenaar 1825270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 18268a7d6542SBram Moolenaar goto failed; 18270bbf722aSBram Moolenaar // name is always valid, checked when compiling 18289a78e6dfSBram Moolenaar (void)eval_env_var(&name, &optval, TRUE); 18298a7d6542SBram Moolenaar *STACK_TV_BOT(0) = optval; 18308a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 18318a7d6542SBram Moolenaar } 18328a7d6542SBram Moolenaar break; 18338a7d6542SBram Moolenaar 18348a7d6542SBram Moolenaar // load @register 18358a7d6542SBram Moolenaar case ISN_LOADREG: 1836270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 18378a7d6542SBram Moolenaar goto failed; 18388a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 18398a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 18402f8ce0aeSBram Moolenaar tv->v_lock = 0; 18411e021e63SBram Moolenaar // This may result in NULL, which should be equivalent to an 18421e021e63SBram Moolenaar // empty string. 18438a7d6542SBram Moolenaar tv->vval.v_string = get_reg_contents( 18448a7d6542SBram Moolenaar iptr->isn_arg.number, GREG_EXPR_SRC); 18458a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 18468a7d6542SBram Moolenaar break; 18478a7d6542SBram Moolenaar 18488a7d6542SBram Moolenaar // store local variable 18498a7d6542SBram Moolenaar case ISN_STORE: 18508a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 18518a7d6542SBram Moolenaar tv = STACK_TV_VAR(iptr->isn_arg.number); 18528a7d6542SBram Moolenaar clear_tv(tv); 18538a7d6542SBram Moolenaar *tv = *STACK_TV_BOT(0); 18548a7d6542SBram Moolenaar break; 18558a7d6542SBram Moolenaar 1856b283a8a6SBram Moolenaar // store s: variable in old script 1857b283a8a6SBram Moolenaar case ISN_STORES: 1858b283a8a6SBram Moolenaar { 1859b283a8a6SBram Moolenaar hashtab_T *ht = &SCRIPT_VARS( 1860b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 1861b283a8a6SBram Moolenaar char_u *name = iptr->isn_arg.loadstore.ls_name; 18620bbf722aSBram Moolenaar dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE); 1863b283a8a6SBram Moolenaar 1864b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 18650bbf722aSBram Moolenaar if (di == NULL) 18665deeb3f1SBram Moolenaar store_var(name, STACK_TV_BOT(0)); 18670bbf722aSBram Moolenaar else 18680bbf722aSBram Moolenaar { 1869b283a8a6SBram Moolenaar clear_tv(&di->di_tv); 1870b283a8a6SBram Moolenaar di->di_tv = *STACK_TV_BOT(0); 1871b283a8a6SBram Moolenaar } 18720bbf722aSBram Moolenaar } 1873b283a8a6SBram Moolenaar break; 1874b283a8a6SBram Moolenaar 1875b283a8a6SBram Moolenaar // store script-local variable in Vim9 script 18768a7d6542SBram Moolenaar case ISN_STORESCRIPT: 18778a7d6542SBram Moolenaar { 18784aab88d9SBram Moolenaar scriptref_T *sref = iptr->isn_arg.script.scriptref; 18794aab88d9SBram Moolenaar svar_T *sv; 18808a7d6542SBram Moolenaar 188107a65d26SBram Moolenaar sv = get_script_svar(sref, &ectx); 188207a65d26SBram Moolenaar if (sv == NULL) 18834aab88d9SBram Moolenaar goto failed; 18848a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 18858a7d6542SBram Moolenaar clear_tv(sv->sv_tv); 18868a7d6542SBram Moolenaar *sv->sv_tv = *STACK_TV_BOT(0); 18878a7d6542SBram Moolenaar } 18888a7d6542SBram Moolenaar break; 18898a7d6542SBram Moolenaar 18908a7d6542SBram Moolenaar // store option 18918a7d6542SBram Moolenaar case ISN_STOREOPT: 18928a7d6542SBram Moolenaar { 18938a7d6542SBram Moolenaar long n = 0; 18948a7d6542SBram Moolenaar char_u *s = NULL; 18958a7d6542SBram Moolenaar char *msg; 18968a7d6542SBram Moolenaar 18978a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 18988a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 18998a7d6542SBram Moolenaar if (tv->v_type == VAR_STRING) 190097a2af39SBram Moolenaar { 19018a7d6542SBram Moolenaar s = tv->vval.v_string; 190297a2af39SBram Moolenaar if (s == NULL) 190397a2af39SBram Moolenaar s = (char_u *)""; 190497a2af39SBram Moolenaar } 19058a7d6542SBram Moolenaar else 1906a6e67e4fSBram Moolenaar // must be VAR_NUMBER, CHECKTYPE makes sure 1907a6e67e4fSBram Moolenaar n = tv->vval.v_number; 19088a7d6542SBram Moolenaar msg = set_option_value(iptr->isn_arg.storeopt.so_name, 19098a7d6542SBram Moolenaar n, s, iptr->isn_arg.storeopt.so_flags); 1910e75ba268SBram Moolenaar clear_tv(tv); 19118a7d6542SBram Moolenaar if (msg != NULL) 19128a7d6542SBram Moolenaar { 19137517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 19148a7d6542SBram Moolenaar emsg(_(msg)); 1915e859312eSBram Moolenaar goto on_error; 19168a7d6542SBram Moolenaar } 19178a7d6542SBram Moolenaar } 19188a7d6542SBram Moolenaar break; 19198a7d6542SBram Moolenaar 1920b283a8a6SBram Moolenaar // store $ENV 1921b283a8a6SBram Moolenaar case ISN_STOREENV: 1922b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 192320431c9dSBram Moolenaar tv = STACK_TV_BOT(0); 192420431c9dSBram Moolenaar vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv)); 192520431c9dSBram Moolenaar clear_tv(tv); 1926b283a8a6SBram Moolenaar break; 1927b283a8a6SBram Moolenaar 1928b283a8a6SBram Moolenaar // store @r 1929b283a8a6SBram Moolenaar case ISN_STOREREG: 1930b283a8a6SBram Moolenaar { 1931b283a8a6SBram Moolenaar int reg = iptr->isn_arg.number; 1932b283a8a6SBram Moolenaar 1933b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 1934401d9ffbSBram Moolenaar tv = STACK_TV_BOT(0); 1935b283a8a6SBram Moolenaar write_reg_contents(reg == '@' ? '"' : reg, 1936401d9ffbSBram Moolenaar tv_get_string(tv), -1, FALSE); 1937401d9ffbSBram Moolenaar clear_tv(tv); 1938b283a8a6SBram Moolenaar } 1939b283a8a6SBram Moolenaar break; 1940b283a8a6SBram Moolenaar 1941b283a8a6SBram Moolenaar // store v: variable 1942b283a8a6SBram Moolenaar case ISN_STOREV: 1943b283a8a6SBram Moolenaar --ectx.ec_stack.ga_len; 1944b283a8a6SBram Moolenaar if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0)) 1945b283a8a6SBram Moolenaar == FAIL) 1946e859312eSBram Moolenaar // should not happen, type is checked when compiling 1947e859312eSBram Moolenaar goto on_error; 1948b283a8a6SBram Moolenaar break; 1949b283a8a6SBram Moolenaar 1950d3aac291SBram Moolenaar // store g:/b:/w:/t: variable 19518a7d6542SBram Moolenaar case ISN_STOREG: 1952d3aac291SBram Moolenaar case ISN_STOREB: 1953d3aac291SBram Moolenaar case ISN_STOREW: 1954d3aac291SBram Moolenaar case ISN_STORET: 19558a7d6542SBram Moolenaar { 19568a7d6542SBram Moolenaar dictitem_T *di; 1957d3aac291SBram Moolenaar hashtab_T *ht; 19583bdc90b7SBram Moolenaar char_u *name = iptr->isn_arg.string + 2; 19593bdc90b7SBram Moolenaar 1960d3aac291SBram Moolenaar switch (iptr->isn_type) 1961d3aac291SBram Moolenaar { 1962d3aac291SBram Moolenaar case ISN_STOREG: 1963d3aac291SBram Moolenaar ht = get_globvar_ht(); 1964d3aac291SBram Moolenaar break; 1965d3aac291SBram Moolenaar case ISN_STOREB: 1966d3aac291SBram Moolenaar ht = &curbuf->b_vars->dv_hashtab; 1967d3aac291SBram Moolenaar break; 1968d3aac291SBram Moolenaar case ISN_STOREW: 1969d3aac291SBram Moolenaar ht = &curwin->w_vars->dv_hashtab; 1970d3aac291SBram Moolenaar break; 1971d3aac291SBram Moolenaar case ISN_STORET: 1972d3aac291SBram Moolenaar ht = &curtab->tp_vars->dv_hashtab; 1973d3aac291SBram Moolenaar break; 1974d3aac291SBram Moolenaar default: // Cannot reach here 1975d3aac291SBram Moolenaar goto failed; 1976d3aac291SBram Moolenaar } 19778a7d6542SBram Moolenaar 19788a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 19793bdc90b7SBram Moolenaar di = find_var_in_ht(ht, 0, name, TRUE); 19808a7d6542SBram Moolenaar if (di == NULL) 19810bbf722aSBram Moolenaar store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); 19828a7d6542SBram Moolenaar else 19838a7d6542SBram Moolenaar { 19843bdc90b7SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 19853bdc90b7SBram Moolenaar if (var_check_permission(di, name) == FAIL) 19863bdc90b7SBram Moolenaar goto on_error; 19878a7d6542SBram Moolenaar clear_tv(&di->di_tv); 19888a7d6542SBram Moolenaar di->di_tv = *STACK_TV_BOT(0); 19898a7d6542SBram Moolenaar } 19908a7d6542SBram Moolenaar } 19918a7d6542SBram Moolenaar break; 19928a7d6542SBram Moolenaar 199303290b84SBram Moolenaar // store an autoload variable 199403290b84SBram Moolenaar case ISN_STOREAUTO: 199503290b84SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 199603290b84SBram Moolenaar set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE); 199703290b84SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 199803290b84SBram Moolenaar --ectx.ec_stack.ga_len; 199903290b84SBram Moolenaar break; 200003290b84SBram Moolenaar 20018a7d6542SBram Moolenaar // store number in local variable 20028a7d6542SBram Moolenaar case ISN_STORENR: 2003a471eeaeSBram Moolenaar tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx); 20048a7d6542SBram Moolenaar clear_tv(tv); 20058a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 2006a471eeaeSBram Moolenaar tv->vval.v_number = iptr->isn_arg.storenr.stnr_val; 20078a7d6542SBram Moolenaar break; 20088a7d6542SBram Moolenaar 20094f5e3977SBram Moolenaar // store value in list or dict variable 20104f5e3977SBram Moolenaar case ISN_STOREINDEX: 20111cc2a94fSBram Moolenaar { 20124f5e3977SBram Moolenaar vartype_T dest_type = iptr->isn_arg.vartype; 20131cc2a94fSBram Moolenaar typval_T *tv_idx = STACK_TV_BOT(-2); 20144f5e3977SBram Moolenaar typval_T *tv_dest = STACK_TV_BOT(-1); 20154f5e3977SBram Moolenaar int status = OK; 20161cc2a94fSBram Moolenaar 2017752fc692SBram Moolenaar // Stack contains: 2018752fc692SBram Moolenaar // -3 value to be stored 2019752fc692SBram Moolenaar // -2 index 2020752fc692SBram Moolenaar // -1 dict or list 20214f5e3977SBram Moolenaar tv = STACK_TV_BOT(-3); 20220b4c66c6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 20234f5e3977SBram Moolenaar if (dest_type == VAR_ANY) 20244f5e3977SBram Moolenaar { 20254f5e3977SBram Moolenaar dest_type = tv_dest->v_type; 20264f5e3977SBram Moolenaar if (dest_type == VAR_DICT) 20274f5e3977SBram Moolenaar status = do_2string(tv_idx, TRUE); 20284f5e3977SBram Moolenaar else if (dest_type == VAR_LIST 20294f5e3977SBram Moolenaar && tv_idx->v_type != VAR_NUMBER) 20304f5e3977SBram Moolenaar { 20314f5e3977SBram Moolenaar emsg(_(e_number_exp)); 20324f5e3977SBram Moolenaar status = FAIL; 20334f5e3977SBram Moolenaar } 20344f5e3977SBram Moolenaar } 20354f5e3977SBram Moolenaar else if (dest_type != tv_dest->v_type) 20364f5e3977SBram Moolenaar { 20374f5e3977SBram Moolenaar // just in case, should be OK 20384f5e3977SBram Moolenaar semsg(_(e_expected_str_but_got_str), 20394f5e3977SBram Moolenaar vartype_name(dest_type), 20404f5e3977SBram Moolenaar vartype_name(tv_dest->v_type)); 20414f5e3977SBram Moolenaar status = FAIL; 20424f5e3977SBram Moolenaar } 20434f5e3977SBram Moolenaar 20444f5e3977SBram Moolenaar if (status == OK && dest_type == VAR_LIST) 20454f5e3977SBram Moolenaar { 2046239f8d93SBram Moolenaar long lidx = (long)tv_idx->vval.v_number; 20474f5e3977SBram Moolenaar list_T *list = tv_dest->vval.v_list; 20484f5e3977SBram Moolenaar 20494f5e3977SBram Moolenaar if (list == NULL) 20504f5e3977SBram Moolenaar { 20514f5e3977SBram Moolenaar emsg(_(e_list_not_set)); 20524f5e3977SBram Moolenaar goto on_error; 20534f5e3977SBram Moolenaar } 20541cc2a94fSBram Moolenaar if (lidx < 0 && list->lv_len + lidx >= 0) 20551cc2a94fSBram Moolenaar // negative index is relative to the end 20561cc2a94fSBram Moolenaar lidx = list->lv_len + lidx; 20571cc2a94fSBram Moolenaar if (lidx < 0 || lidx > list->lv_len) 20581cc2a94fSBram Moolenaar { 20591cc2a94fSBram Moolenaar semsg(_(e_listidx), lidx); 2060e859312eSBram Moolenaar goto on_error; 20611cc2a94fSBram Moolenaar } 20621cc2a94fSBram Moolenaar if (lidx < list->lv_len) 20631cc2a94fSBram Moolenaar { 20641cc2a94fSBram Moolenaar listitem_T *li = list_find(list, lidx); 20651cc2a94fSBram Moolenaar 20660b4c66c6SBram Moolenaar if (error_if_locked(li->li_tv.v_lock, 20670b4c66c6SBram Moolenaar e_cannot_change_list_item)) 20684f5e3977SBram Moolenaar goto on_error; 20691cc2a94fSBram Moolenaar // overwrite existing list item 20701cc2a94fSBram Moolenaar clear_tv(&li->li_tv); 20711cc2a94fSBram Moolenaar li->li_tv = *tv; 20721cc2a94fSBram Moolenaar } 20731cc2a94fSBram Moolenaar else 20741cc2a94fSBram Moolenaar { 20750b4c66c6SBram Moolenaar if (error_if_locked(list->lv_lock, 20760b4c66c6SBram Moolenaar e_cannot_change_list)) 20774f5e3977SBram Moolenaar goto on_error; 2078e859312eSBram Moolenaar // append to list, only fails when out of memory 20791cc2a94fSBram Moolenaar if (list_append_tv(list, tv) == FAIL) 20801cc2a94fSBram Moolenaar goto failed; 20811cc2a94fSBram Moolenaar clear_tv(tv); 20821cc2a94fSBram Moolenaar } 20831cc2a94fSBram Moolenaar } 20844f5e3977SBram Moolenaar else if (status == OK && dest_type == VAR_DICT) 20851cc2a94fSBram Moolenaar { 20864f5e3977SBram Moolenaar char_u *key = tv_idx->vval.v_string; 20874f5e3977SBram Moolenaar dict_T *dict = tv_dest->vval.v_dict; 20881cc2a94fSBram Moolenaar dictitem_T *di; 20891cc2a94fSBram Moolenaar 20900b4c66c6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 20918e4c8c85SBram Moolenaar if (dict == NULL) 20928e4c8c85SBram Moolenaar { 2093bc4c5051SBram Moolenaar emsg(_(e_dictionary_not_set)); 20948e4c8c85SBram Moolenaar goto on_error; 20958e4c8c85SBram Moolenaar } 209658626872SBram Moolenaar if (key == NULL) 209758626872SBram Moolenaar key = (char_u *)""; 20981cc2a94fSBram Moolenaar di = dict_find(dict, key, -1); 20991cc2a94fSBram Moolenaar if (di != NULL) 21001cc2a94fSBram Moolenaar { 21010b4c66c6SBram Moolenaar if (error_if_locked(di->di_tv.v_lock, 21020b4c66c6SBram Moolenaar e_cannot_change_dict_item)) 21034f5e3977SBram Moolenaar goto on_error; 2104e859312eSBram Moolenaar // overwrite existing value 21051cc2a94fSBram Moolenaar clear_tv(&di->di_tv); 21061cc2a94fSBram Moolenaar di->di_tv = *tv; 21071cc2a94fSBram Moolenaar } 21081cc2a94fSBram Moolenaar else 21091cc2a94fSBram Moolenaar { 21100b4c66c6SBram Moolenaar if (error_if_locked(dict->dv_lock, 21110b4c66c6SBram Moolenaar e_cannot_change_dict)) 21124f5e3977SBram Moolenaar goto on_error; 2113e859312eSBram Moolenaar // add to dict, only fails when out of memory 21141cc2a94fSBram Moolenaar if (dict_add_tv(dict, (char *)key, tv) == FAIL) 21151cc2a94fSBram Moolenaar goto failed; 21161cc2a94fSBram Moolenaar clear_tv(tv); 21171cc2a94fSBram Moolenaar } 21184f5e3977SBram Moolenaar } 21194f5e3977SBram Moolenaar else 21204f5e3977SBram Moolenaar { 21214f5e3977SBram Moolenaar status = FAIL; 21224f5e3977SBram Moolenaar semsg(_(e_cannot_index_str), vartype_name(dest_type)); 21234f5e3977SBram Moolenaar } 21244f5e3977SBram Moolenaar 21254f5e3977SBram Moolenaar clear_tv(tv_idx); 21264f5e3977SBram Moolenaar clear_tv(tv_dest); 2127f163bd5eSBram Moolenaar ectx.ec_stack.ga_len -= 3; 21284f5e3977SBram Moolenaar if (status == FAIL) 21294f5e3977SBram Moolenaar { 21304f5e3977SBram Moolenaar clear_tv(tv); 21314f5e3977SBram Moolenaar goto on_error; 21324f5e3977SBram Moolenaar } 21331cc2a94fSBram Moolenaar } 21341cc2a94fSBram Moolenaar break; 21351cc2a94fSBram Moolenaar 21360186e586SBram Moolenaar // load or store variable or argument from outer scope 21370186e586SBram Moolenaar case ISN_LOADOUTER: 21380186e586SBram Moolenaar case ISN_STOREOUTER: 21390186e586SBram Moolenaar { 21400186e586SBram Moolenaar int depth = iptr->isn_arg.outer.outer_depth; 21410186e586SBram Moolenaar outer_T *outer = ectx.ec_outer; 21420186e586SBram Moolenaar 21430186e586SBram Moolenaar while (depth > 1 && outer != NULL) 21440186e586SBram Moolenaar { 21450186e586SBram Moolenaar outer = outer->out_up; 21460186e586SBram Moolenaar --depth; 21470186e586SBram Moolenaar } 21480186e586SBram Moolenaar if (outer == NULL) 21490186e586SBram Moolenaar { 21500186e586SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 21510186e586SBram Moolenaar iemsg("LOADOUTER depth more than scope levels"); 21520186e586SBram Moolenaar goto failed; 21530186e586SBram Moolenaar } 21540186e586SBram Moolenaar tv = ((typval_T *)outer->out_stack->ga_data) 21550186e586SBram Moolenaar + outer->out_frame_idx + STACK_FRAME_SIZE 21560186e586SBram Moolenaar + iptr->isn_arg.outer.outer_idx; 21570186e586SBram Moolenaar if (iptr->isn_type == ISN_LOADOUTER) 21580186e586SBram Moolenaar { 21590186e586SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 21600186e586SBram Moolenaar goto failed; 21610186e586SBram Moolenaar copy_tv(tv, STACK_TV_BOT(0)); 21620186e586SBram Moolenaar ++ectx.ec_stack.ga_len; 21630186e586SBram Moolenaar } 21640186e586SBram Moolenaar else 21650186e586SBram Moolenaar { 21660186e586SBram Moolenaar --ectx.ec_stack.ga_len; 21670186e586SBram Moolenaar clear_tv(tv); 21680186e586SBram Moolenaar *tv = *STACK_TV_BOT(0); 21690186e586SBram Moolenaar } 21700186e586SBram Moolenaar } 21710186e586SBram Moolenaar break; 21720186e586SBram Moolenaar 2173752fc692SBram Moolenaar // unlet item in list or dict variable 2174752fc692SBram Moolenaar case ISN_UNLETINDEX: 2175752fc692SBram Moolenaar { 2176752fc692SBram Moolenaar typval_T *tv_idx = STACK_TV_BOT(-2); 2177752fc692SBram Moolenaar typval_T *tv_dest = STACK_TV_BOT(-1); 2178752fc692SBram Moolenaar int status = OK; 2179752fc692SBram Moolenaar 2180752fc692SBram Moolenaar // Stack contains: 2181752fc692SBram Moolenaar // -2 index 2182752fc692SBram Moolenaar // -1 dict or list 2183752fc692SBram Moolenaar if (tv_dest->v_type == VAR_DICT) 2184752fc692SBram Moolenaar { 2185752fc692SBram Moolenaar // unlet a dict item, index must be a string 2186752fc692SBram Moolenaar if (tv_idx->v_type != VAR_STRING) 2187752fc692SBram Moolenaar { 21880acbf5aeSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2189752fc692SBram Moolenaar semsg(_(e_expected_str_but_got_str), 2190752fc692SBram Moolenaar vartype_name(VAR_STRING), 2191752fc692SBram Moolenaar vartype_name(tv_idx->v_type)); 2192752fc692SBram Moolenaar status = FAIL; 2193752fc692SBram Moolenaar } 2194752fc692SBram Moolenaar else 2195752fc692SBram Moolenaar { 2196752fc692SBram Moolenaar dict_T *d = tv_dest->vval.v_dict; 2197752fc692SBram Moolenaar char_u *key = tv_idx->vval.v_string; 2198752fc692SBram Moolenaar dictitem_T *di = NULL; 2199752fc692SBram Moolenaar 2200752fc692SBram Moolenaar if (key == NULL) 2201752fc692SBram Moolenaar key = (char_u *)""; 2202752fc692SBram Moolenaar if (d != NULL) 2203752fc692SBram Moolenaar di = dict_find(d, key, (int)STRLEN(key)); 2204752fc692SBram Moolenaar if (di == NULL) 2205752fc692SBram Moolenaar { 2206752fc692SBram Moolenaar // NULL dict is equivalent to empty dict 22070acbf5aeSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2208752fc692SBram Moolenaar semsg(_(e_dictkey), key); 2209752fc692SBram Moolenaar status = FAIL; 2210752fc692SBram Moolenaar } 2211752fc692SBram Moolenaar else 2212752fc692SBram Moolenaar { 2213752fc692SBram Moolenaar // TODO: check for dict or item locked 2214752fc692SBram Moolenaar dictitem_remove(d, di); 2215752fc692SBram Moolenaar } 2216752fc692SBram Moolenaar } 2217752fc692SBram Moolenaar } 2218752fc692SBram Moolenaar else if (tv_dest->v_type == VAR_LIST) 2219752fc692SBram Moolenaar { 2220752fc692SBram Moolenaar // unlet a List item, index must be a number 22210acbf5aeSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 22225b5ae29bSBram Moolenaar if (check_for_number(tv_idx) == FAIL) 22235b5ae29bSBram Moolenaar { 2224752fc692SBram Moolenaar status = FAIL; 2225752fc692SBram Moolenaar } 2226752fc692SBram Moolenaar else 2227752fc692SBram Moolenaar { 2228752fc692SBram Moolenaar list_T *l = tv_dest->vval.v_list; 2229239f8d93SBram Moolenaar long n = (long)tv_idx->vval.v_number; 2230752fc692SBram Moolenaar listitem_T *li = NULL; 2231752fc692SBram Moolenaar 2232752fc692SBram Moolenaar li = list_find(l, n); 2233752fc692SBram Moolenaar if (li == NULL) 2234752fc692SBram Moolenaar { 22350acbf5aeSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2236752fc692SBram Moolenaar semsg(_(e_listidx), n); 2237752fc692SBram Moolenaar status = FAIL; 2238752fc692SBram Moolenaar } 2239752fc692SBram Moolenaar else 2240752fc692SBram Moolenaar // TODO: check for list or item locked 2241752fc692SBram Moolenaar listitem_remove(l, li); 2242752fc692SBram Moolenaar } 2243752fc692SBram Moolenaar } 2244752fc692SBram Moolenaar else 2245752fc692SBram Moolenaar { 2246752fc692SBram Moolenaar status = FAIL; 2247752fc692SBram Moolenaar semsg(_(e_cannot_index_str), 2248752fc692SBram Moolenaar vartype_name(tv_dest->v_type)); 2249752fc692SBram Moolenaar } 2250752fc692SBram Moolenaar 2251752fc692SBram Moolenaar clear_tv(tv_idx); 2252752fc692SBram Moolenaar clear_tv(tv_dest); 2253752fc692SBram Moolenaar ectx.ec_stack.ga_len -= 2; 2254752fc692SBram Moolenaar if (status == FAIL) 2255752fc692SBram Moolenaar goto on_error; 2256752fc692SBram Moolenaar } 2257752fc692SBram Moolenaar break; 2258752fc692SBram Moolenaar 22595b5ae29bSBram Moolenaar // unlet range of items in list variable 22605b5ae29bSBram Moolenaar case ISN_UNLETRANGE: 22615b5ae29bSBram Moolenaar { 22625b5ae29bSBram Moolenaar // Stack contains: 22635b5ae29bSBram Moolenaar // -3 index1 22645b5ae29bSBram Moolenaar // -2 index2 22655b5ae29bSBram Moolenaar // -1 dict or list 22665b5ae29bSBram Moolenaar typval_T *tv_idx1 = STACK_TV_BOT(-3); 22675b5ae29bSBram Moolenaar typval_T *tv_idx2 = STACK_TV_BOT(-2); 22685b5ae29bSBram Moolenaar typval_T *tv_dest = STACK_TV_BOT(-1); 22695b5ae29bSBram Moolenaar int status = OK; 22705b5ae29bSBram Moolenaar 22715b5ae29bSBram Moolenaar if (tv_dest->v_type == VAR_LIST) 22725b5ae29bSBram Moolenaar { 22735b5ae29bSBram Moolenaar // indexes must be a number 22745b5ae29bSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 22755b5ae29bSBram Moolenaar if (check_for_number(tv_idx1) == FAIL 22765b5ae29bSBram Moolenaar || check_for_number(tv_idx2) == FAIL) 22775b5ae29bSBram Moolenaar { 22785b5ae29bSBram Moolenaar status = FAIL; 22795b5ae29bSBram Moolenaar } 22805b5ae29bSBram Moolenaar else 22815b5ae29bSBram Moolenaar { 22825b5ae29bSBram Moolenaar list_T *l = tv_dest->vval.v_list; 22835b5ae29bSBram Moolenaar long n1 = (long)tv_idx1->vval.v_number; 22845b5ae29bSBram Moolenaar long n2 = (long)tv_idx2->vval.v_number; 22855b5ae29bSBram Moolenaar listitem_T *li; 22865b5ae29bSBram Moolenaar 22875b5ae29bSBram Moolenaar li = list_find_index(l, &n1); 22885b5ae29bSBram Moolenaar if (li == NULL 22895b5ae29bSBram Moolenaar || list_unlet_range(l, li, NULL, n1, 22905b5ae29bSBram Moolenaar TRUE, n2) == FAIL) 22915b5ae29bSBram Moolenaar status = FAIL; 22925b5ae29bSBram Moolenaar } 22935b5ae29bSBram Moolenaar } 22945b5ae29bSBram Moolenaar else 22955b5ae29bSBram Moolenaar { 22965b5ae29bSBram Moolenaar status = FAIL; 22975b5ae29bSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 22985b5ae29bSBram Moolenaar semsg(_(e_cannot_index_str), 22995b5ae29bSBram Moolenaar vartype_name(tv_dest->v_type)); 23005b5ae29bSBram Moolenaar } 23015b5ae29bSBram Moolenaar 23025b5ae29bSBram Moolenaar clear_tv(tv_idx1); 23035b5ae29bSBram Moolenaar clear_tv(tv_idx2); 23045b5ae29bSBram Moolenaar clear_tv(tv_dest); 23055b5ae29bSBram Moolenaar ectx.ec_stack.ga_len -= 3; 23065b5ae29bSBram Moolenaar if (status == FAIL) 23075b5ae29bSBram Moolenaar goto on_error; 23085b5ae29bSBram Moolenaar } 23095b5ae29bSBram Moolenaar break; 23105b5ae29bSBram Moolenaar 23118a7d6542SBram Moolenaar // push constant 23128a7d6542SBram Moolenaar case ISN_PUSHNR: 23138a7d6542SBram Moolenaar case ISN_PUSHBOOL: 23148a7d6542SBram Moolenaar case ISN_PUSHSPEC: 23158a7d6542SBram Moolenaar case ISN_PUSHF: 23168a7d6542SBram Moolenaar case ISN_PUSHS: 23178a7d6542SBram Moolenaar case ISN_PUSHBLOB: 231842a480bfSBram Moolenaar case ISN_PUSHFUNC: 231942a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 232042a480bfSBram Moolenaar case ISN_PUSHJOB: 2321270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 23228a7d6542SBram Moolenaar goto failed; 23238a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 23242f8ce0aeSBram Moolenaar tv->v_lock = 0; 23258a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 23268a7d6542SBram Moolenaar switch (iptr->isn_type) 23278a7d6542SBram Moolenaar { 23288a7d6542SBram Moolenaar case ISN_PUSHNR: 23298a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 23308a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 23318a7d6542SBram Moolenaar break; 23328a7d6542SBram Moolenaar case ISN_PUSHBOOL: 23338a7d6542SBram Moolenaar tv->v_type = VAR_BOOL; 23348a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 23358a7d6542SBram Moolenaar break; 23368a7d6542SBram Moolenaar case ISN_PUSHSPEC: 23378a7d6542SBram Moolenaar tv->v_type = VAR_SPECIAL; 23388a7d6542SBram Moolenaar tv->vval.v_number = iptr->isn_arg.number; 23398a7d6542SBram Moolenaar break; 23408a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 23418a7d6542SBram Moolenaar case ISN_PUSHF: 23428a7d6542SBram Moolenaar tv->v_type = VAR_FLOAT; 23438a7d6542SBram Moolenaar tv->vval.v_float = iptr->isn_arg.fnumber; 23448a7d6542SBram Moolenaar break; 23458a7d6542SBram Moolenaar #endif 23468a7d6542SBram Moolenaar case ISN_PUSHBLOB: 23478a7d6542SBram Moolenaar blob_copy(iptr->isn_arg.blob, tv); 23488a7d6542SBram Moolenaar break; 234942a480bfSBram Moolenaar case ISN_PUSHFUNC: 235042a480bfSBram Moolenaar tv->v_type = VAR_FUNC; 2351087d2e15SBram Moolenaar if (iptr->isn_arg.string == NULL) 2352087d2e15SBram Moolenaar tv->vval.v_string = NULL; 2353087d2e15SBram Moolenaar else 2354087d2e15SBram Moolenaar tv->vval.v_string = 2355087d2e15SBram Moolenaar vim_strsave(iptr->isn_arg.string); 235642a480bfSBram Moolenaar break; 235742a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 235842a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 235942a480bfSBram Moolenaar tv->v_type = VAR_CHANNEL; 236042a480bfSBram Moolenaar tv->vval.v_channel = iptr->isn_arg.channel; 236142a480bfSBram Moolenaar if (tv->vval.v_channel != NULL) 236242a480bfSBram Moolenaar ++tv->vval.v_channel->ch_refcount; 236342a480bfSBram Moolenaar #endif 236442a480bfSBram Moolenaar break; 236542a480bfSBram Moolenaar case ISN_PUSHJOB: 236642a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 236742a480bfSBram Moolenaar tv->v_type = VAR_JOB; 236842a480bfSBram Moolenaar tv->vval.v_job = iptr->isn_arg.job; 236942a480bfSBram Moolenaar if (tv->vval.v_job != NULL) 237042a480bfSBram Moolenaar ++tv->vval.v_job->jv_refcount; 237142a480bfSBram Moolenaar #endif 237242a480bfSBram Moolenaar break; 23738a7d6542SBram Moolenaar default: 23748a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 2375e69f6d04SBram Moolenaar tv->vval.v_string = vim_strsave( 2376e69f6d04SBram Moolenaar iptr->isn_arg.string == NULL 2377e69f6d04SBram Moolenaar ? (char_u *)"" : iptr->isn_arg.string); 23788a7d6542SBram Moolenaar } 23798a7d6542SBram Moolenaar break; 23808a7d6542SBram Moolenaar 2381d72c1bf0SBram Moolenaar case ISN_UNLET: 2382d72c1bf0SBram Moolenaar if (do_unlet(iptr->isn_arg.unlet.ul_name, 2383d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_forceit) == FAIL) 2384e859312eSBram Moolenaar goto on_error; 2385d72c1bf0SBram Moolenaar break; 23867bdaea6eSBram Moolenaar case ISN_UNLETENV: 23877bdaea6eSBram Moolenaar vim_unsetenv(iptr->isn_arg.unlet.ul_name); 23887bdaea6eSBram Moolenaar break; 2389d72c1bf0SBram Moolenaar 23900b4c66c6SBram Moolenaar case ISN_LOCKCONST: 23910b4c66c6SBram Moolenaar item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE); 23920b4c66c6SBram Moolenaar break; 23930b4c66c6SBram Moolenaar 23948a7d6542SBram Moolenaar // create a list from items on the stack; uses a single allocation 23958a7d6542SBram Moolenaar // for the list header and the items 23968a7d6542SBram Moolenaar case ISN_NEWLIST: 2397fe270817SBram Moolenaar if (exe_newlist(iptr->isn_arg.number, &ectx) == FAIL) 23988a7d6542SBram Moolenaar goto failed; 23998a7d6542SBram Moolenaar break; 24008a7d6542SBram Moolenaar 24018a7d6542SBram Moolenaar // create a dict from items on the stack 24028a7d6542SBram Moolenaar case ISN_NEWDICT: 24038a7d6542SBram Moolenaar { 24048a7d6542SBram Moolenaar int count = iptr->isn_arg.number; 24058a7d6542SBram Moolenaar dict_T *dict = dict_alloc(); 24068a7d6542SBram Moolenaar dictitem_T *item; 2407c7f7f6dbSBram Moolenaar char_u *key; 24088a7d6542SBram Moolenaar 24098a7d6542SBram Moolenaar if (dict == NULL) 24108a7d6542SBram Moolenaar goto failed; 24118a7d6542SBram Moolenaar for (idx = 0; idx < count; ++idx) 24128a7d6542SBram Moolenaar { 2413e859312eSBram Moolenaar // have already checked key type is VAR_STRING 24148a7d6542SBram Moolenaar tv = STACK_TV_BOT(2 * (idx - count)); 2415e859312eSBram Moolenaar // check key is unique 2416c7f7f6dbSBram Moolenaar key = tv->vval.v_string == NULL 2417c7f7f6dbSBram Moolenaar ? (char_u *)"" : tv->vval.v_string; 2418c7f7f6dbSBram Moolenaar item = dict_find(dict, key, -1); 2419e859312eSBram Moolenaar if (item != NULL) 2420e859312eSBram Moolenaar { 24217517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 2422c7f7f6dbSBram Moolenaar semsg(_(e_duplicate_key), key); 2423e859312eSBram Moolenaar dict_unref(dict); 2424e859312eSBram Moolenaar goto on_error; 2425e859312eSBram Moolenaar } 2426c7f7f6dbSBram Moolenaar item = dictitem_alloc(key); 24278a7d6542SBram Moolenaar clear_tv(tv); 24288a7d6542SBram Moolenaar if (item == NULL) 2429e859312eSBram Moolenaar { 2430e859312eSBram Moolenaar dict_unref(dict); 24318a7d6542SBram Moolenaar goto failed; 2432e859312eSBram Moolenaar } 24338a7d6542SBram Moolenaar item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); 24348a7d6542SBram Moolenaar item->di_tv.v_lock = 0; 24358a7d6542SBram Moolenaar if (dict_add(dict, item) == FAIL) 2436e859312eSBram Moolenaar { 2437d032f34aSBram Moolenaar // can this ever happen? 2438e859312eSBram Moolenaar dict_unref(dict); 24398a7d6542SBram Moolenaar goto failed; 24408a7d6542SBram Moolenaar } 2441e859312eSBram Moolenaar } 24428a7d6542SBram Moolenaar 24438a7d6542SBram Moolenaar if (count > 0) 24448a7d6542SBram Moolenaar ectx.ec_stack.ga_len -= 2 * count - 1; 2445270d0388SBram Moolenaar else if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 24468a7d6542SBram Moolenaar goto failed; 24478a7d6542SBram Moolenaar else 24488a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 24498a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 24508a7d6542SBram Moolenaar tv->v_type = VAR_DICT; 24512f8ce0aeSBram Moolenaar tv->v_lock = 0; 24528a7d6542SBram Moolenaar tv->vval.v_dict = dict; 24538a7d6542SBram Moolenaar ++dict->dv_refcount; 24548a7d6542SBram Moolenaar } 24558a7d6542SBram Moolenaar break; 24568a7d6542SBram Moolenaar 24578a7d6542SBram Moolenaar // call a :def function 24588a7d6542SBram Moolenaar case ISN_DCALL: 2459dfa3d552SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 24600186e586SBram Moolenaar if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx, NULL, 24618a7d6542SBram Moolenaar iptr->isn_arg.dfunc.cdf_argcount, 24628a7d6542SBram Moolenaar &ectx) == FAIL) 2463e859312eSBram Moolenaar goto on_error; 24648a7d6542SBram Moolenaar break; 24658a7d6542SBram Moolenaar 24668a7d6542SBram Moolenaar // call a builtin function 24678a7d6542SBram Moolenaar case ISN_BCALL: 24688a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 24698a7d6542SBram Moolenaar if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx, 24708a7d6542SBram Moolenaar iptr->isn_arg.bfunc.cbf_argcount, 24718a7d6542SBram Moolenaar &ectx) == FAIL) 2472d032f34aSBram Moolenaar goto on_error; 24738a7d6542SBram Moolenaar break; 24748a7d6542SBram Moolenaar 24758a7d6542SBram Moolenaar // call a funcref or partial 24768a7d6542SBram Moolenaar case ISN_PCALL: 24778a7d6542SBram Moolenaar { 24788a7d6542SBram Moolenaar cpfunc_T *pfunc = &iptr->isn_arg.pfunc; 24798a7d6542SBram Moolenaar int r; 24806f5b6dfbSBram Moolenaar typval_T partial_tv; 24818a7d6542SBram Moolenaar 24828a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 24838a7d6542SBram Moolenaar if (pfunc->cpf_top) 24848a7d6542SBram Moolenaar { 24858a7d6542SBram Moolenaar // funcref is above the arguments 24868a7d6542SBram Moolenaar tv = STACK_TV_BOT(-pfunc->cpf_argcount - 1); 24878a7d6542SBram Moolenaar } 24888a7d6542SBram Moolenaar else 24898a7d6542SBram Moolenaar { 24908a7d6542SBram Moolenaar // Get the funcref from the stack. 24918a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 24926f5b6dfbSBram Moolenaar partial_tv = *STACK_TV_BOT(0); 24936f5b6dfbSBram Moolenaar tv = &partial_tv; 24948a7d6542SBram Moolenaar } 24958a7d6542SBram Moolenaar r = call_partial(tv, pfunc->cpf_argcount, &ectx); 24966f5b6dfbSBram Moolenaar if (tv == &partial_tv) 24976f5b6dfbSBram Moolenaar clear_tv(&partial_tv); 24988a7d6542SBram Moolenaar if (r == FAIL) 2499d032f34aSBram Moolenaar goto on_error; 2500bd5da371SBram Moolenaar } 2501bd5da371SBram Moolenaar break; 25028a7d6542SBram Moolenaar 2503bd5da371SBram Moolenaar case ISN_PCALL_END: 2504bd5da371SBram Moolenaar // PCALL finished, arguments have been consumed and replaced by 2505bd5da371SBram Moolenaar // the return value. Now clear the funcref from the stack, 2506bd5da371SBram Moolenaar // and move the return value in its place. 25078a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 2508bd5da371SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 25098a7d6542SBram Moolenaar *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); 25108a7d6542SBram Moolenaar break; 25118a7d6542SBram Moolenaar 25128a7d6542SBram Moolenaar // call a user defined function or funcref/partial 25138a7d6542SBram Moolenaar case ISN_UCALL: 25148a7d6542SBram Moolenaar { 25158a7d6542SBram Moolenaar cufunc_T *cufunc = &iptr->isn_arg.ufunc; 25168a7d6542SBram Moolenaar 25178a7d6542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 25188a7d6542SBram Moolenaar if (call_eval_func(cufunc->cuf_name, 25197eeefd4aSBram Moolenaar cufunc->cuf_argcount, &ectx, iptr) == FAIL) 2520d032f34aSBram Moolenaar goto on_error; 25218a7d6542SBram Moolenaar } 25228a7d6542SBram Moolenaar break; 25238a7d6542SBram Moolenaar 25248a7d6542SBram Moolenaar // return from a :def function call 2525299f3036SBram Moolenaar case ISN_RETURN_ZERO: 2526299f3036SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 2527299f3036SBram Moolenaar goto failed; 2528299f3036SBram Moolenaar tv = STACK_TV_BOT(0); 2529299f3036SBram Moolenaar ++ectx.ec_stack.ga_len; 2530299f3036SBram Moolenaar tv->v_type = VAR_NUMBER; 2531299f3036SBram Moolenaar tv->vval.v_number = 0; 2532299f3036SBram Moolenaar tv->v_lock = 0; 2533299f3036SBram Moolenaar // FALLTHROUGH 2534299f3036SBram Moolenaar 25358a7d6542SBram Moolenaar case ISN_RETURN: 25368a7d6542SBram Moolenaar { 25378cbd6dfcSBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 253820431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 25398cbd6dfcSBram Moolenaar 25408cbd6dfcSBram Moolenaar if (trystack->ga_len > 0) 25418cbd6dfcSBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 25428cbd6dfcSBram Moolenaar + trystack->ga_len - 1; 2543bf67ea1aSBram Moolenaar if (trycmd != NULL 25449cb577a6SBram Moolenaar && trycmd->tcd_frame_idx == ectx.ec_frame_idx) 25458a7d6542SBram Moolenaar { 25469cb577a6SBram Moolenaar // jump to ":finally" or ":endtry" 25479cb577a6SBram Moolenaar if (trycmd->tcd_finally_idx != 0) 25488a7d6542SBram Moolenaar ectx.ec_iidx = trycmd->tcd_finally_idx; 25499cb577a6SBram Moolenaar else 25509cb577a6SBram Moolenaar ectx.ec_iidx = trycmd->tcd_endtry_idx; 25518a7d6542SBram Moolenaar trycmd->tcd_return = TRUE; 25528a7d6542SBram Moolenaar } 25538a7d6542SBram Moolenaar else 2554d032f34aSBram Moolenaar goto func_return; 25558a7d6542SBram Moolenaar } 25568a7d6542SBram Moolenaar break; 25578a7d6542SBram Moolenaar 25588a7d6542SBram Moolenaar // push a function reference to a compiled function 25598a7d6542SBram Moolenaar case ISN_FUNCREF: 25608a7d6542SBram Moolenaar { 2561f112f30aSBram Moolenaar partial_T *pt = ALLOC_CLEAR_ONE(partial_T); 2562f112f30aSBram Moolenaar dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data) 2563f112f30aSBram Moolenaar + iptr->isn_arg.funcref.fr_func; 25648a7d6542SBram Moolenaar 25658a7d6542SBram Moolenaar if (pt == NULL) 25668a7d6542SBram Moolenaar goto failed; 2567270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 2568c8cd2b34SBram Moolenaar { 2569bf67ea1aSBram Moolenaar vim_free(pt); 2570bf67ea1aSBram Moolenaar goto failed; 2571bf67ea1aSBram Moolenaar } 2572f112f30aSBram Moolenaar if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc, 2573f112f30aSBram Moolenaar &ectx) == FAIL) 2574bf67ea1aSBram Moolenaar goto failed; 2575c8cd2b34SBram Moolenaar 25768a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 25778a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 25788a7d6542SBram Moolenaar tv->vval.v_partial = pt; 25798a7d6542SBram Moolenaar tv->v_type = VAR_PARTIAL; 25802f8ce0aeSBram Moolenaar tv->v_lock = 0; 25818a7d6542SBram Moolenaar } 25828a7d6542SBram Moolenaar break; 25838a7d6542SBram Moolenaar 258438ddf333SBram Moolenaar // Create a global function from a lambda. 258538ddf333SBram Moolenaar case ISN_NEWFUNC: 258638ddf333SBram Moolenaar { 258738ddf333SBram Moolenaar newfunc_T *newfunc = &iptr->isn_arg.newfunc; 258838ddf333SBram Moolenaar 2589cd45ed03SBram Moolenaar if (copy_func(newfunc->nf_lambda, newfunc->nf_global, 2590f112f30aSBram Moolenaar &ectx) == FAIL) 2591f112f30aSBram Moolenaar goto failed; 259238ddf333SBram Moolenaar } 259338ddf333SBram Moolenaar break; 259438ddf333SBram Moolenaar 25956abdcf82SBram Moolenaar // List functions 25966abdcf82SBram Moolenaar case ISN_DEF: 25976abdcf82SBram Moolenaar if (iptr->isn_arg.string == NULL) 25986abdcf82SBram Moolenaar list_functions(NULL); 25996abdcf82SBram Moolenaar else 26006abdcf82SBram Moolenaar { 26016abdcf82SBram Moolenaar exarg_T ea; 26026abdcf82SBram Moolenaar 26036abdcf82SBram Moolenaar CLEAR_FIELD(ea); 26046abdcf82SBram Moolenaar ea.cmd = ea.arg = iptr->isn_arg.string; 26056abdcf82SBram Moolenaar define_function(&ea, NULL); 26066abdcf82SBram Moolenaar } 26076abdcf82SBram Moolenaar break; 26086abdcf82SBram Moolenaar 26098a7d6542SBram Moolenaar // jump if a condition is met 26108a7d6542SBram Moolenaar case ISN_JUMP: 26118a7d6542SBram Moolenaar { 26128a7d6542SBram Moolenaar jumpwhen_T when = iptr->isn_arg.jump.jump_when; 26132bb2658bSBram Moolenaar int error = FALSE; 26148a7d6542SBram Moolenaar int jump = TRUE; 26158a7d6542SBram Moolenaar 26168a7d6542SBram Moolenaar if (when != JUMP_ALWAYS) 26178a7d6542SBram Moolenaar { 26188a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 26192bb2658bSBram Moolenaar if (when == JUMP_IF_COND_FALSE 262013106605SBram Moolenaar || when == JUMP_IF_FALSE 26212bb2658bSBram Moolenaar || when == JUMP_IF_COND_TRUE) 26222bb2658bSBram Moolenaar { 26232bb2658bSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 26242bb2658bSBram Moolenaar jump = tv_get_bool_chk(tv, &error); 26252bb2658bSBram Moolenaar if (error) 26262bb2658bSBram Moolenaar goto on_error; 26272bb2658bSBram Moolenaar } 26282bb2658bSBram Moolenaar else 26298a7d6542SBram Moolenaar jump = tv2bool(tv); 26308a7d6542SBram Moolenaar if (when == JUMP_IF_FALSE 26312bb2658bSBram Moolenaar || when == JUMP_AND_KEEP_IF_FALSE 26322bb2658bSBram Moolenaar || when == JUMP_IF_COND_FALSE) 26338a7d6542SBram Moolenaar jump = !jump; 2634777770fbSBram Moolenaar if (when == JUMP_IF_FALSE || !jump) 26358a7d6542SBram Moolenaar { 26368a7d6542SBram Moolenaar // drop the value from the stack 26378a7d6542SBram Moolenaar clear_tv(tv); 26388a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 26398a7d6542SBram Moolenaar } 26408a7d6542SBram Moolenaar } 26418a7d6542SBram Moolenaar if (jump) 26428a7d6542SBram Moolenaar ectx.ec_iidx = iptr->isn_arg.jump.jump_where; 26438a7d6542SBram Moolenaar } 26448a7d6542SBram Moolenaar break; 26458a7d6542SBram Moolenaar 26468a7d6542SBram Moolenaar // top of a for loop 26478a7d6542SBram Moolenaar case ISN_FOR: 26488a7d6542SBram Moolenaar { 26498a7d6542SBram Moolenaar list_T *list = STACK_TV_BOT(-1)->vval.v_list; 26508a7d6542SBram Moolenaar typval_T *idxtv = 26518a7d6542SBram Moolenaar STACK_TV_VAR(iptr->isn_arg.forloop.for_idx); 26528a7d6542SBram Moolenaar 26538a7d6542SBram Moolenaar // push the next item from the list 2654270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 26558a7d6542SBram Moolenaar goto failed; 265677e5dcc3SBram Moolenaar ++idxtv->vval.v_number; 265777e5dcc3SBram Moolenaar if (list == NULL || idxtv->vval.v_number >= list->lv_len) 26588a7d6542SBram Moolenaar // past the end of the list, jump to "endfor" 26598a7d6542SBram Moolenaar ectx.ec_iidx = iptr->isn_arg.forloop.for_end; 26608a7d6542SBram Moolenaar else if (list->lv_first == &range_list_item) 26618a7d6542SBram Moolenaar { 26628a7d6542SBram Moolenaar // non-materialized range() list 26638a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 26648a7d6542SBram Moolenaar tv->v_type = VAR_NUMBER; 26652f8ce0aeSBram Moolenaar tv->v_lock = 0; 26668a7d6542SBram Moolenaar tv->vval.v_number = list_find_nr( 26678a7d6542SBram Moolenaar list, idxtv->vval.v_number, NULL); 26688a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 26698a7d6542SBram Moolenaar } 26708a7d6542SBram Moolenaar else 26718a7d6542SBram Moolenaar { 26728a7d6542SBram Moolenaar listitem_T *li = list_find(list, idxtv->vval.v_number); 26738a7d6542SBram Moolenaar 26748a7d6542SBram Moolenaar copy_tv(&li->li_tv, STACK_TV_BOT(0)); 26758a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 26768a7d6542SBram Moolenaar } 26778a7d6542SBram Moolenaar } 26788a7d6542SBram Moolenaar break; 26798a7d6542SBram Moolenaar 26808a7d6542SBram Moolenaar // start of ":try" block 26818a7d6542SBram Moolenaar case ISN_TRY: 26828a7d6542SBram Moolenaar { 268320431c9dSBram Moolenaar trycmd_T *trycmd = NULL; 268420431c9dSBram Moolenaar 2685270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_trystack, 1) == FAIL) 26868a7d6542SBram Moolenaar goto failed; 26878a7d6542SBram Moolenaar trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data) 26888a7d6542SBram Moolenaar + ectx.ec_trystack.ga_len; 26898a7d6542SBram Moolenaar ++ectx.ec_trystack.ga_len; 26908a7d6542SBram Moolenaar ++trylevel; 26918d4be890SBram Moolenaar CLEAR_POINTER(trycmd); 2692bf67ea1aSBram Moolenaar trycmd->tcd_frame_idx = ectx.ec_frame_idx; 2693d9d7789bSBram Moolenaar trycmd->tcd_stack_len = ectx.ec_stack.ga_len; 26947e82c5f3SBram Moolenaar trycmd->tcd_catch_idx = iptr->isn_arg.try.try_ref->try_catch; 26957e82c5f3SBram Moolenaar trycmd->tcd_finally_idx = iptr->isn_arg.try.try_ref->try_finally; 26967e82c5f3SBram Moolenaar trycmd->tcd_endtry_idx = iptr->isn_arg.try.try_ref->try_endtry; 26978a7d6542SBram Moolenaar } 26988a7d6542SBram Moolenaar break; 26998a7d6542SBram Moolenaar 27008a7d6542SBram Moolenaar case ISN_PUSHEXC: 27018a7d6542SBram Moolenaar if (current_exception == NULL) 27028a7d6542SBram Moolenaar { 27037517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 27048a7d6542SBram Moolenaar iemsg("Evaluating catch while current_exception is NULL"); 27058a7d6542SBram Moolenaar goto failed; 27068a7d6542SBram Moolenaar } 2707270d0388SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 27088a7d6542SBram Moolenaar goto failed; 27098a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 27108a7d6542SBram Moolenaar ++ectx.ec_stack.ga_len; 27118a7d6542SBram Moolenaar tv->v_type = VAR_STRING; 27122f8ce0aeSBram Moolenaar tv->v_lock = 0; 27138a7d6542SBram Moolenaar tv->vval.v_string = vim_strsave( 27148a7d6542SBram Moolenaar (char_u *)current_exception->value); 27158a7d6542SBram Moolenaar break; 27168a7d6542SBram Moolenaar 27178a7d6542SBram Moolenaar case ISN_CATCH: 27188a7d6542SBram Moolenaar { 27198a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 27208a7d6542SBram Moolenaar 272120a76298SBram Moolenaar if (restore_cmdmod) 272220a76298SBram Moolenaar { 272320a76298SBram Moolenaar cmdmod.cmod_filter_regmatch.regprog = NULL; 272420a76298SBram Moolenaar undo_cmdmod(&cmdmod); 272520a76298SBram Moolenaar cmdmod = save_cmdmod; 272620a76298SBram Moolenaar restore_cmdmod = FALSE; 272720a76298SBram Moolenaar } 27288a7d6542SBram Moolenaar if (trystack->ga_len > 0) 27298a7d6542SBram Moolenaar { 273020431c9dSBram Moolenaar trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data) 27318a7d6542SBram Moolenaar + trystack->ga_len - 1; 27328a7d6542SBram Moolenaar trycmd->tcd_caught = TRUE; 27338a7d6542SBram Moolenaar } 27348a7d6542SBram Moolenaar did_emsg = got_int = did_throw = FALSE; 27351430ceebSBram Moolenaar force_abort = need_rethrow = FALSE; 27368a7d6542SBram Moolenaar catch_exception(current_exception); 27378a7d6542SBram Moolenaar } 27388a7d6542SBram Moolenaar break; 27398a7d6542SBram Moolenaar 2740c150c09eSBram Moolenaar case ISN_TRYCONT: 2741c150c09eSBram Moolenaar { 2742c150c09eSBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 2743c150c09eSBram Moolenaar trycont_T *trycont = &iptr->isn_arg.trycont; 2744c150c09eSBram Moolenaar int i; 2745c150c09eSBram Moolenaar trycmd_T *trycmd; 2746c150c09eSBram Moolenaar int iidx = trycont->tct_where; 2747c150c09eSBram Moolenaar 2748c150c09eSBram Moolenaar if (trystack->ga_len < trycont->tct_levels) 2749c150c09eSBram Moolenaar { 2750c150c09eSBram Moolenaar siemsg("TRYCONT: expected %d levels, found %d", 2751c150c09eSBram Moolenaar trycont->tct_levels, trystack->ga_len); 2752c150c09eSBram Moolenaar goto failed; 2753c150c09eSBram Moolenaar } 2754c150c09eSBram Moolenaar // Make :endtry jump to any outer try block and the last 2755c150c09eSBram Moolenaar // :endtry inside the loop to the loop start. 2756c150c09eSBram Moolenaar for (i = trycont->tct_levels; i > 0; --i) 2757c150c09eSBram Moolenaar { 2758c150c09eSBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 2759c150c09eSBram Moolenaar + trystack->ga_len - i; 2760c150c09eSBram Moolenaar trycmd->tcd_cont = iidx; 27617e82c5f3SBram Moolenaar iidx = trycmd->tcd_finally_idx == 0 27627e82c5f3SBram Moolenaar ? trycmd->tcd_endtry_idx : trycmd->tcd_finally_idx; 2763c150c09eSBram Moolenaar } 2764c150c09eSBram Moolenaar // jump to :finally or :endtry of current try statement 2765c150c09eSBram Moolenaar ectx.ec_iidx = iidx; 2766c150c09eSBram Moolenaar } 2767c150c09eSBram Moolenaar break; 2768c150c09eSBram Moolenaar 27697e82c5f3SBram Moolenaar case ISN_FINALLY: 27707e82c5f3SBram Moolenaar { 27717e82c5f3SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 27727e82c5f3SBram Moolenaar trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data) 27737e82c5f3SBram Moolenaar + trystack->ga_len - 1; 27747e82c5f3SBram Moolenaar 27757e82c5f3SBram Moolenaar // Reset the index to avoid a return statement jumps here 27767e82c5f3SBram Moolenaar // again. 27777e82c5f3SBram Moolenaar trycmd->tcd_finally_idx = 0; 27787e82c5f3SBram Moolenaar break; 27797e82c5f3SBram Moolenaar } 27807e82c5f3SBram Moolenaar 27818a7d6542SBram Moolenaar // end of ":try" block 27828a7d6542SBram Moolenaar case ISN_ENDTRY: 27838a7d6542SBram Moolenaar { 27848a7d6542SBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 27858a7d6542SBram Moolenaar 27868a7d6542SBram Moolenaar if (trystack->ga_len > 0) 27878a7d6542SBram Moolenaar { 2788107e9cecSBram Moolenaar trycmd_T *trycmd; 278920431c9dSBram Moolenaar 27908a7d6542SBram Moolenaar --trystack->ga_len; 27918a7d6542SBram Moolenaar --trylevel; 279268d130c6SBram Moolenaar ectx.ec_in_catch = FALSE; 27938a7d6542SBram Moolenaar trycmd = ((trycmd_T *)trystack->ga_data) 27948a7d6542SBram Moolenaar + trystack->ga_len; 2795f575adffSBram Moolenaar if (trycmd->tcd_caught && current_exception != NULL) 27968a7d6542SBram Moolenaar { 27978a7d6542SBram Moolenaar // discard the exception 27988a7d6542SBram Moolenaar if (caught_stack == current_exception) 27998a7d6542SBram Moolenaar caught_stack = caught_stack->caught; 28008a7d6542SBram Moolenaar discard_current_exception(); 28018a7d6542SBram Moolenaar } 28028a7d6542SBram Moolenaar 28038a7d6542SBram Moolenaar if (trycmd->tcd_return) 2804d032f34aSBram Moolenaar goto func_return; 2805d9d7789bSBram Moolenaar 2806d9d7789bSBram Moolenaar while (ectx.ec_stack.ga_len > trycmd->tcd_stack_len) 2807d9d7789bSBram Moolenaar { 2808d9d7789bSBram Moolenaar --ectx.ec_stack.ga_len; 2809d9d7789bSBram Moolenaar clear_tv(STACK_TV_BOT(0)); 2810d9d7789bSBram Moolenaar } 28118d4be890SBram Moolenaar if (trycmd->tcd_cont != 0) 2812c150c09eSBram Moolenaar // handling :continue: jump to outer try block or 2813c150c09eSBram Moolenaar // start of the loop 2814c150c09eSBram Moolenaar ectx.ec_iidx = trycmd->tcd_cont; 28158a7d6542SBram Moolenaar } 28168a7d6542SBram Moolenaar } 28178a7d6542SBram Moolenaar break; 28188a7d6542SBram Moolenaar 28198a7d6542SBram Moolenaar case ISN_THROW: 28208f81b22eSBram Moolenaar { 2821107e9cecSBram Moolenaar garray_T *trystack = &ectx.ec_trystack; 2822107e9cecSBram Moolenaar 2823107e9cecSBram Moolenaar if (trystack->ga_len == 0 && trylevel == 0 && emsg_silent) 2824107e9cecSBram Moolenaar { 2825107e9cecSBram Moolenaar // throwing an exception while using "silent!" causes 2826107e9cecSBram Moolenaar // the function to abort but not display an error. 28278f81b22eSBram Moolenaar tv = STACK_TV_BOT(-1); 28288f81b22eSBram Moolenaar clear_tv(tv); 28298f81b22eSBram Moolenaar tv->v_type = VAR_NUMBER; 28308f81b22eSBram Moolenaar tv->vval.v_number = 0; 28318f81b22eSBram Moolenaar goto done; 28328f81b22eSBram Moolenaar } 28338a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 28348a7d6542SBram Moolenaar tv = STACK_TV_BOT(0); 28351e021e63SBram Moolenaar if (tv->vval.v_string == NULL 28361e021e63SBram Moolenaar || *skipwhite(tv->vval.v_string) == NUL) 28371e021e63SBram Moolenaar { 2838335e6713SBram Moolenaar vim_free(tv->vval.v_string); 28391dcae599SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 28401e021e63SBram Moolenaar emsg(_(e_throw_with_empty_string)); 28411e021e63SBram Moolenaar goto failed; 28421e021e63SBram Moolenaar } 28431e021e63SBram Moolenaar 2844107e9cecSBram Moolenaar // Inside a "catch" we need to first discard the caught 2845107e9cecSBram Moolenaar // exception. 2846107e9cecSBram Moolenaar if (trystack->ga_len > 0) 2847107e9cecSBram Moolenaar { 2848107e9cecSBram Moolenaar trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data) 2849107e9cecSBram Moolenaar + trystack->ga_len - 1; 2850107e9cecSBram Moolenaar if (trycmd->tcd_caught && current_exception != NULL) 2851107e9cecSBram Moolenaar { 2852107e9cecSBram Moolenaar // discard the exception 2853107e9cecSBram Moolenaar if (caught_stack == current_exception) 2854107e9cecSBram Moolenaar caught_stack = caught_stack->caught; 2855107e9cecSBram Moolenaar discard_current_exception(); 2856107e9cecSBram Moolenaar trycmd->tcd_caught = FALSE; 2857107e9cecSBram Moolenaar } 2858107e9cecSBram Moolenaar } 2859107e9cecSBram Moolenaar 2860107e9cecSBram Moolenaar if (throw_exception(tv->vval.v_string, ET_USER, NULL) 2861107e9cecSBram Moolenaar == FAIL) 28628a7d6542SBram Moolenaar { 28638a7d6542SBram Moolenaar vim_free(tv->vval.v_string); 28648a7d6542SBram Moolenaar goto failed; 28658a7d6542SBram Moolenaar } 28668a7d6542SBram Moolenaar did_throw = TRUE; 2867107e9cecSBram Moolenaar } 28688a7d6542SBram Moolenaar break; 28698a7d6542SBram Moolenaar 28708a7d6542SBram Moolenaar // compare with special values 28718a7d6542SBram Moolenaar case ISN_COMPAREBOOL: 28728a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 28738a7d6542SBram Moolenaar { 28748a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 28758a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 28768a7d6542SBram Moolenaar varnumber_T arg1 = tv1->vval.v_number; 28778a7d6542SBram Moolenaar varnumber_T arg2 = tv2->vval.v_number; 28788a7d6542SBram Moolenaar int res; 28798a7d6542SBram Moolenaar 28808a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 28818a7d6542SBram Moolenaar { 28828a7d6542SBram Moolenaar case EXPR_EQUAL: res = arg1 == arg2; break; 28838a7d6542SBram Moolenaar case EXPR_NEQUAL: res = arg1 != arg2; break; 28848a7d6542SBram Moolenaar default: res = 0; break; 28858a7d6542SBram Moolenaar } 28868a7d6542SBram Moolenaar 28878a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 28888a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 28898a7d6542SBram Moolenaar tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; 28908a7d6542SBram Moolenaar } 28918a7d6542SBram Moolenaar break; 28928a7d6542SBram Moolenaar 28938a7d6542SBram Moolenaar // Operation with two number arguments 28948a7d6542SBram Moolenaar case ISN_OPNR: 28958a7d6542SBram Moolenaar case ISN_COMPARENR: 28968a7d6542SBram Moolenaar { 28978a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 28988a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 28998a7d6542SBram Moolenaar varnumber_T arg1 = tv1->vval.v_number; 29008a7d6542SBram Moolenaar varnumber_T arg2 = tv2->vval.v_number; 29018a7d6542SBram Moolenaar varnumber_T res; 29028a7d6542SBram Moolenaar 29038a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 29048a7d6542SBram Moolenaar { 29058a7d6542SBram Moolenaar case EXPR_MULT: res = arg1 * arg2; break; 29068a7d6542SBram Moolenaar case EXPR_DIV: res = arg1 / arg2; break; 29078a7d6542SBram Moolenaar case EXPR_REM: res = arg1 % arg2; break; 29088a7d6542SBram Moolenaar case EXPR_SUB: res = arg1 - arg2; break; 29098a7d6542SBram Moolenaar case EXPR_ADD: res = arg1 + arg2; break; 29108a7d6542SBram Moolenaar 29118a7d6542SBram Moolenaar case EXPR_EQUAL: res = arg1 == arg2; break; 29128a7d6542SBram Moolenaar case EXPR_NEQUAL: res = arg1 != arg2; break; 29138a7d6542SBram Moolenaar case EXPR_GREATER: res = arg1 > arg2; break; 29148a7d6542SBram Moolenaar case EXPR_GEQUAL: res = arg1 >= arg2; break; 29158a7d6542SBram Moolenaar case EXPR_SMALLER: res = arg1 < arg2; break; 29168a7d6542SBram Moolenaar case EXPR_SEQUAL: res = arg1 <= arg2; break; 29178a7d6542SBram Moolenaar default: res = 0; break; 29188a7d6542SBram Moolenaar } 29198a7d6542SBram Moolenaar 29208a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 29218a7d6542SBram Moolenaar if (iptr->isn_type == ISN_COMPARENR) 29228a7d6542SBram Moolenaar { 29238a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 29248a7d6542SBram Moolenaar tv1->vval.v_number = res ? VVAL_TRUE : VVAL_FALSE; 29258a7d6542SBram Moolenaar } 29268a7d6542SBram Moolenaar else 29278a7d6542SBram Moolenaar tv1->vval.v_number = res; 29288a7d6542SBram Moolenaar } 29298a7d6542SBram Moolenaar break; 29308a7d6542SBram Moolenaar 29318a7d6542SBram Moolenaar // Computation with two float arguments 29328a7d6542SBram Moolenaar case ISN_OPFLOAT: 29338a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: 2934a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT 29358a7d6542SBram Moolenaar { 29368a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 29378a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 29388a7d6542SBram Moolenaar float_T arg1 = tv1->vval.v_float; 29398a7d6542SBram Moolenaar float_T arg2 = tv2->vval.v_float; 29408a7d6542SBram Moolenaar float_T res = 0; 29418a7d6542SBram Moolenaar int cmp = FALSE; 29428a7d6542SBram Moolenaar 29438a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 29448a7d6542SBram Moolenaar { 29458a7d6542SBram Moolenaar case EXPR_MULT: res = arg1 * arg2; break; 29468a7d6542SBram Moolenaar case EXPR_DIV: res = arg1 / arg2; break; 29478a7d6542SBram Moolenaar case EXPR_SUB: res = arg1 - arg2; break; 29488a7d6542SBram Moolenaar case EXPR_ADD: res = arg1 + arg2; break; 29498a7d6542SBram Moolenaar 29508a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = arg1 == arg2; break; 29518a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = arg1 != arg2; break; 29528a7d6542SBram Moolenaar case EXPR_GREATER: cmp = arg1 > arg2; break; 29538a7d6542SBram Moolenaar case EXPR_GEQUAL: cmp = arg1 >= arg2; break; 29548a7d6542SBram Moolenaar case EXPR_SMALLER: cmp = arg1 < arg2; break; 29558a7d6542SBram Moolenaar case EXPR_SEQUAL: cmp = arg1 <= arg2; break; 29568a7d6542SBram Moolenaar default: cmp = 0; break; 29578a7d6542SBram Moolenaar } 29588a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 29598a7d6542SBram Moolenaar if (iptr->isn_type == ISN_COMPAREFLOAT) 29608a7d6542SBram Moolenaar { 29618a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 29628a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 29638a7d6542SBram Moolenaar } 29648a7d6542SBram Moolenaar else 29658a7d6542SBram Moolenaar tv1->vval.v_float = res; 29668a7d6542SBram Moolenaar } 2967a5d5953dSBram Moolenaar #endif 29688a7d6542SBram Moolenaar break; 29698a7d6542SBram Moolenaar 29708a7d6542SBram Moolenaar case ISN_COMPARELIST: 29718a7d6542SBram Moolenaar { 29728a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 29738a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 29748a7d6542SBram Moolenaar list_T *arg1 = tv1->vval.v_list; 29758a7d6542SBram Moolenaar list_T *arg2 = tv2->vval.v_list; 29768a7d6542SBram Moolenaar int cmp = FALSE; 29778a7d6542SBram Moolenaar int ic = iptr->isn_arg.op.op_ic; 29788a7d6542SBram Moolenaar 29798a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 29808a7d6542SBram Moolenaar { 29818a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = 29828a7d6542SBram Moolenaar list_equal(arg1, arg2, ic, FALSE); break; 29838a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = 29848a7d6542SBram Moolenaar !list_equal(arg1, arg2, ic, FALSE); break; 29858a7d6542SBram Moolenaar case EXPR_IS: cmp = arg1 == arg2; break; 29868a7d6542SBram Moolenaar case EXPR_ISNOT: cmp = arg1 != arg2; break; 29878a7d6542SBram Moolenaar default: cmp = 0; break; 29888a7d6542SBram Moolenaar } 29898a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 29908a7d6542SBram Moolenaar clear_tv(tv1); 29918a7d6542SBram Moolenaar clear_tv(tv2); 29928a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 29938a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 29948a7d6542SBram Moolenaar } 29958a7d6542SBram Moolenaar break; 29968a7d6542SBram Moolenaar 29978a7d6542SBram Moolenaar case ISN_COMPAREBLOB: 29988a7d6542SBram Moolenaar { 29998a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 30008a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 30018a7d6542SBram Moolenaar blob_T *arg1 = tv1->vval.v_blob; 30028a7d6542SBram Moolenaar blob_T *arg2 = tv2->vval.v_blob; 30038a7d6542SBram Moolenaar int cmp = FALSE; 30048a7d6542SBram Moolenaar 30058a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 30068a7d6542SBram Moolenaar { 30078a7d6542SBram Moolenaar case EXPR_EQUAL: cmp = blob_equal(arg1, arg2); break; 30088a7d6542SBram Moolenaar case EXPR_NEQUAL: cmp = !blob_equal(arg1, arg2); break; 30098a7d6542SBram Moolenaar case EXPR_IS: cmp = arg1 == arg2; break; 30108a7d6542SBram Moolenaar case EXPR_ISNOT: cmp = arg1 != arg2; break; 30118a7d6542SBram Moolenaar default: cmp = 0; break; 30128a7d6542SBram Moolenaar } 30138a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 30148a7d6542SBram Moolenaar clear_tv(tv1); 30158a7d6542SBram Moolenaar clear_tv(tv2); 30168a7d6542SBram Moolenaar tv1->v_type = VAR_BOOL; 30178a7d6542SBram Moolenaar tv1->vval.v_number = cmp ? VVAL_TRUE : VVAL_FALSE; 30188a7d6542SBram Moolenaar } 30198a7d6542SBram Moolenaar break; 30208a7d6542SBram Moolenaar 30218a7d6542SBram Moolenaar // TODO: handle separately 30228a7d6542SBram Moolenaar case ISN_COMPARESTRING: 30238a7d6542SBram Moolenaar case ISN_COMPAREDICT: 30248a7d6542SBram Moolenaar case ISN_COMPAREFUNC: 30258a7d6542SBram Moolenaar case ISN_COMPAREANY: 30268a7d6542SBram Moolenaar { 30278a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 30288a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 3029657137caSBram Moolenaar exprtype_T exprtype = iptr->isn_arg.op.op_type; 30308a7d6542SBram Moolenaar int ic = iptr->isn_arg.op.op_ic; 30318a7d6542SBram Moolenaar 3032eb26f433SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3033657137caSBram Moolenaar typval_compare(tv1, tv2, exprtype, ic); 30348a7d6542SBram Moolenaar clear_tv(tv2); 30358a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 30368a7d6542SBram Moolenaar } 30378a7d6542SBram Moolenaar break; 30388a7d6542SBram Moolenaar 30398a7d6542SBram Moolenaar case ISN_ADDLIST: 30408a7d6542SBram Moolenaar case ISN_ADDBLOB: 30418a7d6542SBram Moolenaar { 30428a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 30438a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 30448a7d6542SBram Moolenaar 30451dcae599SBram Moolenaar // add two lists or blobs 30468a7d6542SBram Moolenaar if (iptr->isn_type == ISN_ADDLIST) 30478a7d6542SBram Moolenaar eval_addlist(tv1, tv2); 30488a7d6542SBram Moolenaar else 30498a7d6542SBram Moolenaar eval_addblob(tv1, tv2); 30508a7d6542SBram Moolenaar clear_tv(tv2); 30518a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 30528a7d6542SBram Moolenaar } 30538a7d6542SBram Moolenaar break; 30548a7d6542SBram Moolenaar 30551dcae599SBram Moolenaar case ISN_LISTAPPEND: 30561dcae599SBram Moolenaar { 30571dcae599SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 30581dcae599SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 30591dcae599SBram Moolenaar list_T *l = tv1->vval.v_list; 30601dcae599SBram Moolenaar 30611dcae599SBram Moolenaar // add an item to a list 30621dcae599SBram Moolenaar if (l == NULL) 30631dcae599SBram Moolenaar { 30641dcae599SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 30651dcae599SBram Moolenaar emsg(_(e_cannot_add_to_null_list)); 30661dcae599SBram Moolenaar goto on_error; 30671dcae599SBram Moolenaar } 30681dcae599SBram Moolenaar if (list_append_tv(l, tv2) == FAIL) 30691dcae599SBram Moolenaar goto failed; 3070955347ccSBram Moolenaar clear_tv(tv2); 30711dcae599SBram Moolenaar --ectx.ec_stack.ga_len; 30721dcae599SBram Moolenaar } 30731dcae599SBram Moolenaar break; 30741dcae599SBram Moolenaar 307580b0e5eaSBram Moolenaar case ISN_BLOBAPPEND: 307680b0e5eaSBram Moolenaar { 307780b0e5eaSBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 307880b0e5eaSBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 307980b0e5eaSBram Moolenaar blob_T *b = tv1->vval.v_blob; 308080b0e5eaSBram Moolenaar int error = FALSE; 308180b0e5eaSBram Moolenaar varnumber_T n; 308280b0e5eaSBram Moolenaar 308380b0e5eaSBram Moolenaar // add a number to a blob 308480b0e5eaSBram Moolenaar if (b == NULL) 308580b0e5eaSBram Moolenaar { 308680b0e5eaSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 308780b0e5eaSBram Moolenaar emsg(_(e_cannot_add_to_null_blob)); 308880b0e5eaSBram Moolenaar goto on_error; 308980b0e5eaSBram Moolenaar } 309080b0e5eaSBram Moolenaar n = tv_get_number_chk(tv2, &error); 309180b0e5eaSBram Moolenaar if (error) 309280b0e5eaSBram Moolenaar goto on_error; 309380b0e5eaSBram Moolenaar ga_append(&b->bv_ga, (int)n); 309480b0e5eaSBram Moolenaar --ectx.ec_stack.ga_len; 309580b0e5eaSBram Moolenaar } 309680b0e5eaSBram Moolenaar break; 309780b0e5eaSBram Moolenaar 30988a7d6542SBram Moolenaar // Computation with two arguments of unknown type 30998a7d6542SBram Moolenaar case ISN_OPANY: 31008a7d6542SBram Moolenaar { 31018a7d6542SBram Moolenaar typval_T *tv1 = STACK_TV_BOT(-2); 31028a7d6542SBram Moolenaar typval_T *tv2 = STACK_TV_BOT(-1); 31038a7d6542SBram Moolenaar varnumber_T n1, n2; 31048a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 31058a7d6542SBram Moolenaar float_T f1 = 0, f2 = 0; 31068a7d6542SBram Moolenaar #endif 31078a7d6542SBram Moolenaar int error = FALSE; 31088a7d6542SBram Moolenaar 31098a7d6542SBram Moolenaar if (iptr->isn_arg.op.op_type == EXPR_ADD) 31108a7d6542SBram Moolenaar { 31118a7d6542SBram Moolenaar if (tv1->v_type == VAR_LIST && tv2->v_type == VAR_LIST) 31128a7d6542SBram Moolenaar { 31138a7d6542SBram Moolenaar eval_addlist(tv1, tv2); 31148a7d6542SBram Moolenaar clear_tv(tv2); 31158a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 31168a7d6542SBram Moolenaar break; 31178a7d6542SBram Moolenaar } 31188a7d6542SBram Moolenaar else if (tv1->v_type == VAR_BLOB 31198a7d6542SBram Moolenaar && tv2->v_type == VAR_BLOB) 31208a7d6542SBram Moolenaar { 31218a7d6542SBram Moolenaar eval_addblob(tv1, tv2); 31228a7d6542SBram Moolenaar clear_tv(tv2); 31238a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 31248a7d6542SBram Moolenaar break; 31258a7d6542SBram Moolenaar } 31268a7d6542SBram Moolenaar } 31278a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 31288a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT) 31298a7d6542SBram Moolenaar { 31308a7d6542SBram Moolenaar f1 = tv1->vval.v_float; 31318a7d6542SBram Moolenaar n1 = 0; 31328a7d6542SBram Moolenaar } 31338a7d6542SBram Moolenaar else 31348a7d6542SBram Moolenaar #endif 31358a7d6542SBram Moolenaar { 3136f665e97fSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 31378a7d6542SBram Moolenaar n1 = tv_get_number_chk(tv1, &error); 31388a7d6542SBram Moolenaar if (error) 3139d032f34aSBram Moolenaar goto on_error; 31408a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 31418a7d6542SBram Moolenaar if (tv2->v_type == VAR_FLOAT) 31428a7d6542SBram Moolenaar f1 = n1; 31438a7d6542SBram Moolenaar #endif 31448a7d6542SBram Moolenaar } 31458a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 31468a7d6542SBram Moolenaar if (tv2->v_type == VAR_FLOAT) 31478a7d6542SBram Moolenaar { 31488a7d6542SBram Moolenaar f2 = tv2->vval.v_float; 31498a7d6542SBram Moolenaar n2 = 0; 31508a7d6542SBram Moolenaar } 31518a7d6542SBram Moolenaar else 31528a7d6542SBram Moolenaar #endif 31538a7d6542SBram Moolenaar { 31548a7d6542SBram Moolenaar n2 = tv_get_number_chk(tv2, &error); 31558a7d6542SBram Moolenaar if (error) 3156d032f34aSBram Moolenaar goto on_error; 31578a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 31588a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT) 31598a7d6542SBram Moolenaar f2 = n2; 31608a7d6542SBram Moolenaar #endif 31618a7d6542SBram Moolenaar } 31628a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 31638a7d6542SBram Moolenaar // if there is a float on either side the result is a float 31648a7d6542SBram Moolenaar if (tv1->v_type == VAR_FLOAT || tv2->v_type == VAR_FLOAT) 31658a7d6542SBram Moolenaar { 31668a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 31678a7d6542SBram Moolenaar { 31688a7d6542SBram Moolenaar case EXPR_MULT: f1 = f1 * f2; break; 31698a7d6542SBram Moolenaar case EXPR_DIV: f1 = f1 / f2; break; 31708a7d6542SBram Moolenaar case EXPR_SUB: f1 = f1 - f2; break; 31718a7d6542SBram Moolenaar case EXPR_ADD: f1 = f1 + f2; break; 31727517ffdbSBram Moolenaar default: SOURCING_LNUM = iptr->isn_lnum; 31737517ffdbSBram Moolenaar emsg(_(e_modulus)); 3174f0b9f43cSBram Moolenaar goto on_error; 31758a7d6542SBram Moolenaar } 31768a7d6542SBram Moolenaar clear_tv(tv1); 31778a7d6542SBram Moolenaar clear_tv(tv2); 31788a7d6542SBram Moolenaar tv1->v_type = VAR_FLOAT; 31798a7d6542SBram Moolenaar tv1->vval.v_float = f1; 31808a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 31818a7d6542SBram Moolenaar } 31828a7d6542SBram Moolenaar else 31838a7d6542SBram Moolenaar #endif 31848a7d6542SBram Moolenaar { 3185b1f28570SBram Moolenaar int failed = FALSE; 3186b1f28570SBram Moolenaar 31878a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 31888a7d6542SBram Moolenaar { 31898a7d6542SBram Moolenaar case EXPR_MULT: n1 = n1 * n2; break; 3190b1f28570SBram Moolenaar case EXPR_DIV: n1 = num_divide(n1, n2, &failed); 3191b1f28570SBram Moolenaar if (failed) 319299880f96SBram Moolenaar goto on_error; 319399880f96SBram Moolenaar break; 31948a7d6542SBram Moolenaar case EXPR_SUB: n1 = n1 - n2; break; 31958a7d6542SBram Moolenaar case EXPR_ADD: n1 = n1 + n2; break; 3196b1f28570SBram Moolenaar default: n1 = num_modulus(n1, n2, &failed); 3197b1f28570SBram Moolenaar if (failed) 319899880f96SBram Moolenaar goto on_error; 319999880f96SBram Moolenaar break; 32008a7d6542SBram Moolenaar } 32018a7d6542SBram Moolenaar clear_tv(tv1); 32028a7d6542SBram Moolenaar clear_tv(tv2); 32038a7d6542SBram Moolenaar tv1->v_type = VAR_NUMBER; 32048a7d6542SBram Moolenaar tv1->vval.v_number = n1; 32058a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 32068a7d6542SBram Moolenaar } 32078a7d6542SBram Moolenaar } 32088a7d6542SBram Moolenaar break; 32098a7d6542SBram Moolenaar 32108a7d6542SBram Moolenaar case ISN_CONCAT: 32118a7d6542SBram Moolenaar { 32128a7d6542SBram Moolenaar char_u *str1 = STACK_TV_BOT(-2)->vval.v_string; 32138a7d6542SBram Moolenaar char_u *str2 = STACK_TV_BOT(-1)->vval.v_string; 32148a7d6542SBram Moolenaar char_u *res; 32158a7d6542SBram Moolenaar 32168a7d6542SBram Moolenaar res = concat_str(str1, str2); 32178a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(-2)); 32188a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(-1)); 32198a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 32208a7d6542SBram Moolenaar STACK_TV_BOT(-1)->vval.v_string = res; 32218a7d6542SBram Moolenaar } 32228a7d6542SBram Moolenaar break; 32238a7d6542SBram Moolenaar 3224bf9d8c37SBram Moolenaar case ISN_STRINDEX: 322511107babSBram Moolenaar case ISN_STRSLICE: 3226bf9d8c37SBram Moolenaar { 322711107babSBram Moolenaar int is_slice = iptr->isn_type == ISN_STRSLICE; 322811107babSBram Moolenaar varnumber_T n1 = 0, n2; 3229bf9d8c37SBram Moolenaar char_u *res; 3230bf9d8c37SBram Moolenaar 3231bf9d8c37SBram Moolenaar // string index: string is at stack-2, index at stack-1 323211107babSBram Moolenaar // string slice: string is at stack-3, first index at 323311107babSBram Moolenaar // stack-2, second index at stack-1 323411107babSBram Moolenaar if (is_slice) 323511107babSBram Moolenaar { 323611107babSBram Moolenaar tv = STACK_TV_BOT(-2); 323711107babSBram Moolenaar n1 = tv->vval.v_number; 323811107babSBram Moolenaar } 323911107babSBram Moolenaar 3240bf9d8c37SBram Moolenaar tv = STACK_TV_BOT(-1); 324111107babSBram Moolenaar n2 = tv->vval.v_number; 3242bf9d8c37SBram Moolenaar 324311107babSBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 3244bf9d8c37SBram Moolenaar tv = STACK_TV_BOT(-1); 324511107babSBram Moolenaar if (is_slice) 324611107babSBram Moolenaar // Slice: Select the characters from the string 32476601b629SBram Moolenaar res = string_slice(tv->vval.v_string, n1, n2, FALSE); 324811107babSBram Moolenaar else 324911107babSBram Moolenaar // Index: The resulting variable is a string of a 325011107babSBram Moolenaar // single character. If the index is too big or 325111107babSBram Moolenaar // negative the result is empty. 325211107babSBram Moolenaar res = char_from_string(tv->vval.v_string, n2); 3253bf9d8c37SBram Moolenaar vim_free(tv->vval.v_string); 3254bf9d8c37SBram Moolenaar tv->vval.v_string = res; 3255bf9d8c37SBram Moolenaar } 3256bf9d8c37SBram Moolenaar break; 3257bf9d8c37SBram Moolenaar 3258bf9d8c37SBram Moolenaar case ISN_LISTINDEX: 3259ed591877SBram Moolenaar case ISN_LISTSLICE: 32608a7d6542SBram Moolenaar { 3261ed591877SBram Moolenaar int is_slice = iptr->isn_type == ISN_LISTSLICE; 32628a7d6542SBram Moolenaar list_T *list; 3263ed591877SBram Moolenaar varnumber_T n1, n2; 32648a7d6542SBram Moolenaar 32658a7d6542SBram Moolenaar // list index: list is at stack-2, index at stack-1 3266ed591877SBram Moolenaar // list slice: list is at stack-3, indexes at stack-2 and 3267ed591877SBram Moolenaar // stack-1 3268ed591877SBram Moolenaar tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); 32698a7d6542SBram Moolenaar list = tv->vval.v_list; 32708a7d6542SBram Moolenaar 32718a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 3272ed591877SBram Moolenaar n1 = n2 = tv->vval.v_number; 32738a7d6542SBram Moolenaar clear_tv(tv); 3274ed591877SBram Moolenaar 3275ed591877SBram Moolenaar if (is_slice) 3276ed591877SBram Moolenaar { 3277ed591877SBram Moolenaar tv = STACK_TV_BOT(-2); 3278ed591877SBram Moolenaar n1 = tv->vval.v_number; 3279ed591877SBram Moolenaar clear_tv(tv); 3280ed591877SBram Moolenaar } 3281ed591877SBram Moolenaar 3282ed591877SBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 3283435d8978SBram Moolenaar tv = STACK_TV_BOT(-1); 32841d634542SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 32856601b629SBram Moolenaar if (list_slice_or_index(list, is_slice, n1, n2, FALSE, 32866601b629SBram Moolenaar tv, TRUE) == FAIL) 3287ed591877SBram Moolenaar goto on_error; 32888a7d6542SBram Moolenaar } 32898a7d6542SBram Moolenaar break; 32908a7d6542SBram Moolenaar 3291cc673e74SBram Moolenaar case ISN_ANYINDEX: 3292cc673e74SBram Moolenaar case ISN_ANYSLICE: 3293cc673e74SBram Moolenaar { 3294cc673e74SBram Moolenaar int is_slice = iptr->isn_type == ISN_ANYSLICE; 3295cc673e74SBram Moolenaar typval_T *var1, *var2; 3296cc673e74SBram Moolenaar int res; 3297cc673e74SBram Moolenaar 3298cc673e74SBram Moolenaar // index: composite is at stack-2, index at stack-1 3299cc673e74SBram Moolenaar // slice: composite is at stack-3, indexes at stack-2 and 3300cc673e74SBram Moolenaar // stack-1 3301cc673e74SBram Moolenaar tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); 33023affe7a6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3303cc673e74SBram Moolenaar if (check_can_index(tv, TRUE, TRUE) == FAIL) 3304cc673e74SBram Moolenaar goto on_error; 3305cc673e74SBram Moolenaar var1 = is_slice ? STACK_TV_BOT(-2) : STACK_TV_BOT(-1); 3306cc673e74SBram Moolenaar var2 = is_slice ? STACK_TV_BOT(-1) : NULL; 33076601b629SBram Moolenaar res = eval_index_inner(tv, is_slice, var1, var2, 33086601b629SBram Moolenaar FALSE, NULL, -1, TRUE); 3309cc673e74SBram Moolenaar clear_tv(var1); 3310cc673e74SBram Moolenaar if (is_slice) 3311cc673e74SBram Moolenaar clear_tv(var2); 3312cc673e74SBram Moolenaar ectx.ec_stack.ga_len -= is_slice ? 2 : 1; 3313cc673e74SBram Moolenaar if (res == FAIL) 3314cc673e74SBram Moolenaar goto on_error; 3315cc673e74SBram Moolenaar } 3316cc673e74SBram Moolenaar break; 3317cc673e74SBram Moolenaar 33189af78769SBram Moolenaar case ISN_SLICE: 33199af78769SBram Moolenaar { 33209af78769SBram Moolenaar list_T *list; 33219af78769SBram Moolenaar int count = iptr->isn_arg.number; 33229af78769SBram Moolenaar 3323c5b1c20bSBram Moolenaar // type will have been checked to be a list 33249af78769SBram Moolenaar tv = STACK_TV_BOT(-1); 33259af78769SBram Moolenaar list = tv->vval.v_list; 33269af78769SBram Moolenaar 33279af78769SBram Moolenaar // no error for short list, expect it to be checked earlier 33289af78769SBram Moolenaar if (list != NULL && list->lv_len >= count) 33299af78769SBram Moolenaar { 33309af78769SBram Moolenaar list_T *newlist = list_slice(list, 33319af78769SBram Moolenaar count, list->lv_len - 1); 33329af78769SBram Moolenaar 33339af78769SBram Moolenaar if (newlist != NULL) 33349af78769SBram Moolenaar { 33359af78769SBram Moolenaar list_unref(list); 33369af78769SBram Moolenaar tv->vval.v_list = newlist; 33379af78769SBram Moolenaar ++newlist->lv_refcount; 33389af78769SBram Moolenaar } 33399af78769SBram Moolenaar } 33409af78769SBram Moolenaar } 33419af78769SBram Moolenaar break; 33429af78769SBram Moolenaar 334347a519a9SBram Moolenaar case ISN_GETITEM: 334447a519a9SBram Moolenaar { 334547a519a9SBram Moolenaar listitem_T *li; 334647a519a9SBram Moolenaar int index = iptr->isn_arg.number; 334747a519a9SBram Moolenaar 3348c785b9a7SBram Moolenaar // Get list item: list is at stack-1, push item. 3349c785b9a7SBram Moolenaar // List type and length is checked for when compiling. 335047a519a9SBram Moolenaar tv = STACK_TV_BOT(-1); 3351c785b9a7SBram Moolenaar li = list_find(tv->vval.v_list, index); 335247a519a9SBram Moolenaar 335347a519a9SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 335447a519a9SBram Moolenaar goto failed; 335547a519a9SBram Moolenaar ++ectx.ec_stack.ga_len; 335647a519a9SBram Moolenaar copy_tv(&li->li_tv, STACK_TV_BOT(-1)); 3357f785aa13SBram Moolenaar 3358f785aa13SBram Moolenaar // Useful when used in unpack assignment. Reset at 3359f785aa13SBram Moolenaar // ISN_DROP. 3360f785aa13SBram Moolenaar where.wt_index = index + 1; 3361f785aa13SBram Moolenaar where.wt_variable = TRUE; 336247a519a9SBram Moolenaar } 336347a519a9SBram Moolenaar break; 336447a519a9SBram Moolenaar 33658a7d6542SBram Moolenaar case ISN_MEMBER: 33668a7d6542SBram Moolenaar { 33678a7d6542SBram Moolenaar dict_T *dict; 33681cc2a94fSBram Moolenaar char_u *key; 33691cc2a94fSBram Moolenaar dictitem_T *di; 337050788ef3SBram Moolenaar typval_T temp_tv; 33711cc2a94fSBram Moolenaar 33721cc2a94fSBram Moolenaar // dict member: dict is at stack-2, key at stack-1 33731cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-2); 33744dac32caSBram Moolenaar // no need to check for VAR_DICT, CHECKTYPE will check. 33751cc2a94fSBram Moolenaar dict = tv->vval.v_dict; 33761cc2a94fSBram Moolenaar 33771cc2a94fSBram Moolenaar tv = STACK_TV_BOT(-1); 33784dac32caSBram Moolenaar // no need to check for VAR_STRING, 2STRING will check. 33791cc2a94fSBram Moolenaar key = tv->vval.v_string; 3380086fc9a5SBram Moolenaar if (key == NULL) 3381086fc9a5SBram Moolenaar key = (char_u *)""; 33824dac32caSBram Moolenaar 33831cc2a94fSBram Moolenaar if ((di = dict_find(dict, key, -1)) == NULL) 33841cc2a94fSBram Moolenaar { 33857517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 33861cc2a94fSBram Moolenaar semsg(_(e_dictkey), key); 33874029cabbSBram Moolenaar 33884029cabbSBram Moolenaar // If :silent! is used we will continue, make sure the 33894029cabbSBram Moolenaar // stack contents makes sense. 33904029cabbSBram Moolenaar clear_tv(tv); 33914029cabbSBram Moolenaar --ectx.ec_stack.ga_len; 33924029cabbSBram Moolenaar tv = STACK_TV_BOT(-1); 33934029cabbSBram Moolenaar clear_tv(tv); 33944029cabbSBram Moolenaar tv->v_type = VAR_NUMBER; 33954029cabbSBram Moolenaar tv->vval.v_number = 0; 3396af0df47aSBram Moolenaar goto on_fatal_error; 33971cc2a94fSBram Moolenaar } 33981cc2a94fSBram Moolenaar clear_tv(tv); 339950788ef3SBram Moolenaar --ectx.ec_stack.ga_len; 3400af0df47aSBram Moolenaar // Clear the dict only after getting the item, to avoid 3401af0df47aSBram Moolenaar // that it makes the item invalid. 340250788ef3SBram Moolenaar tv = STACK_TV_BOT(-1); 340350788ef3SBram Moolenaar temp_tv = *tv; 340450788ef3SBram Moolenaar copy_tv(&di->di_tv, tv); 340550788ef3SBram Moolenaar clear_tv(&temp_tv); 34061cc2a94fSBram Moolenaar } 34071cc2a94fSBram Moolenaar break; 34081cc2a94fSBram Moolenaar 34091cc2a94fSBram Moolenaar // dict member with string key 34101cc2a94fSBram Moolenaar case ISN_STRINGMEMBER: 34111cc2a94fSBram Moolenaar { 34121cc2a94fSBram Moolenaar dict_T *dict; 34138a7d6542SBram Moolenaar dictitem_T *di; 3414fb9d5c51SBram Moolenaar typval_T temp_tv; 34158a7d6542SBram Moolenaar 34168a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 34178a7d6542SBram Moolenaar if (tv->v_type != VAR_DICT || tv->vval.v_dict == NULL) 34188a7d6542SBram Moolenaar { 34197517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 34208a7d6542SBram Moolenaar emsg(_(e_dictreq)); 3421d032f34aSBram Moolenaar goto on_error; 34228a7d6542SBram Moolenaar } 34238a7d6542SBram Moolenaar dict = tv->vval.v_dict; 34248a7d6542SBram Moolenaar 34258a7d6542SBram Moolenaar if ((di = dict_find(dict, iptr->isn_arg.string, -1)) 34268a7d6542SBram Moolenaar == NULL) 34278a7d6542SBram Moolenaar { 34287517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 34298a7d6542SBram Moolenaar semsg(_(e_dictkey), iptr->isn_arg.string); 3430d032f34aSBram Moolenaar goto on_error; 34318a7d6542SBram Moolenaar } 3432fb9d5c51SBram Moolenaar // Clear the dict after getting the item, to avoid that it 3433fb9d5c51SBram Moolenaar // make the item invalid. 3434fb9d5c51SBram Moolenaar temp_tv = *tv; 34358a7d6542SBram Moolenaar copy_tv(&di->di_tv, tv); 3436fb9d5c51SBram Moolenaar clear_tv(&temp_tv); 34378a7d6542SBram Moolenaar } 34388a7d6542SBram Moolenaar break; 34398a7d6542SBram Moolenaar 34408a7d6542SBram Moolenaar case ISN_NEGATENR: 34418a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 3442c58164c5SBram Moolenaar if (tv->v_type != VAR_NUMBER 3443c58164c5SBram Moolenaar #ifdef FEAT_FLOAT 3444c58164c5SBram Moolenaar && tv->v_type != VAR_FLOAT 3445c58164c5SBram Moolenaar #endif 3446c58164c5SBram Moolenaar ) 3447c58164c5SBram Moolenaar { 34487517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3449c58164c5SBram Moolenaar emsg(_(e_number_exp)); 3450f0b9f43cSBram Moolenaar goto on_error; 3451c58164c5SBram Moolenaar } 3452c58164c5SBram Moolenaar #ifdef FEAT_FLOAT 3453c58164c5SBram Moolenaar if (tv->v_type == VAR_FLOAT) 3454c58164c5SBram Moolenaar tv->vval.v_float = -tv->vval.v_float; 3455c58164c5SBram Moolenaar else 3456c58164c5SBram Moolenaar #endif 34578a7d6542SBram Moolenaar tv->vval.v_number = -tv->vval.v_number; 34588a7d6542SBram Moolenaar break; 34598a7d6542SBram Moolenaar 34608a7d6542SBram Moolenaar case ISN_CHECKNR: 34618a7d6542SBram Moolenaar { 34628a7d6542SBram Moolenaar int error = FALSE; 34638a7d6542SBram Moolenaar 34648a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 34653affe7a6SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 34668a7d6542SBram Moolenaar if (check_not_string(tv) == FAIL) 3467f0b9f43cSBram Moolenaar goto on_error; 34688a7d6542SBram Moolenaar (void)tv_get_number_chk(tv, &error); 34698a7d6542SBram Moolenaar if (error) 3470f0b9f43cSBram Moolenaar goto on_error; 34718a7d6542SBram Moolenaar } 34728a7d6542SBram Moolenaar break; 34738a7d6542SBram Moolenaar 34748a7d6542SBram Moolenaar case ISN_CHECKTYPE: 34758a7d6542SBram Moolenaar { 34768a7d6542SBram Moolenaar checktype_T *ct = &iptr->isn_arg.type; 34778a7d6542SBram Moolenaar 3478b3005ce1SBram Moolenaar tv = STACK_TV_BOT((int)ct->ct_off); 34795e654230SBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3480f785aa13SBram Moolenaar if (!where.wt_variable) 3481f785aa13SBram Moolenaar where.wt_index = ct->ct_arg_idx; 3482f785aa13SBram Moolenaar if (check_typval_type(ct->ct_type, tv, where) == FAIL) 34835e654230SBram Moolenaar goto on_error; 3484f785aa13SBram Moolenaar if (!where.wt_variable) 3485f785aa13SBram Moolenaar where.wt_index = 0; 34865e654230SBram Moolenaar 34875e654230SBram Moolenaar // number 0 is FALSE, number 1 is TRUE 34885e654230SBram Moolenaar if (tv->v_type == VAR_NUMBER 34895e654230SBram Moolenaar && ct->ct_type->tt_type == VAR_BOOL 3490dadaddd5SBram Moolenaar && (tv->vval.v_number == 0 3491dadaddd5SBram Moolenaar || tv->vval.v_number == 1)) 3492dadaddd5SBram Moolenaar { 3493dadaddd5SBram Moolenaar tv->v_type = VAR_BOOL; 3494dadaddd5SBram Moolenaar tv->vval.v_number = tv->vval.v_number 3495dadaddd5SBram Moolenaar ? VVAL_TRUE : VVAL_FALSE; 3496dadaddd5SBram Moolenaar } 3497dadaddd5SBram Moolenaar } 34988a7d6542SBram Moolenaar break; 34998a7d6542SBram Moolenaar 35009af78769SBram Moolenaar case ISN_CHECKLEN: 35019af78769SBram Moolenaar { 35029af78769SBram Moolenaar int min_len = iptr->isn_arg.checklen.cl_min_len; 35039af78769SBram Moolenaar list_T *list = NULL; 35049af78769SBram Moolenaar 35059af78769SBram Moolenaar tv = STACK_TV_BOT(-1); 35069af78769SBram Moolenaar if (tv->v_type == VAR_LIST) 35079af78769SBram Moolenaar list = tv->vval.v_list; 35089af78769SBram Moolenaar if (list == NULL || list->lv_len < min_len 35099af78769SBram Moolenaar || (list->lv_len > min_len 35109af78769SBram Moolenaar && !iptr->isn_arg.checklen.cl_more_OK)) 35119af78769SBram Moolenaar { 35127517ffdbSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3513451c2e35SBram Moolenaar semsg(_(e_expected_nr_items_but_got_nr), 35149af78769SBram Moolenaar min_len, list == NULL ? 0 : list->lv_len); 3515f0b9f43cSBram Moolenaar goto on_error; 35169af78769SBram Moolenaar } 35179af78769SBram Moolenaar } 35189af78769SBram Moolenaar break; 35199af78769SBram Moolenaar 3520aa210a3aSBram Moolenaar case ISN_SETTYPE: 3521aa210a3aSBram Moolenaar { 3522aa210a3aSBram Moolenaar checktype_T *ct = &iptr->isn_arg.type; 3523aa210a3aSBram Moolenaar 3524aa210a3aSBram Moolenaar tv = STACK_TV_BOT(-1); 3525aa210a3aSBram Moolenaar if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) 3526aa210a3aSBram Moolenaar { 3527aa210a3aSBram Moolenaar free_type(tv->vval.v_dict->dv_type); 3528aa210a3aSBram Moolenaar tv->vval.v_dict->dv_type = alloc_type(ct->ct_type); 3529aa210a3aSBram Moolenaar } 3530aa210a3aSBram Moolenaar else if (tv->v_type == VAR_LIST && tv->vval.v_list != NULL) 3531aa210a3aSBram Moolenaar { 3532aa210a3aSBram Moolenaar free_type(tv->vval.v_list->lv_type); 3533aa210a3aSBram Moolenaar tv->vval.v_list->lv_type = alloc_type(ct->ct_type); 3534aa210a3aSBram Moolenaar } 3535aa210a3aSBram Moolenaar } 3536aa210a3aSBram Moolenaar break; 3537aa210a3aSBram Moolenaar 35388a7d6542SBram Moolenaar case ISN_2BOOL: 35392bb2658bSBram Moolenaar case ISN_COND2BOOL: 35408a7d6542SBram Moolenaar { 35418a7d6542SBram Moolenaar int n; 35422bb2658bSBram Moolenaar int error = FALSE; 35438a7d6542SBram Moolenaar 35448a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 35452bb2658bSBram Moolenaar if (iptr->isn_type == ISN_2BOOL) 35462bb2658bSBram Moolenaar { 35478a7d6542SBram Moolenaar n = tv2bool(tv); 35488a7d6542SBram Moolenaar if (iptr->isn_arg.number) // invert 35498a7d6542SBram Moolenaar n = !n; 35502bb2658bSBram Moolenaar } 35512bb2658bSBram Moolenaar else 35522bb2658bSBram Moolenaar { 35532bb2658bSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 35542bb2658bSBram Moolenaar n = tv_get_bool_chk(tv, &error); 35552bb2658bSBram Moolenaar if (error) 35562bb2658bSBram Moolenaar goto on_error; 35572bb2658bSBram Moolenaar } 35588a7d6542SBram Moolenaar clear_tv(tv); 35598a7d6542SBram Moolenaar tv->v_type = VAR_BOOL; 35608a7d6542SBram Moolenaar tv->vval.v_number = n ? VVAL_TRUE : VVAL_FALSE; 35618a7d6542SBram Moolenaar } 35628a7d6542SBram Moolenaar break; 35638a7d6542SBram Moolenaar 35648a7d6542SBram Moolenaar case ISN_2STRING: 3565418f1df5SBram Moolenaar case ISN_2STRING_ANY: 35660acbf5aeSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 35674f5e3977SBram Moolenaar if (do_2string(STACK_TV_BOT(iptr->isn_arg.number), 35684f5e3977SBram Moolenaar iptr->isn_type == ISN_2STRING_ANY) == FAIL) 3569418f1df5SBram Moolenaar goto on_error; 35708a7d6542SBram Moolenaar break; 35718a7d6542SBram Moolenaar 357208597875SBram Moolenaar case ISN_RANGE: 357308597875SBram Moolenaar { 357408597875SBram Moolenaar exarg_T ea; 357508597875SBram Moolenaar char *errormsg; 357608597875SBram Moolenaar 3577ece0b87cSBram Moolenaar ea.line2 = 0; 3578d1510ee9SBram Moolenaar ea.addr_count = 0; 357908597875SBram Moolenaar ea.addr_type = ADDR_LINES; 358008597875SBram Moolenaar ea.cmd = iptr->isn_arg.string; 3581ece0b87cSBram Moolenaar ea.skip = FALSE; 358208597875SBram Moolenaar if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL) 3583ece0b87cSBram Moolenaar goto on_error; 3584a28639e7SBram Moolenaar 3585a28639e7SBram Moolenaar if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 3586a28639e7SBram Moolenaar goto failed; 3587a28639e7SBram Moolenaar ++ectx.ec_stack.ga_len; 3588a28639e7SBram Moolenaar tv = STACK_TV_BOT(-1); 3589a28639e7SBram Moolenaar tv->v_type = VAR_NUMBER; 3590a28639e7SBram Moolenaar tv->v_lock = 0; 359108597875SBram Moolenaar if (ea.addr_count == 0) 359208597875SBram Moolenaar tv->vval.v_number = curwin->w_cursor.lnum; 359308597875SBram Moolenaar else 359408597875SBram Moolenaar tv->vval.v_number = ea.line2; 359508597875SBram Moolenaar } 359608597875SBram Moolenaar break; 359708597875SBram Moolenaar 3598c3516f7eSBram Moolenaar case ISN_PUT: 3599c3516f7eSBram Moolenaar { 3600c3516f7eSBram Moolenaar int regname = iptr->isn_arg.put.put_regname; 3601c3516f7eSBram Moolenaar linenr_T lnum = iptr->isn_arg.put.put_lnum; 3602c3516f7eSBram Moolenaar char_u *expr = NULL; 3603c3516f7eSBram Moolenaar int dir = FORWARD; 3604c3516f7eSBram Moolenaar 360508597875SBram Moolenaar if (lnum < -2) 360608597875SBram Moolenaar { 360708597875SBram Moolenaar // line number was put on the stack by ISN_RANGE 360808597875SBram Moolenaar tv = STACK_TV_BOT(-1); 360908597875SBram Moolenaar curwin->w_cursor.lnum = tv->vval.v_number; 361008597875SBram Moolenaar if (lnum == LNUM_VARIABLE_RANGE_ABOVE) 361108597875SBram Moolenaar dir = BACKWARD; 361208597875SBram Moolenaar --ectx.ec_stack.ga_len; 361308597875SBram Moolenaar } 361408597875SBram Moolenaar else if (lnum == -2) 3615c3516f7eSBram Moolenaar // :put! above cursor 3616c3516f7eSBram Moolenaar dir = BACKWARD; 3617c3516f7eSBram Moolenaar else if (lnum >= 0) 3618c3516f7eSBram Moolenaar curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum; 3619a28639e7SBram Moolenaar 3620a28639e7SBram Moolenaar if (regname == '=') 3621a28639e7SBram Moolenaar { 3622a28639e7SBram Moolenaar tv = STACK_TV_BOT(-1); 3623a28639e7SBram Moolenaar if (tv->v_type == VAR_STRING) 3624a28639e7SBram Moolenaar expr = tv->vval.v_string; 3625a28639e7SBram Moolenaar else 3626a28639e7SBram Moolenaar { 3627a28639e7SBram Moolenaar expr = typval2string(tv, TRUE); // allocates value 3628a28639e7SBram Moolenaar clear_tv(tv); 3629a28639e7SBram Moolenaar } 3630a28639e7SBram Moolenaar --ectx.ec_stack.ga_len; 3631a28639e7SBram Moolenaar } 3632c3516f7eSBram Moolenaar check_cursor(); 3633c3516f7eSBram Moolenaar do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE); 3634c3516f7eSBram Moolenaar vim_free(expr); 3635c3516f7eSBram Moolenaar } 3636c3516f7eSBram Moolenaar break; 3637c3516f7eSBram Moolenaar 363802194d2bSBram Moolenaar case ISN_CMDMOD: 363902194d2bSBram Moolenaar save_cmdmod = cmdmod; 364002194d2bSBram Moolenaar restore_cmdmod = TRUE; 3641f904133eSBram Moolenaar restore_cmdmod_stacklen = ectx.ec_stack.ga_len; 364202194d2bSBram Moolenaar cmdmod = *iptr->isn_arg.cmdmod.cf_cmdmod; 364302194d2bSBram Moolenaar apply_cmdmod(&cmdmod); 3644f4c6e1e7SBram Moolenaar break; 3645f4c6e1e7SBram Moolenaar 364602194d2bSBram Moolenaar case ISN_CMDMOD_REV: 364702194d2bSBram Moolenaar // filter regprog is owned by the instruction, don't free it 364802194d2bSBram Moolenaar cmdmod.cmod_filter_regmatch.regprog = NULL; 364902194d2bSBram Moolenaar undo_cmdmod(&cmdmod); 365002194d2bSBram Moolenaar cmdmod = save_cmdmod; 365102194d2bSBram Moolenaar restore_cmdmod = FALSE; 3652f4c6e1e7SBram Moolenaar break; 3653f4c6e1e7SBram Moolenaar 3654792f786aSBram Moolenaar case ISN_UNPACK: 3655792f786aSBram Moolenaar { 3656792f786aSBram Moolenaar int count = iptr->isn_arg.unpack.unp_count; 3657792f786aSBram Moolenaar int semicolon = iptr->isn_arg.unpack.unp_semicolon; 3658792f786aSBram Moolenaar list_T *l; 3659792f786aSBram Moolenaar listitem_T *li; 3660792f786aSBram Moolenaar int i; 3661792f786aSBram Moolenaar 3662792f786aSBram Moolenaar // Check there is a valid list to unpack. 3663792f786aSBram Moolenaar tv = STACK_TV_BOT(-1); 3664792f786aSBram Moolenaar if (tv->v_type != VAR_LIST) 3665792f786aSBram Moolenaar { 3666792f786aSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3667792f786aSBram Moolenaar emsg(_(e_for_argument_must_be_sequence_of_lists)); 3668792f786aSBram Moolenaar goto on_error; 3669792f786aSBram Moolenaar } 3670792f786aSBram Moolenaar l = tv->vval.v_list; 3671792f786aSBram Moolenaar if (l == NULL 3672792f786aSBram Moolenaar || l->lv_len < (semicolon ? count - 1 : count)) 3673792f786aSBram Moolenaar { 3674792f786aSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3675792f786aSBram Moolenaar emsg(_(e_list_value_does_not_have_enough_items)); 3676792f786aSBram Moolenaar goto on_error; 3677792f786aSBram Moolenaar } 3678792f786aSBram Moolenaar else if (!semicolon && l->lv_len > count) 3679792f786aSBram Moolenaar { 3680792f786aSBram Moolenaar SOURCING_LNUM = iptr->isn_lnum; 3681792f786aSBram Moolenaar emsg(_(e_list_value_has_more_items_than_targets)); 3682792f786aSBram Moolenaar goto on_error; 3683792f786aSBram Moolenaar } 3684792f786aSBram Moolenaar 3685792f786aSBram Moolenaar CHECK_LIST_MATERIALIZE(l); 3686792f786aSBram Moolenaar if (GA_GROW(&ectx.ec_stack, count - 1) == FAIL) 3687792f786aSBram Moolenaar goto failed; 3688792f786aSBram Moolenaar ectx.ec_stack.ga_len += count - 1; 3689792f786aSBram Moolenaar 3690792f786aSBram Moolenaar // Variable after semicolon gets a list with the remaining 3691792f786aSBram Moolenaar // items. 3692792f786aSBram Moolenaar if (semicolon) 3693792f786aSBram Moolenaar { 3694792f786aSBram Moolenaar list_T *rem_list = 3695792f786aSBram Moolenaar list_alloc_with_items(l->lv_len - count + 1); 3696792f786aSBram Moolenaar 3697792f786aSBram Moolenaar if (rem_list == NULL) 3698792f786aSBram Moolenaar goto failed; 3699792f786aSBram Moolenaar tv = STACK_TV_BOT(-count); 3700792f786aSBram Moolenaar tv->vval.v_list = rem_list; 3701792f786aSBram Moolenaar ++rem_list->lv_refcount; 3702792f786aSBram Moolenaar tv->v_lock = 0; 3703792f786aSBram Moolenaar li = l->lv_first; 3704792f786aSBram Moolenaar for (i = 0; i < count - 1; ++i) 3705792f786aSBram Moolenaar li = li->li_next; 3706792f786aSBram Moolenaar for (i = 0; li != NULL; ++i) 3707792f786aSBram Moolenaar { 3708792f786aSBram Moolenaar list_set_item(rem_list, i, &li->li_tv); 3709792f786aSBram Moolenaar li = li->li_next; 3710792f786aSBram Moolenaar } 3711792f786aSBram Moolenaar --count; 3712792f786aSBram Moolenaar } 3713792f786aSBram Moolenaar 3714792f786aSBram Moolenaar // Produce the values in reverse order, first item last. 3715792f786aSBram Moolenaar li = l->lv_first; 3716792f786aSBram Moolenaar for (i = 0; i < count; ++i) 3717792f786aSBram Moolenaar { 3718792f786aSBram Moolenaar tv = STACK_TV_BOT(-i - 1); 3719792f786aSBram Moolenaar copy_tv(&li->li_tv, tv); 3720792f786aSBram Moolenaar li = li->li_next; 3721792f786aSBram Moolenaar } 3722792f786aSBram Moolenaar 3723792f786aSBram Moolenaar list_unref(l); 3724792f786aSBram Moolenaar } 3725792f786aSBram Moolenaar break; 3726792f786aSBram Moolenaar 3727b2049903SBram Moolenaar case ISN_PROF_START: 3728b2049903SBram Moolenaar case ISN_PROF_END: 3729b2049903SBram Moolenaar { 3730f002a41dSBram Moolenaar #ifdef FEAT_PROFILE 3731b2049903SBram Moolenaar funccall_T cookie; 3732b2049903SBram Moolenaar ufunc_T *cur_ufunc = 3733b2049903SBram Moolenaar (((dfunc_T *)def_functions.ga_data) 3734b2049903SBram Moolenaar + ectx.ec_dfunc_idx)->df_ufunc; 3735b2049903SBram Moolenaar 3736b2049903SBram Moolenaar cookie.func = cur_ufunc; 3737b2049903SBram Moolenaar if (iptr->isn_type == ISN_PROF_START) 3738b2049903SBram Moolenaar { 3739b2049903SBram Moolenaar func_line_start(&cookie, iptr->isn_lnum); 3740b2049903SBram Moolenaar // if we get here the instruction is executed 3741b2049903SBram Moolenaar func_line_exec(&cookie); 3742b2049903SBram Moolenaar } 3743b2049903SBram Moolenaar else 3744b2049903SBram Moolenaar func_line_end(&cookie); 3745f002a41dSBram Moolenaar #endif 3746b2049903SBram Moolenaar } 3747b2049903SBram Moolenaar break; 3748b2049903SBram Moolenaar 3749389df259SBram Moolenaar case ISN_SHUFFLE: 3750389df259SBram Moolenaar { 3751389df259SBram Moolenaar typval_T tmp_tv; 3752389df259SBram Moolenaar int item = iptr->isn_arg.shuffle.shfl_item; 3753389df259SBram Moolenaar int up = iptr->isn_arg.shuffle.shfl_up; 3754389df259SBram Moolenaar 3755389df259SBram Moolenaar tmp_tv = *STACK_TV_BOT(-item); 3756389df259SBram Moolenaar for ( ; up > 0 && item > 1; --up) 3757389df259SBram Moolenaar { 3758389df259SBram Moolenaar *STACK_TV_BOT(-item) = *STACK_TV_BOT(-item + 1); 3759389df259SBram Moolenaar --item; 3760389df259SBram Moolenaar } 3761389df259SBram Moolenaar *STACK_TV_BOT(-item) = tmp_tv; 3762389df259SBram Moolenaar } 3763389df259SBram Moolenaar break; 3764389df259SBram Moolenaar 37658a7d6542SBram Moolenaar case ISN_DROP: 37668a7d6542SBram Moolenaar --ectx.ec_stack.ga_len; 37678a7d6542SBram Moolenaar clear_tv(STACK_TV_BOT(0)); 3768f785aa13SBram Moolenaar where.wt_index = 0; 3769f785aa13SBram Moolenaar where.wt_variable = FALSE; 37708a7d6542SBram Moolenaar break; 37718a7d6542SBram Moolenaar } 3772f0b9f43cSBram Moolenaar continue; 3773f0b9f43cSBram Moolenaar 3774d032f34aSBram Moolenaar func_return: 37757cbfaa51SBram Moolenaar // Restore previous function. If the frame pointer is where we started 37767cbfaa51SBram Moolenaar // then there is none and we are done. 3777d032f34aSBram Moolenaar if (ectx.ec_frame_idx == initial_frame_idx) 3778d032f34aSBram Moolenaar goto done; 37797cbfaa51SBram Moolenaar 3780d032f34aSBram Moolenaar if (func_return(&ectx) == FAIL) 3781d032f34aSBram Moolenaar // only fails when out of memory 3782d032f34aSBram Moolenaar goto failed; 3783c7db5778SBram Moolenaar continue; 3784d032f34aSBram Moolenaar 3785f0b9f43cSBram Moolenaar on_error: 3786af0df47aSBram Moolenaar // Jump here for an error that does not require aborting execution. 378756602ba1SBram Moolenaar // If "emsg_silent" is set then ignore the error, unless it was set 378856602ba1SBram Moolenaar // when calling the function. 378956602ba1SBram Moolenaar if (did_emsg_cumul + did_emsg == did_emsg_before 379056602ba1SBram Moolenaar && emsg_silent && did_emsg_def == 0) 3791f904133eSBram Moolenaar { 3792f904133eSBram Moolenaar // If a sequence of instructions causes an error while ":silent!" 3793f904133eSBram Moolenaar // was used, restore the stack length and jump ahead to restoring 3794f904133eSBram Moolenaar // the cmdmod. 3795f904133eSBram Moolenaar if (restore_cmdmod) 3796f904133eSBram Moolenaar { 3797f904133eSBram Moolenaar while (ectx.ec_stack.ga_len > restore_cmdmod_stacklen) 3798f904133eSBram Moolenaar { 3799f904133eSBram Moolenaar --ectx.ec_stack.ga_len; 3800f904133eSBram Moolenaar clear_tv(STACK_TV_BOT(0)); 3801f904133eSBram Moolenaar } 3802f904133eSBram Moolenaar while (ectx.ec_instr[ectx.ec_iidx].isn_type != ISN_CMDMOD_REV) 3803f904133eSBram Moolenaar ++ectx.ec_iidx; 3804f904133eSBram Moolenaar } 3805cd030c4bSBram Moolenaar continue; 3806f904133eSBram Moolenaar } 3807af0df47aSBram Moolenaar on_fatal_error: 3808af0df47aSBram Moolenaar // Jump here for an error that messes up the stack. 3809171fb923SBram Moolenaar // If we are not inside a try-catch started here, abort execution. 3810171fb923SBram Moolenaar if (trylevel <= trylevel_at_start) 3811f0b9f43cSBram Moolenaar goto failed; 38128a7d6542SBram Moolenaar } 38138a7d6542SBram Moolenaar 38148a7d6542SBram Moolenaar done: 38158a7d6542SBram Moolenaar // function finished, get result from the stack. 38168a7d6542SBram Moolenaar tv = STACK_TV_BOT(-1); 38178a7d6542SBram Moolenaar *rettv = *tv; 38188a7d6542SBram Moolenaar tv->v_type = VAR_UNKNOWN; 38198a7d6542SBram Moolenaar ret = OK; 38208a7d6542SBram Moolenaar 38218a7d6542SBram Moolenaar failed: 38227eeefd4aSBram Moolenaar // When failed need to unwind the call stack. 3823bf67ea1aSBram Moolenaar while (ectx.ec_frame_idx != initial_frame_idx) 38247eeefd4aSBram Moolenaar func_return(&ectx); 3825bf67ea1aSBram Moolenaar 3826c70bdab0SBram Moolenaar // Deal with any remaining closures, they may be in use somewhere. 3827c70bdab0SBram Moolenaar if (ectx.ec_funcrefs.ga_len > 0) 3828f112f30aSBram Moolenaar { 3829c70bdab0SBram Moolenaar handle_closure_in_use(&ectx, FALSE); 3830f112f30aSBram Moolenaar ga_clear(&ectx.ec_funcrefs); // TODO: should not be needed? 3831f112f30aSBram Moolenaar } 3832c70bdab0SBram Moolenaar 3833ee8580e5SBram Moolenaar estack_pop(); 3834ee8580e5SBram Moolenaar current_sctx = save_current_sctx; 3835ee8580e5SBram Moolenaar 3836352134bbSBram Moolenaar if (*msg_list != NULL && saved_msg_list != NULL) 3837352134bbSBram Moolenaar { 3838352134bbSBram Moolenaar msglist_T **plist = saved_msg_list; 3839352134bbSBram Moolenaar 3840352134bbSBram Moolenaar // Append entries from the current msg_list (uncaught exceptions) to 3841352134bbSBram Moolenaar // the saved msg_list. 3842352134bbSBram Moolenaar while (*plist != NULL) 3843352134bbSBram Moolenaar plist = &(*plist)->next; 3844352134bbSBram Moolenaar 3845352134bbSBram Moolenaar *plist = *msg_list; 3846352134bbSBram Moolenaar } 3847352134bbSBram Moolenaar msg_list = saved_msg_list; 3848352134bbSBram Moolenaar 384902194d2bSBram Moolenaar if (restore_cmdmod) 385002194d2bSBram Moolenaar { 385102194d2bSBram Moolenaar cmdmod.cmod_filter_regmatch.regprog = NULL; 385202194d2bSBram Moolenaar undo_cmdmod(&cmdmod); 385302194d2bSBram Moolenaar cmdmod = save_cmdmod; 385402194d2bSBram Moolenaar } 385556602ba1SBram Moolenaar emsg_silent_def = save_emsg_silent_def; 385656602ba1SBram Moolenaar did_emsg_def += save_did_emsg_def; 3857f4c6e1e7SBram Moolenaar 3858ee8580e5SBram Moolenaar failed_early: 3859bf67ea1aSBram Moolenaar // Free all local variables, but not arguments. 38608a7d6542SBram Moolenaar for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx) 38618a7d6542SBram Moolenaar clear_tv(STACK_TV(idx)); 3862bf67ea1aSBram Moolenaar 38638a7d6542SBram Moolenaar vim_free(ectx.ec_stack.ga_data); 386420431c9dSBram Moolenaar vim_free(ectx.ec_trystack.ga_data); 3865682d0a15SBram Moolenaar 38660186e586SBram Moolenaar while (ectx.ec_outer != NULL) 38670186e586SBram Moolenaar { 38680186e586SBram Moolenaar outer_T *up = ectx.ec_outer->out_up_is_copy 38690186e586SBram Moolenaar ? NULL : ectx.ec_outer->out_up; 38700186e586SBram Moolenaar 38710186e586SBram Moolenaar vim_free(ectx.ec_outer); 38720186e586SBram Moolenaar ectx.ec_outer = up; 38730186e586SBram Moolenaar } 38740186e586SBram Moolenaar 387577e5dcc3SBram Moolenaar // Not sure if this is necessary. 387677e5dcc3SBram Moolenaar suppress_errthrow = save_suppress_errthrow; 387777e5dcc3SBram Moolenaar 3878eeece9e4SBram Moolenaar if (ret != OK && did_emsg_cumul + did_emsg == did_emsg_before) 3879451c2e35SBram Moolenaar semsg(_(e_unknown_error_while_executing_str), 3880682d0a15SBram Moolenaar printable_func_name(ufunc)); 38810ba48e8cSBram Moolenaar funcdepth_restore(orig_funcdepth); 38828a7d6542SBram Moolenaar return ret; 38838a7d6542SBram Moolenaar } 38848a7d6542SBram Moolenaar 38858a7d6542SBram Moolenaar /* 38868e7d6223SBram Moolenaar * ":disassemble". 3887777770fbSBram Moolenaar * We don't really need this at runtime, but we do have tests that require it, 3888777770fbSBram Moolenaar * so always include this. 38898a7d6542SBram Moolenaar */ 38908a7d6542SBram Moolenaar void 38918a7d6542SBram Moolenaar ex_disassemble(exarg_T *eap) 38928a7d6542SBram Moolenaar { 389321456cdcSBram Moolenaar char_u *arg = eap->arg; 38940f18b6d1SBram Moolenaar char_u *fname; 38950f18b6d1SBram Moolenaar ufunc_T *ufunc; 38968a7d6542SBram Moolenaar dfunc_T *dfunc; 38978a7d6542SBram Moolenaar isn_T *instr; 3898b2049903SBram Moolenaar int instr_count; 38998a7d6542SBram Moolenaar int current; 39008a7d6542SBram Moolenaar int line_idx = 0; 39018a7d6542SBram Moolenaar int prev_current = 0; 39024c17ad94SBram Moolenaar int is_global = FALSE; 39038a7d6542SBram Moolenaar 3904bfd65589SBram Moolenaar if (STRNCMP(arg, "<lambda>", 8) == 0) 3905bfd65589SBram Moolenaar { 3906bfd65589SBram Moolenaar arg += 8; 3907bfd65589SBram Moolenaar (void)getdigits(&arg); 3908bfd65589SBram Moolenaar fname = vim_strnsave(eap->arg, arg - eap->arg); 3909bfd65589SBram Moolenaar } 3910bfd65589SBram Moolenaar else 39114c17ad94SBram Moolenaar fname = trans_function_name(&arg, &is_global, FALSE, 391232b3f820SBram Moolenaar TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL); 391321456cdcSBram Moolenaar if (fname == NULL) 391421456cdcSBram Moolenaar { 391521456cdcSBram Moolenaar semsg(_(e_invarg2), eap->arg); 391621456cdcSBram Moolenaar return; 391721456cdcSBram Moolenaar } 391821456cdcSBram Moolenaar 39194c17ad94SBram Moolenaar ufunc = find_func(fname, is_global, NULL); 3920a26b9700SBram Moolenaar if (ufunc == NULL) 3921a26b9700SBram Moolenaar { 3922a26b9700SBram Moolenaar char_u *p = untrans_function_name(fname); 3923a26b9700SBram Moolenaar 3924a26b9700SBram Moolenaar if (p != NULL) 3925a26b9700SBram Moolenaar // Try again without making it script-local. 39264c17ad94SBram Moolenaar ufunc = find_func(p, FALSE, NULL); 3927a26b9700SBram Moolenaar } 39280f18b6d1SBram Moolenaar vim_free(fname); 39298a7d6542SBram Moolenaar if (ufunc == NULL) 39308a7d6542SBram Moolenaar { 3931451c2e35SBram Moolenaar semsg(_(e_cannot_find_function_str), eap->arg); 39328a7d6542SBram Moolenaar return; 39338a7d6542SBram Moolenaar } 3934b2049903SBram Moolenaar if (func_needs_compiling(ufunc, eap->forceit) 3935b2049903SBram Moolenaar && compile_def_function(ufunc, FALSE, eap->forceit, NULL) == FAIL) 3936822ba247SBram Moolenaar return; 39370cb5bcf5SBram Moolenaar if (ufunc->uf_def_status != UF_COMPILED) 39388a7d6542SBram Moolenaar { 3939451c2e35SBram Moolenaar semsg(_(e_function_is_not_compiled_str), eap->arg); 39408a7d6542SBram Moolenaar return; 39418a7d6542SBram Moolenaar } 39428a7d6542SBram Moolenaar if (ufunc->uf_name_exp != NULL) 39438a7d6542SBram Moolenaar msg((char *)ufunc->uf_name_exp); 39448a7d6542SBram Moolenaar else 39458a7d6542SBram Moolenaar msg((char *)ufunc->uf_name); 39468a7d6542SBram Moolenaar 39478a7d6542SBram Moolenaar dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; 3948f002a41dSBram Moolenaar #ifdef FEAT_PROFILE 3949b2049903SBram Moolenaar instr = eap->forceit ? dfunc->df_instr_prof : dfunc->df_instr; 3950b2049903SBram Moolenaar instr_count = eap->forceit ? dfunc->df_instr_prof_count 3951b2049903SBram Moolenaar : dfunc->df_instr_count; 3952f002a41dSBram Moolenaar #else 3953f002a41dSBram Moolenaar instr = dfunc->df_instr; 3954f002a41dSBram Moolenaar instr_count = dfunc->df_instr_count; 3955f002a41dSBram Moolenaar #endif 3956b2049903SBram Moolenaar for (current = 0; current < instr_count; ++current) 39578a7d6542SBram Moolenaar { 39588a7d6542SBram Moolenaar isn_T *iptr = &instr[current]; 3959f2460a3aSBram Moolenaar char *line; 39608a7d6542SBram Moolenaar 39618a7d6542SBram Moolenaar while (line_idx < iptr->isn_lnum && line_idx < ufunc->uf_lines.ga_len) 39628a7d6542SBram Moolenaar { 39638a7d6542SBram Moolenaar if (current > prev_current) 39648a7d6542SBram Moolenaar { 39658a7d6542SBram Moolenaar msg_puts("\n\n"); 39668a7d6542SBram Moolenaar prev_current = current; 39678a7d6542SBram Moolenaar } 3968f2460a3aSBram Moolenaar line = ((char **)ufunc->uf_lines.ga_data)[line_idx++]; 3969f2460a3aSBram Moolenaar if (line != NULL) 3970f2460a3aSBram Moolenaar msg(line); 39718a7d6542SBram Moolenaar } 39728a7d6542SBram Moolenaar 39738a7d6542SBram Moolenaar switch (iptr->isn_type) 39748a7d6542SBram Moolenaar { 39758a7d6542SBram Moolenaar case ISN_EXEC: 39768a7d6542SBram Moolenaar smsg("%4d EXEC %s", current, iptr->isn_arg.string); 39778a7d6542SBram Moolenaar break; 3978cfe435d7SBram Moolenaar case ISN_EXECCONCAT: 3979cfe435d7SBram Moolenaar smsg("%4d EXECCONCAT %lld", current, 398082c38fe5SBram Moolenaar (varnumber_T)iptr->isn_arg.number); 3981cfe435d7SBram Moolenaar break; 39828a7d6542SBram Moolenaar case ISN_ECHO: 39838a7d6542SBram Moolenaar { 39848a7d6542SBram Moolenaar echo_T *echo = &iptr->isn_arg.echo; 39858a7d6542SBram Moolenaar 39868a7d6542SBram Moolenaar smsg("%4d %s %d", current, 39878a7d6542SBram Moolenaar echo->echo_with_white ? "ECHO" : "ECHON", 39888a7d6542SBram Moolenaar echo->echo_count); 39898a7d6542SBram Moolenaar } 39908a7d6542SBram Moolenaar break; 3991ad39c094SBram Moolenaar case ISN_EXECUTE: 39921082772fSBram Moolenaar smsg("%4d EXECUTE %lld", current, 399382c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 3994ad39c094SBram Moolenaar break; 3995f93c7feaSBram Moolenaar case ISN_ECHOMSG: 3996f93c7feaSBram Moolenaar smsg("%4d ECHOMSG %lld", current, 399782c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 3998f93c7feaSBram Moolenaar break; 3999f93c7feaSBram Moolenaar case ISN_ECHOERR: 4000f93c7feaSBram Moolenaar smsg("%4d ECHOERR %lld", current, 400182c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 4002f93c7feaSBram Moolenaar break; 40038a7d6542SBram Moolenaar case ISN_LOAD: 4004c8cd2b34SBram Moolenaar { 40058a7d6542SBram Moolenaar if (iptr->isn_arg.number < 0) 4006ab360526SBram Moolenaar smsg("%4d LOAD arg[%lld]", current, 400782c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number 4008c8cd2b34SBram Moolenaar + STACK_FRAME_SIZE)); 40098a7d6542SBram Moolenaar else 4010ab360526SBram Moolenaar smsg("%4d LOAD $%lld", current, 401182c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 4012c8cd2b34SBram Moolenaar } 40138a7d6542SBram Moolenaar break; 4014ab360526SBram Moolenaar case ISN_LOADOUTER: 4015ab360526SBram Moolenaar { 4016ab360526SBram Moolenaar if (iptr->isn_arg.number < 0) 4017ab360526SBram Moolenaar smsg("%4d LOADOUTER level %d arg[%d]", current, 4018ab360526SBram Moolenaar iptr->isn_arg.outer.outer_depth, 4019ab360526SBram Moolenaar iptr->isn_arg.outer.outer_idx 4020ab360526SBram Moolenaar + STACK_FRAME_SIZE); 4021ab360526SBram Moolenaar else 4022ab360526SBram Moolenaar smsg("%4d LOADOUTER level %d $%d", current, 4023ab360526SBram Moolenaar iptr->isn_arg.outer.outer_depth, 4024ab360526SBram Moolenaar iptr->isn_arg.outer.outer_idx); 4025ab360526SBram Moolenaar } 4026ab360526SBram Moolenaar break; 40278a7d6542SBram Moolenaar case ISN_LOADV: 40288a7d6542SBram Moolenaar smsg("%4d LOADV v:%s", current, 40298a7d6542SBram Moolenaar get_vim_var_name(iptr->isn_arg.number)); 40308a7d6542SBram Moolenaar break; 40318a7d6542SBram Moolenaar case ISN_LOADSCRIPT: 40328a7d6542SBram Moolenaar { 40334aab88d9SBram Moolenaar scriptref_T *sref = iptr->isn_arg.script.scriptref; 40344aab88d9SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid); 40358a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 40364aab88d9SBram Moolenaar + sref->sref_idx; 40378a7d6542SBram Moolenaar 4038fbbcd003SBram Moolenaar smsg("%4d LOADSCRIPT %s-%d from %s", current, 4039fbbcd003SBram Moolenaar sv->sv_name, 40404aab88d9SBram Moolenaar sref->sref_idx, 4041fbbcd003SBram Moolenaar si->sn_name); 40428a7d6542SBram Moolenaar } 40438a7d6542SBram Moolenaar break; 40448a7d6542SBram Moolenaar case ISN_LOADS: 40458a7d6542SBram Moolenaar { 4046b283a8a6SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 4047b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 40488a7d6542SBram Moolenaar 40498a7d6542SBram Moolenaar smsg("%4d LOADS s:%s from %s", current, 40505deeb3f1SBram Moolenaar iptr->isn_arg.loadstore.ls_name, si->sn_name); 40518a7d6542SBram Moolenaar } 40528a7d6542SBram Moolenaar break; 405303290b84SBram Moolenaar case ISN_LOADAUTO: 405403290b84SBram Moolenaar smsg("%4d LOADAUTO %s", current, iptr->isn_arg.string); 405503290b84SBram Moolenaar break; 40568a7d6542SBram Moolenaar case ISN_LOADG: 40578a7d6542SBram Moolenaar smsg("%4d LOADG g:%s", current, iptr->isn_arg.string); 40588a7d6542SBram Moolenaar break; 4059d3aac291SBram Moolenaar case ISN_LOADB: 4060d3aac291SBram Moolenaar smsg("%4d LOADB b:%s", current, iptr->isn_arg.string); 4061d3aac291SBram Moolenaar break; 4062d3aac291SBram Moolenaar case ISN_LOADW: 4063d3aac291SBram Moolenaar smsg("%4d LOADW w:%s", current, iptr->isn_arg.string); 4064d3aac291SBram Moolenaar break; 4065d3aac291SBram Moolenaar case ISN_LOADT: 4066d3aac291SBram Moolenaar smsg("%4d LOADT t:%s", current, iptr->isn_arg.string); 4067d3aac291SBram Moolenaar break; 40682f8ce0aeSBram Moolenaar case ISN_LOADGDICT: 40692f8ce0aeSBram Moolenaar smsg("%4d LOAD g:", current); 40702f8ce0aeSBram Moolenaar break; 40712f8ce0aeSBram Moolenaar case ISN_LOADBDICT: 40722f8ce0aeSBram Moolenaar smsg("%4d LOAD b:", current); 40732f8ce0aeSBram Moolenaar break; 40742f8ce0aeSBram Moolenaar case ISN_LOADWDICT: 40752f8ce0aeSBram Moolenaar smsg("%4d LOAD w:", current); 40762f8ce0aeSBram Moolenaar break; 40772f8ce0aeSBram Moolenaar case ISN_LOADTDICT: 40782f8ce0aeSBram Moolenaar smsg("%4d LOAD t:", current); 40792f8ce0aeSBram Moolenaar break; 40808a7d6542SBram Moolenaar case ISN_LOADOPT: 40818a7d6542SBram Moolenaar smsg("%4d LOADOPT %s", current, iptr->isn_arg.string); 40828a7d6542SBram Moolenaar break; 40838a7d6542SBram Moolenaar case ISN_LOADENV: 40848a7d6542SBram Moolenaar smsg("%4d LOADENV %s", current, iptr->isn_arg.string); 40858a7d6542SBram Moolenaar break; 40868a7d6542SBram Moolenaar case ISN_LOADREG: 40871082772fSBram Moolenaar smsg("%4d LOADREG @%c", current, (int)(iptr->isn_arg.number)); 40888a7d6542SBram Moolenaar break; 40898a7d6542SBram Moolenaar 40908a7d6542SBram Moolenaar case ISN_STORE: 4091ab360526SBram Moolenaar if (iptr->isn_arg.number < 0) 4092ab360526SBram Moolenaar smsg("%4d STORE arg[%lld]", current, 4093ab360526SBram Moolenaar iptr->isn_arg.number + STACK_FRAME_SIZE); 4094ab360526SBram Moolenaar else 4095ab360526SBram Moolenaar smsg("%4d STORE $%lld", current, iptr->isn_arg.number); 4096ab360526SBram Moolenaar break; 4097b68b346eSBram Moolenaar case ISN_STOREOUTER: 4098b68b346eSBram Moolenaar { 4099170fcfcfSBram Moolenaar if (iptr->isn_arg.number < 0) 4100ab360526SBram Moolenaar smsg("%4d STOREOUTEr level %d arg[%d]", current, 4101ab360526SBram Moolenaar iptr->isn_arg.outer.outer_depth, 4102ab360526SBram Moolenaar iptr->isn_arg.outer.outer_idx + STACK_FRAME_SIZE); 4103170fcfcfSBram Moolenaar else 4104ab360526SBram Moolenaar smsg("%4d STOREOUTER level %d $%d", current, 4105ab360526SBram Moolenaar iptr->isn_arg.outer.outer_depth, 4106ab360526SBram Moolenaar iptr->isn_arg.outer.outer_idx); 4107b68b346eSBram Moolenaar } 41088a7d6542SBram Moolenaar break; 4109b283a8a6SBram Moolenaar case ISN_STOREV: 4110b283a8a6SBram Moolenaar smsg("%4d STOREV v:%s", current, 4111b283a8a6SBram Moolenaar get_vim_var_name(iptr->isn_arg.number)); 4112b283a8a6SBram Moolenaar break; 411303290b84SBram Moolenaar case ISN_STOREAUTO: 411403290b84SBram Moolenaar smsg("%4d STOREAUTO %s", current, iptr->isn_arg.string); 411503290b84SBram Moolenaar break; 41168a7d6542SBram Moolenaar case ISN_STOREG: 4117b283a8a6SBram Moolenaar smsg("%4d STOREG %s", current, iptr->isn_arg.string); 4118b283a8a6SBram Moolenaar break; 4119d3aac291SBram Moolenaar case ISN_STOREB: 4120d3aac291SBram Moolenaar smsg("%4d STOREB %s", current, iptr->isn_arg.string); 4121d3aac291SBram Moolenaar break; 4122d3aac291SBram Moolenaar case ISN_STOREW: 4123d3aac291SBram Moolenaar smsg("%4d STOREW %s", current, iptr->isn_arg.string); 4124d3aac291SBram Moolenaar break; 4125d3aac291SBram Moolenaar case ISN_STORET: 4126d3aac291SBram Moolenaar smsg("%4d STORET %s", current, iptr->isn_arg.string); 4127d3aac291SBram Moolenaar break; 4128b283a8a6SBram Moolenaar case ISN_STORES: 4129b283a8a6SBram Moolenaar { 4130b283a8a6SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM( 4131b283a8a6SBram Moolenaar iptr->isn_arg.loadstore.ls_sid); 4132b283a8a6SBram Moolenaar 41330bbf722aSBram Moolenaar smsg("%4d STORES %s in %s", current, 41345deeb3f1SBram Moolenaar iptr->isn_arg.loadstore.ls_name, si->sn_name); 4135b283a8a6SBram Moolenaar } 41368a7d6542SBram Moolenaar break; 41378a7d6542SBram Moolenaar case ISN_STORESCRIPT: 41388a7d6542SBram Moolenaar { 41394aab88d9SBram Moolenaar scriptref_T *sref = iptr->isn_arg.script.scriptref; 41404aab88d9SBram Moolenaar scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid); 41418a7d6542SBram Moolenaar svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) 41424aab88d9SBram Moolenaar + sref->sref_idx; 41438a7d6542SBram Moolenaar 4144fbbcd003SBram Moolenaar smsg("%4d STORESCRIPT %s-%d in %s", current, 4145fbbcd003SBram Moolenaar sv->sv_name, 41464aab88d9SBram Moolenaar sref->sref_idx, 4147fbbcd003SBram Moolenaar si->sn_name); 41488a7d6542SBram Moolenaar } 41498a7d6542SBram Moolenaar break; 41508a7d6542SBram Moolenaar case ISN_STOREOPT: 41518a7d6542SBram Moolenaar smsg("%4d STOREOPT &%s", current, 41528a7d6542SBram Moolenaar iptr->isn_arg.storeopt.so_name); 41538a7d6542SBram Moolenaar break; 4154b283a8a6SBram Moolenaar case ISN_STOREENV: 4155b283a8a6SBram Moolenaar smsg("%4d STOREENV $%s", current, iptr->isn_arg.string); 4156b283a8a6SBram Moolenaar break; 4157b283a8a6SBram Moolenaar case ISN_STOREREG: 41581082772fSBram Moolenaar smsg("%4d STOREREG @%c", current, (int)iptr->isn_arg.number); 4159b283a8a6SBram Moolenaar break; 41608a7d6542SBram Moolenaar case ISN_STORENR: 41618a7d6542SBram Moolenaar smsg("%4d STORE %lld in $%d", current, 4162a471eeaeSBram Moolenaar iptr->isn_arg.storenr.stnr_val, 4163a471eeaeSBram Moolenaar iptr->isn_arg.storenr.stnr_idx); 41648a7d6542SBram Moolenaar break; 41658a7d6542SBram Moolenaar 41664f5e3977SBram Moolenaar case ISN_STOREINDEX: 41674f5e3977SBram Moolenaar switch (iptr->isn_arg.vartype) 41684f5e3977SBram Moolenaar { 41694f5e3977SBram Moolenaar case VAR_LIST: 41701cc2a94fSBram Moolenaar smsg("%4d STORELIST", current); 41711cc2a94fSBram Moolenaar break; 41724f5e3977SBram Moolenaar case VAR_DICT: 41731cc2a94fSBram Moolenaar smsg("%4d STOREDICT", current); 41741cc2a94fSBram Moolenaar break; 41754f5e3977SBram Moolenaar case VAR_ANY: 41764f5e3977SBram Moolenaar smsg("%4d STOREINDEX", current); 41774f5e3977SBram Moolenaar break; 41784f5e3977SBram Moolenaar default: break; 41794f5e3977SBram Moolenaar } 41804f5e3977SBram Moolenaar break; 41811cc2a94fSBram Moolenaar 41828a7d6542SBram Moolenaar // constants 41838a7d6542SBram Moolenaar case ISN_PUSHNR: 41841082772fSBram Moolenaar smsg("%4d PUSHNR %lld", current, 418582c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 41868a7d6542SBram Moolenaar break; 41878a7d6542SBram Moolenaar case ISN_PUSHBOOL: 41888a7d6542SBram Moolenaar case ISN_PUSHSPEC: 41898a7d6542SBram Moolenaar smsg("%4d PUSH %s", current, 41908a7d6542SBram Moolenaar get_var_special_name(iptr->isn_arg.number)); 41918a7d6542SBram Moolenaar break; 41928a7d6542SBram Moolenaar case ISN_PUSHF: 4193a5d5953dSBram Moolenaar #ifdef FEAT_FLOAT 41948a7d6542SBram Moolenaar smsg("%4d PUSHF %g", current, iptr->isn_arg.fnumber); 4195a5d5953dSBram Moolenaar #endif 41968a7d6542SBram Moolenaar break; 41978a7d6542SBram Moolenaar case ISN_PUSHS: 41988a7d6542SBram Moolenaar smsg("%4d PUSHS \"%s\"", current, iptr->isn_arg.string); 41998a7d6542SBram Moolenaar break; 42008a7d6542SBram Moolenaar case ISN_PUSHBLOB: 42018a7d6542SBram Moolenaar { 42028a7d6542SBram Moolenaar char_u *r; 42038a7d6542SBram Moolenaar char_u numbuf[NUMBUFLEN]; 42048a7d6542SBram Moolenaar char_u *tofree; 42058a7d6542SBram Moolenaar 42068a7d6542SBram Moolenaar r = blob2string(iptr->isn_arg.blob, &tofree, numbuf); 4207ff80cb68SBram Moolenaar smsg("%4d PUSHBLOB %s", current, r); 42088a7d6542SBram Moolenaar vim_free(tofree); 42098a7d6542SBram Moolenaar } 42108a7d6542SBram Moolenaar break; 421142a480bfSBram Moolenaar case ISN_PUSHFUNC: 4212087d2e15SBram Moolenaar { 4213087d2e15SBram Moolenaar char *name = (char *)iptr->isn_arg.string; 4214087d2e15SBram Moolenaar 4215087d2e15SBram Moolenaar smsg("%4d PUSHFUNC \"%s\"", current, 4216087d2e15SBram Moolenaar name == NULL ? "[none]" : name); 4217087d2e15SBram Moolenaar } 421842a480bfSBram Moolenaar break; 421942a480bfSBram Moolenaar case ISN_PUSHCHANNEL: 422042a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 422142a480bfSBram Moolenaar { 422242a480bfSBram Moolenaar channel_T *channel = iptr->isn_arg.channel; 422342a480bfSBram Moolenaar 422442a480bfSBram Moolenaar smsg("%4d PUSHCHANNEL %d", current, 422542a480bfSBram Moolenaar channel == NULL ? 0 : channel->ch_id); 422642a480bfSBram Moolenaar } 422742a480bfSBram Moolenaar #endif 422842a480bfSBram Moolenaar break; 422942a480bfSBram Moolenaar case ISN_PUSHJOB: 423042a480bfSBram Moolenaar #ifdef FEAT_JOB_CHANNEL 423142a480bfSBram Moolenaar { 423242a480bfSBram Moolenaar typval_T tv; 423342a480bfSBram Moolenaar char_u *name; 423442a480bfSBram Moolenaar 423542a480bfSBram Moolenaar tv.v_type = VAR_JOB; 423642a480bfSBram Moolenaar tv.vval.v_job = iptr->isn_arg.job; 423742a480bfSBram Moolenaar name = tv_get_string(&tv); 4238f51cb4e0SBram Moolenaar smsg("%4d PUSHJOB \"%s\"", current, name); 423942a480bfSBram Moolenaar } 424042a480bfSBram Moolenaar #endif 424142a480bfSBram Moolenaar break; 42428a7d6542SBram Moolenaar case ISN_PUSHEXC: 42438a7d6542SBram Moolenaar smsg("%4d PUSH v:exception", current); 42448a7d6542SBram Moolenaar break; 4245d72c1bf0SBram Moolenaar case ISN_UNLET: 4246d72c1bf0SBram Moolenaar smsg("%4d UNLET%s %s", current, 4247d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_forceit ? "!" : "", 4248d72c1bf0SBram Moolenaar iptr->isn_arg.unlet.ul_name); 4249d72c1bf0SBram Moolenaar break; 42507bdaea6eSBram Moolenaar case ISN_UNLETENV: 42517bdaea6eSBram Moolenaar smsg("%4d UNLETENV%s $%s", current, 42527bdaea6eSBram Moolenaar iptr->isn_arg.unlet.ul_forceit ? "!" : "", 42537bdaea6eSBram Moolenaar iptr->isn_arg.unlet.ul_name); 42547bdaea6eSBram Moolenaar break; 4255752fc692SBram Moolenaar case ISN_UNLETINDEX: 4256752fc692SBram Moolenaar smsg("%4d UNLETINDEX", current); 4257752fc692SBram Moolenaar break; 42585b5ae29bSBram Moolenaar case ISN_UNLETRANGE: 42595b5ae29bSBram Moolenaar smsg("%4d UNLETRANGE", current); 42605b5ae29bSBram Moolenaar break; 42610b4c66c6SBram Moolenaar case ISN_LOCKCONST: 42620b4c66c6SBram Moolenaar smsg("%4d LOCKCONST", current); 42630b4c66c6SBram Moolenaar break; 42648a7d6542SBram Moolenaar case ISN_NEWLIST: 42651082772fSBram Moolenaar smsg("%4d NEWLIST size %lld", current, 426682c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 42678a7d6542SBram Moolenaar break; 42688a7d6542SBram Moolenaar case ISN_NEWDICT: 42691082772fSBram Moolenaar smsg("%4d NEWDICT size %lld", current, 427082c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 42718a7d6542SBram Moolenaar break; 42728a7d6542SBram Moolenaar 42738a7d6542SBram Moolenaar // function call 42748a7d6542SBram Moolenaar case ISN_BCALL: 42758a7d6542SBram Moolenaar { 42768a7d6542SBram Moolenaar cbfunc_T *cbfunc = &iptr->isn_arg.bfunc; 42778a7d6542SBram Moolenaar 42788a7d6542SBram Moolenaar smsg("%4d BCALL %s(argc %d)", current, 42798a7d6542SBram Moolenaar internal_func_name(cbfunc->cbf_idx), 42808a7d6542SBram Moolenaar cbfunc->cbf_argcount); 42818a7d6542SBram Moolenaar } 42828a7d6542SBram Moolenaar break; 42838a7d6542SBram Moolenaar case ISN_DCALL: 42848a7d6542SBram Moolenaar { 42858a7d6542SBram Moolenaar cdfunc_T *cdfunc = &iptr->isn_arg.dfunc; 42868a7d6542SBram Moolenaar dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 42878a7d6542SBram Moolenaar + cdfunc->cdf_idx; 42888a7d6542SBram Moolenaar 42898a7d6542SBram Moolenaar smsg("%4d DCALL %s(argc %d)", current, 42908a7d6542SBram Moolenaar df->df_ufunc->uf_name_exp != NULL 42918a7d6542SBram Moolenaar ? df->df_ufunc->uf_name_exp 42928a7d6542SBram Moolenaar : df->df_ufunc->uf_name, cdfunc->cdf_argcount); 42938a7d6542SBram Moolenaar } 42948a7d6542SBram Moolenaar break; 42958a7d6542SBram Moolenaar case ISN_UCALL: 42968a7d6542SBram Moolenaar { 42978a7d6542SBram Moolenaar cufunc_T *cufunc = &iptr->isn_arg.ufunc; 42988a7d6542SBram Moolenaar 42998a7d6542SBram Moolenaar smsg("%4d UCALL %s(argc %d)", current, 43008a7d6542SBram Moolenaar cufunc->cuf_name, cufunc->cuf_argcount); 43018a7d6542SBram Moolenaar } 43028a7d6542SBram Moolenaar break; 43038a7d6542SBram Moolenaar case ISN_PCALL: 43048a7d6542SBram Moolenaar { 43058a7d6542SBram Moolenaar cpfunc_T *cpfunc = &iptr->isn_arg.pfunc; 43068a7d6542SBram Moolenaar 43078a7d6542SBram Moolenaar smsg("%4d PCALL%s (argc %d)", current, 43088a7d6542SBram Moolenaar cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); 43098a7d6542SBram Moolenaar } 43108a7d6542SBram Moolenaar break; 4311bd5da371SBram Moolenaar case ISN_PCALL_END: 4312bd5da371SBram Moolenaar smsg("%4d PCALL end", current); 4313bd5da371SBram Moolenaar break; 43148a7d6542SBram Moolenaar case ISN_RETURN: 43158a7d6542SBram Moolenaar smsg("%4d RETURN", current); 43168a7d6542SBram Moolenaar break; 4317299f3036SBram Moolenaar case ISN_RETURN_ZERO: 4318299f3036SBram Moolenaar smsg("%4d RETURN 0", current); 4319299f3036SBram Moolenaar break; 43208a7d6542SBram Moolenaar case ISN_FUNCREF: 43218a7d6542SBram Moolenaar { 43225adc55cbSBram Moolenaar funcref_T *funcref = &iptr->isn_arg.funcref; 43238a7d6542SBram Moolenaar dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 43245adc55cbSBram Moolenaar + funcref->fr_func; 43258a7d6542SBram Moolenaar 4326148ce7aeSBram Moolenaar smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name); 43278a7d6542SBram Moolenaar } 43288a7d6542SBram Moolenaar break; 43298a7d6542SBram Moolenaar 433038ddf333SBram Moolenaar case ISN_NEWFUNC: 433138ddf333SBram Moolenaar { 433238ddf333SBram Moolenaar newfunc_T *newfunc = &iptr->isn_arg.newfunc; 433338ddf333SBram Moolenaar 433438ddf333SBram Moolenaar smsg("%4d NEWFUNC %s %s", current, 433538ddf333SBram Moolenaar newfunc->nf_lambda, newfunc->nf_global); 433638ddf333SBram Moolenaar } 433738ddf333SBram Moolenaar break; 433838ddf333SBram Moolenaar 43396abdcf82SBram Moolenaar case ISN_DEF: 43406abdcf82SBram Moolenaar { 43416abdcf82SBram Moolenaar char_u *name = iptr->isn_arg.string; 43426abdcf82SBram Moolenaar 43436abdcf82SBram Moolenaar smsg("%4d DEF %s", current, 43446abdcf82SBram Moolenaar name == NULL ? (char_u *)"" : name); 43456abdcf82SBram Moolenaar } 43466abdcf82SBram Moolenaar break; 43476abdcf82SBram Moolenaar 43488a7d6542SBram Moolenaar case ISN_JUMP: 43498a7d6542SBram Moolenaar { 43508a7d6542SBram Moolenaar char *when = "?"; 43518a7d6542SBram Moolenaar 43528a7d6542SBram Moolenaar switch (iptr->isn_arg.jump.jump_when) 43538a7d6542SBram Moolenaar { 43548a7d6542SBram Moolenaar case JUMP_ALWAYS: 43558a7d6542SBram Moolenaar when = "JUMP"; 43568a7d6542SBram Moolenaar break; 43578a7d6542SBram Moolenaar case JUMP_AND_KEEP_IF_TRUE: 43588a7d6542SBram Moolenaar when = "JUMP_AND_KEEP_IF_TRUE"; 43598a7d6542SBram Moolenaar break; 43608a7d6542SBram Moolenaar case JUMP_IF_FALSE: 43618a7d6542SBram Moolenaar when = "JUMP_IF_FALSE"; 43628a7d6542SBram Moolenaar break; 43638a7d6542SBram Moolenaar case JUMP_AND_KEEP_IF_FALSE: 43648a7d6542SBram Moolenaar when = "JUMP_AND_KEEP_IF_FALSE"; 43658a7d6542SBram Moolenaar break; 43662bb2658bSBram Moolenaar case JUMP_IF_COND_FALSE: 43672bb2658bSBram Moolenaar when = "JUMP_IF_COND_FALSE"; 43682bb2658bSBram Moolenaar break; 43692bb2658bSBram Moolenaar case JUMP_IF_COND_TRUE: 43702bb2658bSBram Moolenaar when = "JUMP_IF_COND_TRUE"; 43712bb2658bSBram Moolenaar break; 43728a7d6542SBram Moolenaar } 43738a677a37SBram Moolenaar smsg("%4d %s -> %d", current, when, 43748a7d6542SBram Moolenaar iptr->isn_arg.jump.jump_where); 43758a7d6542SBram Moolenaar } 43768a7d6542SBram Moolenaar break; 43778a7d6542SBram Moolenaar 43788a7d6542SBram Moolenaar case ISN_FOR: 43798a7d6542SBram Moolenaar { 43808a7d6542SBram Moolenaar forloop_T *forloop = &iptr->isn_arg.forloop; 43818a7d6542SBram Moolenaar 43828a7d6542SBram Moolenaar smsg("%4d FOR $%d -> %d", current, 43838a7d6542SBram Moolenaar forloop->for_idx, forloop->for_end); 43848a7d6542SBram Moolenaar } 43858a7d6542SBram Moolenaar break; 43868a7d6542SBram Moolenaar 43878a7d6542SBram Moolenaar case ISN_TRY: 43888a7d6542SBram Moolenaar { 43898a7d6542SBram Moolenaar try_T *try = &iptr->isn_arg.try; 43908a7d6542SBram Moolenaar 43917e82c5f3SBram Moolenaar if (try->try_ref->try_finally == 0) 43927e82c5f3SBram Moolenaar smsg("%4d TRY catch -> %d, endtry -> %d", 43937e82c5f3SBram Moolenaar current, 43947e82c5f3SBram Moolenaar try->try_ref->try_catch, 43957e82c5f3SBram Moolenaar try->try_ref->try_endtry); 43967e82c5f3SBram Moolenaar else 43977e82c5f3SBram Moolenaar smsg("%4d TRY catch -> %d, finally -> %d, endtry -> %d", 43987e82c5f3SBram Moolenaar current, 43997e82c5f3SBram Moolenaar try->try_ref->try_catch, 44007e82c5f3SBram Moolenaar try->try_ref->try_finally, 44017e82c5f3SBram Moolenaar try->try_ref->try_endtry); 44028a7d6542SBram Moolenaar } 44038a7d6542SBram Moolenaar break; 44048a7d6542SBram Moolenaar case ISN_CATCH: 44058a7d6542SBram Moolenaar // TODO 44068a7d6542SBram Moolenaar smsg("%4d CATCH", current); 44078a7d6542SBram Moolenaar break; 4408c150c09eSBram Moolenaar case ISN_TRYCONT: 4409c150c09eSBram Moolenaar { 4410c150c09eSBram Moolenaar trycont_T *trycont = &iptr->isn_arg.trycont; 4411c150c09eSBram Moolenaar 4412c150c09eSBram Moolenaar smsg("%4d TRY-CONTINUE %d level%s -> %d", current, 4413c150c09eSBram Moolenaar trycont->tct_levels, 4414c150c09eSBram Moolenaar trycont->tct_levels == 1 ? "" : "s", 4415c150c09eSBram Moolenaar trycont->tct_where); 4416c150c09eSBram Moolenaar } 4417c150c09eSBram Moolenaar break; 44187e82c5f3SBram Moolenaar case ISN_FINALLY: 44197e82c5f3SBram Moolenaar smsg("%4d FINALLY", current); 44207e82c5f3SBram Moolenaar break; 44218a7d6542SBram Moolenaar case ISN_ENDTRY: 44228a7d6542SBram Moolenaar smsg("%4d ENDTRY", current); 44238a7d6542SBram Moolenaar break; 44248a7d6542SBram Moolenaar case ISN_THROW: 44258a7d6542SBram Moolenaar smsg("%4d THROW", current); 44268a7d6542SBram Moolenaar break; 44278a7d6542SBram Moolenaar 44288a7d6542SBram Moolenaar // expression operations on number 44298a7d6542SBram Moolenaar case ISN_OPNR: 44308a7d6542SBram Moolenaar case ISN_OPFLOAT: 44318a7d6542SBram Moolenaar case ISN_OPANY: 44328a7d6542SBram Moolenaar { 44338a7d6542SBram Moolenaar char *what; 44348a7d6542SBram Moolenaar char *ins; 44358a7d6542SBram Moolenaar 44368a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 44378a7d6542SBram Moolenaar { 44388a7d6542SBram Moolenaar case EXPR_MULT: what = "*"; break; 44398a7d6542SBram Moolenaar case EXPR_DIV: what = "/"; break; 44408a7d6542SBram Moolenaar case EXPR_REM: what = "%"; break; 44418a7d6542SBram Moolenaar case EXPR_SUB: what = "-"; break; 44428a7d6542SBram Moolenaar case EXPR_ADD: what = "+"; break; 44438a7d6542SBram Moolenaar default: what = "???"; break; 44448a7d6542SBram Moolenaar } 44458a7d6542SBram Moolenaar switch (iptr->isn_type) 44468a7d6542SBram Moolenaar { 44478a7d6542SBram Moolenaar case ISN_OPNR: ins = "OPNR"; break; 44488a7d6542SBram Moolenaar case ISN_OPFLOAT: ins = "OPFLOAT"; break; 44498a7d6542SBram Moolenaar case ISN_OPANY: ins = "OPANY"; break; 44508a7d6542SBram Moolenaar default: ins = "???"; break; 44518a7d6542SBram Moolenaar } 44528a7d6542SBram Moolenaar smsg("%4d %s %s", current, ins, what); 44538a7d6542SBram Moolenaar } 44548a7d6542SBram Moolenaar break; 44558a7d6542SBram Moolenaar 44568a7d6542SBram Moolenaar case ISN_COMPAREBOOL: 44578a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 44588a7d6542SBram Moolenaar case ISN_COMPARENR: 44598a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: 44608a7d6542SBram Moolenaar case ISN_COMPARESTRING: 44618a7d6542SBram Moolenaar case ISN_COMPAREBLOB: 44628a7d6542SBram Moolenaar case ISN_COMPARELIST: 44638a7d6542SBram Moolenaar case ISN_COMPAREDICT: 44648a7d6542SBram Moolenaar case ISN_COMPAREFUNC: 44658a7d6542SBram Moolenaar case ISN_COMPAREANY: 44668a7d6542SBram Moolenaar { 44678a7d6542SBram Moolenaar char *p; 44688a7d6542SBram Moolenaar char buf[10]; 44698a7d6542SBram Moolenaar char *type; 44708a7d6542SBram Moolenaar 44718a7d6542SBram Moolenaar switch (iptr->isn_arg.op.op_type) 44728a7d6542SBram Moolenaar { 44738a7d6542SBram Moolenaar case EXPR_EQUAL: p = "=="; break; 44748a7d6542SBram Moolenaar case EXPR_NEQUAL: p = "!="; break; 44758a7d6542SBram Moolenaar case EXPR_GREATER: p = ">"; break; 44768a7d6542SBram Moolenaar case EXPR_GEQUAL: p = ">="; break; 44778a7d6542SBram Moolenaar case EXPR_SMALLER: p = "<"; break; 44788a7d6542SBram Moolenaar case EXPR_SEQUAL: p = "<="; break; 44798a7d6542SBram Moolenaar case EXPR_MATCH: p = "=~"; break; 44808a7d6542SBram Moolenaar case EXPR_IS: p = "is"; break; 44818a7d6542SBram Moolenaar case EXPR_ISNOT: p = "isnot"; break; 44828a7d6542SBram Moolenaar case EXPR_NOMATCH: p = "!~"; break; 44838a7d6542SBram Moolenaar default: p = "???"; break; 44848a7d6542SBram Moolenaar } 44858a7d6542SBram Moolenaar STRCPY(buf, p); 44868a7d6542SBram Moolenaar if (iptr->isn_arg.op.op_ic == TRUE) 44878a7d6542SBram Moolenaar strcat(buf, "?"); 44888a7d6542SBram Moolenaar switch(iptr->isn_type) 44898a7d6542SBram Moolenaar { 44908a7d6542SBram Moolenaar case ISN_COMPAREBOOL: type = "COMPAREBOOL"; break; 44918a7d6542SBram Moolenaar case ISN_COMPARESPECIAL: 44928a7d6542SBram Moolenaar type = "COMPARESPECIAL"; break; 44938a7d6542SBram Moolenaar case ISN_COMPARENR: type = "COMPARENR"; break; 44948a7d6542SBram Moolenaar case ISN_COMPAREFLOAT: type = "COMPAREFLOAT"; break; 44958a7d6542SBram Moolenaar case ISN_COMPARESTRING: 44968a7d6542SBram Moolenaar type = "COMPARESTRING"; break; 44978a7d6542SBram Moolenaar case ISN_COMPAREBLOB: type = "COMPAREBLOB"; break; 44988a7d6542SBram Moolenaar case ISN_COMPARELIST: type = "COMPARELIST"; break; 44998a7d6542SBram Moolenaar case ISN_COMPAREDICT: type = "COMPAREDICT"; break; 45008a7d6542SBram Moolenaar case ISN_COMPAREFUNC: type = "COMPAREFUNC"; break; 45018a7d6542SBram Moolenaar case ISN_COMPAREANY: type = "COMPAREANY"; break; 45028a7d6542SBram Moolenaar default: type = "???"; break; 45038a7d6542SBram Moolenaar } 45048a7d6542SBram Moolenaar 45058a7d6542SBram Moolenaar smsg("%4d %s %s", current, type, buf); 45068a7d6542SBram Moolenaar } 45078a7d6542SBram Moolenaar break; 45088a7d6542SBram Moolenaar 45098a7d6542SBram Moolenaar case ISN_ADDLIST: smsg("%4d ADDLIST", current); break; 45108a7d6542SBram Moolenaar case ISN_ADDBLOB: smsg("%4d ADDBLOB", current); break; 45118a7d6542SBram Moolenaar 45128a7d6542SBram Moolenaar // expression operations 45138a7d6542SBram Moolenaar case ISN_CONCAT: smsg("%4d CONCAT", current); break; 4514bf9d8c37SBram Moolenaar case ISN_STRINDEX: smsg("%4d STRINDEX", current); break; 451511107babSBram Moolenaar case ISN_STRSLICE: smsg("%4d STRSLICE", current); break; 45161dcae599SBram Moolenaar case ISN_LISTAPPEND: smsg("%4d LISTAPPEND", current); break; 451780b0e5eaSBram Moolenaar case ISN_BLOBAPPEND: smsg("%4d BLOBAPPEND", current); break; 4518bf9d8c37SBram Moolenaar case ISN_LISTINDEX: smsg("%4d LISTINDEX", current); break; 4519ed591877SBram Moolenaar case ISN_LISTSLICE: smsg("%4d LISTSLICE", current); break; 4520cc673e74SBram Moolenaar case ISN_ANYINDEX: smsg("%4d ANYINDEX", current); break; 4521cc673e74SBram Moolenaar case ISN_ANYSLICE: smsg("%4d ANYSLICE", current); break; 45229af78769SBram Moolenaar case ISN_SLICE: smsg("%4d SLICE %lld", 45239af78769SBram Moolenaar current, iptr->isn_arg.number); break; 452447a519a9SBram Moolenaar case ISN_GETITEM: smsg("%4d ITEM %lld", 452547a519a9SBram Moolenaar current, iptr->isn_arg.number); break; 45261cc2a94fSBram Moolenaar case ISN_MEMBER: smsg("%4d MEMBER", current); break; 45271cc2a94fSBram Moolenaar case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current, 45288a7d6542SBram Moolenaar iptr->isn_arg.string); break; 45298a7d6542SBram Moolenaar case ISN_NEGATENR: smsg("%4d NEGATENR", current); break; 45308a7d6542SBram Moolenaar 45318a7d6542SBram Moolenaar case ISN_CHECKNR: smsg("%4d CHECKNR", current); break; 45325e654230SBram Moolenaar case ISN_CHECKTYPE: 45335e654230SBram Moolenaar { 4534e32e516dSBram Moolenaar checktype_T *ct = &iptr->isn_arg.type; 45355e654230SBram Moolenaar char *tofree; 45365e654230SBram Moolenaar 4537e32e516dSBram Moolenaar if (ct->ct_arg_idx == 0) 45385e654230SBram Moolenaar smsg("%4d CHECKTYPE %s stack[%d]", current, 4539e32e516dSBram Moolenaar type_name(ct->ct_type, &tofree), 4540b3005ce1SBram Moolenaar (int)ct->ct_off); 4541e32e516dSBram Moolenaar else 4542e32e516dSBram Moolenaar smsg("%4d CHECKTYPE %s stack[%d] arg %d", current, 4543e32e516dSBram Moolenaar type_name(ct->ct_type, &tofree), 4544b3005ce1SBram Moolenaar (int)ct->ct_off, 4545e32e516dSBram Moolenaar (int)ct->ct_arg_idx); 45465e654230SBram Moolenaar vim_free(tofree); 45478a7d6542SBram Moolenaar break; 45485e654230SBram Moolenaar } 45499af78769SBram Moolenaar case ISN_CHECKLEN: smsg("%4d CHECKLEN %s%d", current, 45509af78769SBram Moolenaar iptr->isn_arg.checklen.cl_more_OK ? ">= " : "", 45519af78769SBram Moolenaar iptr->isn_arg.checklen.cl_min_len); 45529af78769SBram Moolenaar break; 4553aa210a3aSBram Moolenaar case ISN_SETTYPE: 4554aa210a3aSBram Moolenaar { 4555aa210a3aSBram Moolenaar char *tofree; 4556aa210a3aSBram Moolenaar 4557aa210a3aSBram Moolenaar smsg("%4d SETTYPE %s", current, 4558aa210a3aSBram Moolenaar type_name(iptr->isn_arg.type.ct_type, &tofree)); 4559aa210a3aSBram Moolenaar vim_free(tofree); 4560aa210a3aSBram Moolenaar break; 4561aa210a3aSBram Moolenaar } 45622bb2658bSBram Moolenaar case ISN_COND2BOOL: smsg("%4d COND2BOOL", current); break; 45638a7d6542SBram Moolenaar case ISN_2BOOL: if (iptr->isn_arg.number) 45648a7d6542SBram Moolenaar smsg("%4d INVERT (!val)", current); 45658a7d6542SBram Moolenaar else 45668a7d6542SBram Moolenaar smsg("%4d 2BOOL (!!val)", current); 45678a7d6542SBram Moolenaar break; 4568db99f9f2SBram Moolenaar case ISN_2STRING: smsg("%4d 2STRING stack[%lld]", current, 456982c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 45708a7d6542SBram Moolenaar break; 4571418f1df5SBram Moolenaar case ISN_2STRING_ANY: smsg("%4d 2STRING_ANY stack[%lld]", current, 457282c38fe5SBram Moolenaar (varnumber_T)(iptr->isn_arg.number)); 4573418f1df5SBram Moolenaar break; 457408597875SBram Moolenaar case ISN_RANGE: smsg("%4d RANGE %s", current, iptr->isn_arg.string); 457508597875SBram Moolenaar break; 4576c3516f7eSBram Moolenaar case ISN_PUT: 457708597875SBram Moolenaar if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE_ABOVE) 457808597875SBram Moolenaar smsg("%4d PUT %c above range", 457908597875SBram Moolenaar current, iptr->isn_arg.put.put_regname); 458008597875SBram Moolenaar else if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE) 458108597875SBram Moolenaar smsg("%4d PUT %c range", 458208597875SBram Moolenaar current, iptr->isn_arg.put.put_regname); 458308597875SBram Moolenaar else 458408597875SBram Moolenaar smsg("%4d PUT %c %ld", current, 458508597875SBram Moolenaar iptr->isn_arg.put.put_regname, 4586c3516f7eSBram Moolenaar (long)iptr->isn_arg.put.put_lnum); 4587c3516f7eSBram Moolenaar break; 45888a7d6542SBram Moolenaar 458902194d2bSBram Moolenaar // TODO: summarize modifiers 459002194d2bSBram Moolenaar case ISN_CMDMOD: 459102194d2bSBram Moolenaar { 459202194d2bSBram Moolenaar char_u *buf; 4593a360dbe3SBram Moolenaar size_t len = produce_cmdmods( 459402194d2bSBram Moolenaar NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE); 459502194d2bSBram Moolenaar 459602194d2bSBram Moolenaar buf = alloc(len + 1); 459702194d2bSBram Moolenaar if (buf != NULL) 459802194d2bSBram Moolenaar { 459902194d2bSBram Moolenaar (void)produce_cmdmods( 460002194d2bSBram Moolenaar buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE); 460102194d2bSBram Moolenaar smsg("%4d CMDMOD %s", current, buf); 460202194d2bSBram Moolenaar vim_free(buf); 460302194d2bSBram Moolenaar } 460402194d2bSBram Moolenaar break; 460502194d2bSBram Moolenaar } 460602194d2bSBram Moolenaar case ISN_CMDMOD_REV: smsg("%4d CMDMOD_REV", current); break; 4607f4c6e1e7SBram Moolenaar 4608b2049903SBram Moolenaar case ISN_PROF_START: 4609b2049903SBram Moolenaar smsg("%4d PROFILE START line %d", current, iptr->isn_lnum); 4610b2049903SBram Moolenaar break; 4611b2049903SBram Moolenaar 4612b2049903SBram Moolenaar case ISN_PROF_END: 4613b2049903SBram Moolenaar smsg("%4d PROFILE END", current); 4614b2049903SBram Moolenaar break; 4615b2049903SBram Moolenaar 4616792f786aSBram Moolenaar case ISN_UNPACK: smsg("%4d UNPACK %d%s", current, 4617792f786aSBram Moolenaar iptr->isn_arg.unpack.unp_count, 4618792f786aSBram Moolenaar iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : ""); 4619792f786aSBram Moolenaar break; 4620389df259SBram Moolenaar case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current, 4621389df259SBram Moolenaar iptr->isn_arg.shuffle.shfl_item, 4622389df259SBram Moolenaar iptr->isn_arg.shuffle.shfl_up); 4623389df259SBram Moolenaar break; 46248a7d6542SBram Moolenaar case ISN_DROP: smsg("%4d DROP", current); break; 46258a7d6542SBram Moolenaar } 4626793dcc54SBram Moolenaar 4627793dcc54SBram Moolenaar out_flush(); // output one line at a time 4628793dcc54SBram Moolenaar ui_breakcheck(); 4629793dcc54SBram Moolenaar if (got_int) 4630793dcc54SBram Moolenaar break; 46318a7d6542SBram Moolenaar } 46328a7d6542SBram Moolenaar } 46338a7d6542SBram Moolenaar 46348a7d6542SBram Moolenaar /* 463513106605SBram Moolenaar * Return TRUE when "tv" is not falsy: non-zero, non-empty string, non-empty 46368a7d6542SBram Moolenaar * list, etc. Mostly like what JavaScript does, except that empty list and 46378a7d6542SBram Moolenaar * empty dictionary are FALSE. 46388a7d6542SBram Moolenaar */ 46398a7d6542SBram Moolenaar int 46408a7d6542SBram Moolenaar tv2bool(typval_T *tv) 46418a7d6542SBram Moolenaar { 46428a7d6542SBram Moolenaar switch (tv->v_type) 46438a7d6542SBram Moolenaar { 46448a7d6542SBram Moolenaar case VAR_NUMBER: 46458a7d6542SBram Moolenaar return tv->vval.v_number != 0; 46468a7d6542SBram Moolenaar case VAR_FLOAT: 46478a7d6542SBram Moolenaar #ifdef FEAT_FLOAT 46488a7d6542SBram Moolenaar return tv->vval.v_float != 0.0; 46498a7d6542SBram Moolenaar #else 46508a7d6542SBram Moolenaar break; 46518a7d6542SBram Moolenaar #endif 46528a7d6542SBram Moolenaar case VAR_PARTIAL: 46538a7d6542SBram Moolenaar return tv->vval.v_partial != NULL; 46548a7d6542SBram Moolenaar case VAR_FUNC: 46558a7d6542SBram Moolenaar case VAR_STRING: 46568a7d6542SBram Moolenaar return tv->vval.v_string != NULL && *tv->vval.v_string != NUL; 46578a7d6542SBram Moolenaar case VAR_LIST: 46588a7d6542SBram Moolenaar return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0; 46598a7d6542SBram Moolenaar case VAR_DICT: 46608a7d6542SBram Moolenaar return tv->vval.v_dict != NULL 46618a7d6542SBram Moolenaar && tv->vval.v_dict->dv_hashtab.ht_used > 0; 46628a7d6542SBram Moolenaar case VAR_BOOL: 46638a7d6542SBram Moolenaar case VAR_SPECIAL: 46648a7d6542SBram Moolenaar return tv->vval.v_number == VVAL_TRUE ? TRUE : FALSE; 46658a7d6542SBram Moolenaar case VAR_JOB: 46668a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL 46678a7d6542SBram Moolenaar return tv->vval.v_job != NULL; 46688a7d6542SBram Moolenaar #else 46698a7d6542SBram Moolenaar break; 46708a7d6542SBram Moolenaar #endif 46718a7d6542SBram Moolenaar case VAR_CHANNEL: 46728a7d6542SBram Moolenaar #ifdef FEAT_JOB_CHANNEL 46738a7d6542SBram Moolenaar return tv->vval.v_channel != NULL; 46748a7d6542SBram Moolenaar #else 46758a7d6542SBram Moolenaar break; 46768a7d6542SBram Moolenaar #endif 46778a7d6542SBram Moolenaar case VAR_BLOB: 46788a7d6542SBram Moolenaar return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0; 46798a7d6542SBram Moolenaar case VAR_UNKNOWN: 46804c683750SBram Moolenaar case VAR_ANY: 46818a7d6542SBram Moolenaar case VAR_VOID: 46828a7d6542SBram Moolenaar break; 46838a7d6542SBram Moolenaar } 46848a7d6542SBram Moolenaar return FALSE; 46858a7d6542SBram Moolenaar } 46868a7d6542SBram Moolenaar 4687ea2d407fSBram Moolenaar void 4688ea2d407fSBram Moolenaar emsg_using_string_as(typval_T *tv, int as_number) 4689ea2d407fSBram Moolenaar { 4690ea2d407fSBram Moolenaar semsg(_(as_number ? e_using_string_as_number_str 4691ea2d407fSBram Moolenaar : e_using_string_as_bool_str), 4692ea2d407fSBram Moolenaar tv->vval.v_string == NULL 4693ea2d407fSBram Moolenaar ? (char_u *)"" : tv->vval.v_string); 4694ea2d407fSBram Moolenaar } 4695ea2d407fSBram Moolenaar 46968a7d6542SBram Moolenaar /* 46978a7d6542SBram Moolenaar * If "tv" is a string give an error and return FAIL. 46988a7d6542SBram Moolenaar */ 46998a7d6542SBram Moolenaar int 47008a7d6542SBram Moolenaar check_not_string(typval_T *tv) 47018a7d6542SBram Moolenaar { 47028a7d6542SBram Moolenaar if (tv->v_type == VAR_STRING) 47038a7d6542SBram Moolenaar { 4704ea2d407fSBram Moolenaar emsg_using_string_as(tv, TRUE); 47058a7d6542SBram Moolenaar clear_tv(tv); 47068a7d6542SBram Moolenaar return FAIL; 47078a7d6542SBram Moolenaar } 47088a7d6542SBram Moolenaar return OK; 47098a7d6542SBram Moolenaar } 47108a7d6542SBram Moolenaar 47118a7d6542SBram Moolenaar 47128a7d6542SBram Moolenaar #endif // FEAT_EVAL 4713