blob: 279a8c3a3e6c75b0045ed7d0fb795826d660177f [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9compile.c: :def and dealing with instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#define DEFINE_VIM9_GLOBALS
24#include "vim9.h"
25
Bram Moolenaarefd88552020-06-18 20:50:10 +020026// values for ctx_skip
27typedef enum {
28 SKIP_NOT, // condition is a constant, produce code
29 SKIP_YES, // condition is a constant, do NOT produce code
Bram Moolenaar280b0dc2020-06-20 13:29:03 +020030 SKIP_UNKNOWN // condition is not a constant, produce code
Bram Moolenaarefd88552020-06-18 20:50:10 +020031} skip_T;
32
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010033/*
34 * Chain of jump instructions where the end label needs to be set.
35 */
36typedef struct endlabel_S endlabel_T;
37struct endlabel_S {
38 endlabel_T *el_next; // chain end_label locations
39 int el_end_label; // instruction idx where to set end
40};
41
42/*
43 * info specific for the scope of :if / elseif / else
44 */
45typedef struct {
Bram Moolenaarefd88552020-06-18 20:50:10 +020046 int is_seen_else;
Bram Moolenaarced68a02021-01-24 17:53:47 +010047 int is_seen_skip_not; // a block was unconditionally executed
Bram Moolenaarefd88552020-06-18 20:50:10 +020048 int is_had_return; // every block ends in :return
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010049 int is_if_label; // instruction idx at IF or ELSEIF
50 endlabel_T *is_end_label; // instructions to set end label
51} ifscope_T;
52
53/*
54 * info specific for the scope of :while
55 */
56typedef struct {
57 int ws_top_label; // instruction idx at WHILE
58 endlabel_T *ws_end_label; // instructions to set end
59} whilescope_T;
60
61/*
62 * info specific for the scope of :for
63 */
64typedef struct {
65 int fs_top_label; // instruction idx at FOR
66 endlabel_T *fs_end_label; // break instructions
67} forscope_T;
68
69/*
70 * info specific for the scope of :try
71 */
72typedef struct {
73 int ts_try_label; // instruction idx at TRY
74 endlabel_T *ts_end_label; // jump to :finally or :endtry
75 int ts_catch_label; // instruction idx of last CATCH
76 int ts_caught_all; // "catch" without argument encountered
77} tryscope_T;
78
79typedef enum {
80 NO_SCOPE,
81 IF_SCOPE,
82 WHILE_SCOPE,
83 FOR_SCOPE,
84 TRY_SCOPE,
85 BLOCK_SCOPE
86} scopetype_T;
87
88/*
89 * Info for one scope, pointed to by "ctx_scope".
90 */
91typedef struct scope_S scope_T;
92struct scope_S {
93 scope_T *se_outer; // scope containing this one
94 scopetype_T se_type;
95 int se_local_count; // ctx_locals.ga_len before scope
Bram Moolenaarefd88552020-06-18 20:50:10 +020096 skip_T se_skip_save; // ctx_skip before the block
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010097 union {
98 ifscope_T se_if;
99 whilescope_T se_while;
100 forscope_T se_for;
101 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +0100102 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100103};
104
105/*
106 * Entry for "ctx_locals". Used for arguments and local variables.
107 */
108typedef struct {
109 char_u *lv_name;
110 type_T *lv_type;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200111 int lv_idx; // index of the variable on the stack
Bram Moolenaarab360522021-01-10 14:02:28 +0100112 int lv_from_outer; // nesting level, using ctx_outer scope
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200113 int lv_const; // when TRUE cannot be assigned to
114 int lv_arg; // when TRUE this is an argument
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100115} lvar_T;
116
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +0200117// Destination for an assignment or ":unlet" with an index.
118typedef enum {
119 dest_local,
120 dest_option,
121 dest_env,
122 dest_global,
123 dest_buffer,
124 dest_window,
125 dest_tab,
126 dest_vimvar,
127 dest_script,
128 dest_reg,
129 dest_expr,
130} assign_dest_T;
131
132// Used by compile_lhs() to store information about the LHS of an assignment
133// and one argument of ":unlet" with an index.
134typedef struct {
135 assign_dest_T lhs_dest; // type of destination
136
137 char_u *lhs_name; // allocated name including
138 // "[expr]" or ".name".
139 size_t lhs_varlen; // length of the variable without
140 // "[expr]" or ".name"
141 char_u *lhs_dest_end; // end of the destination, including
142 // "[expr]" or ".name".
143
144 int lhs_has_index; // has "[expr]" or ".name"
145
146 int lhs_new_local; // create new local variable
147 int lhs_opt_flags; // for when destination is an option
148 int lhs_vimvaridx; // for when destination is a v:var
149
150 lvar_T lhs_local_lvar; // used for existing local destination
151 lvar_T lhs_arg_lvar; // used for argument destination
152 lvar_T *lhs_lvar; // points to destination lvar
153 int lhs_scriptvar_sid;
154 int lhs_scriptvar_idx;
155
156 int lhs_has_type; // type was specified
157 type_T *lhs_type;
158 type_T *lhs_member_type;
159
160 int lhs_append; // used by ISN_REDIREND
161} lhs_T;
162
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100163/*
164 * Context for compiling lines of Vim script.
165 * Stores info about the local variables and condition stack.
166 */
167struct cctx_S {
168 ufunc_T *ctx_ufunc; // current function
169 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200170 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100171 garray_T ctx_instr; // generated instructions
172
Bram Moolenaarb2049902021-01-24 12:53:53 +0100173 int ctx_profiling; // when TRUE generate ISN_PROF_START
174
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100175 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200176 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100177
Bram Moolenaar148ce7a2020-09-23 21:57:23 +0200178 int ctx_has_closure; // set to one if a closures was created in
179 // the function
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200180
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100181 garray_T ctx_imports; // imported items
182
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200183 skip_T ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100184 scope_T *ctx_scope; // current scope, NULL at toplevel
Bram Moolenaarefd88552020-06-18 20:50:10 +0200185 int ctx_had_return; // last seen statement was "return"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100186
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200187 cctx_T *ctx_outer; // outer scope for lambda or nested
188 // function
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200189 int ctx_outer_used; // var in ctx_outer was used
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200190
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100191 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200192 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +0200193
Bram Moolenaar02194d22020-10-24 23:08:38 +0200194 int ctx_has_cmdmod; // ISN_CMDMOD was generated
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +0200195
196 lhs_T ctx_redir_lhs; // LHS for ":redir => var", valid when
197 // lhs_name is not NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100198};
199
Bram Moolenaarcdc40c42020-12-26 17:43:08 +0100200static void delete_def_function_contents(dfunc_T *dfunc, int mark_deleted);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100201
202/*
Bram Moolenaar709664c2020-12-12 14:33:41 +0100203 * Lookup variable "name" in the local scope and return it in "lvar".
Bram Moolenaarab360522021-01-10 14:02:28 +0100204 * "lvar->lv_from_outer" is incremented accordingly.
Bram Moolenaar709664c2020-12-12 14:33:41 +0100205 * If "lvar" is NULL only check if the variable can be found.
206 * Return FAIL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100207 */
Bram Moolenaar709664c2020-12-12 14:33:41 +0100208 static int
209lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100210{
211 int idx;
Bram Moolenaar709664c2020-12-12 14:33:41 +0100212 lvar_T *lvp;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100213
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100214 if (len == 0)
Bram Moolenaar709664c2020-12-12 14:33:41 +0100215 return FAIL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200216
217 // Find local in current function scope.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100218 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
219 {
Bram Moolenaar709664c2020-12-12 14:33:41 +0100220 lvp = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
221 if (STRNCMP(name, lvp->lv_name, len) == 0
222 && STRLEN(lvp->lv_name) == len)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200223 {
Bram Moolenaar709664c2020-12-12 14:33:41 +0100224 if (lvar != NULL)
225 {
226 *lvar = *lvp;
Bram Moolenaarab360522021-01-10 14:02:28 +0100227 lvar->lv_from_outer = 0;
Bram Moolenaar709664c2020-12-12 14:33:41 +0100228 }
229 return OK;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200230 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100231 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200232
233 // Find local in outer function scope.
234 if (cctx->ctx_outer != NULL)
235 {
Bram Moolenaar709664c2020-12-12 14:33:41 +0100236 if (lookup_local(name, len, lvar, cctx->ctx_outer) == OK)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200237 {
Bram Moolenaar709664c2020-12-12 14:33:41 +0100238 if (lvar != NULL)
239 {
240 cctx->ctx_outer_used = TRUE;
Bram Moolenaarab360522021-01-10 14:02:28 +0100241 ++lvar->lv_from_outer;
Bram Moolenaar709664c2020-12-12 14:33:41 +0100242 }
243 return OK;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200244 }
245 }
246
Bram Moolenaar709664c2020-12-12 14:33:41 +0100247 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100248}
249
250/*
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200251 * Lookup an argument in the current function and an enclosing function.
252 * Returns the argument index in "idxp"
253 * Returns the argument type in "type"
254 * Sets "gen_load_outer" to TRUE if found in outer scope.
255 * Returns OK when found, FAIL otherwise.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100256 */
257 static int
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200258arg_exists(
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200259 char_u *name,
260 size_t len,
261 int *idxp,
262 type_T **type,
263 int *gen_load_outer,
264 cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100265{
266 int idx;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200267 char_u *va_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100268
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100269 if (len == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200270 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
272 {
273 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
274
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200275 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
276 {
277 if (idxp != NULL)
278 {
279 // Arguments are located above the frame pointer. One further
280 // if there is a vararg argument
281 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
282 + STACK_FRAME_SIZE)
283 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
284
285 if (cctx->ctx_ufunc->uf_arg_types != NULL)
286 *type = cctx->ctx_ufunc->uf_arg_types[idx];
287 else
288 *type = &t_any;
289 }
290 return OK;
291 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100292 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100293
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200294 va_name = cctx->ctx_ufunc->uf_va_name;
295 if (va_name != NULL
296 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
297 {
298 if (idxp != NULL)
299 {
300 // varargs is always the last argument
301 *idxp = -STACK_FRAME_SIZE - 1;
302 *type = cctx->ctx_ufunc->uf_va_type;
303 }
304 return OK;
305 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100306
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200307 if (cctx->ctx_outer != NULL)
308 {
309 // Lookup the name for an argument of the outer function.
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200310 if (arg_exists(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200311 == OK)
312 {
Bram Moolenaar44ec21c2021-02-12 21:50:57 +0100313 if (gen_load_outer != NULL)
314 ++*gen_load_outer;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200315 return OK;
316 }
317 }
318
319 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100320}
321
322/*
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200323 * Lookup a script-local variable in the current script, possibly defined in a
324 * block that contains the function "cctx->ctx_ufunc".
325 * "cctx" is NULL at the script level.
Bram Moolenaar18062fc2021-03-05 21:35:47 +0100326 * If "len" is <= 0 "name" must be NUL terminated.
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200327 * Return NULL when not found.
328 */
329 static sallvar_T *
330find_script_var(char_u *name, size_t len, cctx_T *cctx)
331{
332 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
333 hashitem_T *hi;
334 int cc;
335 sallvar_T *sav;
336 ufunc_T *ufunc;
337
338 // Find the list of all script variables with the right name.
339 if (len > 0)
340 {
341 cc = name[len];
342 name[len] = NUL;
343 }
344 hi = hash_find(&si->sn_all_vars.dv_hashtab, name);
345 if (len > 0)
346 name[len] = cc;
347 if (HASHITEM_EMPTY(hi))
348 return NULL;
349
350 sav = HI2SAV(hi);
351 if (sav->sav_block_id == 0 || cctx == NULL)
352 // variable defined in the script scope or not in a function.
353 return sav;
354
355 // Go over the variables with this name and find one that was visible
356 // from the function.
357 ufunc = cctx->ctx_ufunc;
358 while (sav != NULL)
359 {
360 int idx;
361
362 // Go over the blocks that this function was defined in. If the
363 // variable block ID matches it was visible to the function.
364 for (idx = 0; idx < ufunc->uf_block_depth; ++idx)
365 if (ufunc->uf_block_ids[idx] == sav->sav_block_id)
366 return sav;
367 sav = sav->sav_next;
368 }
369
370 return NULL;
371}
372
373/*
Bram Moolenaar8e7d6222020-12-18 19:49:56 +0100374 * Return TRUE if the script context is Vim9 script.
Bram Moolenaar84367732020-08-23 15:21:55 +0200375 */
376 static int
377script_is_vim9()
378{
379 return SCRIPT_ITEM(current_sctx.sc_sid)->sn_version == SCRIPT_VERSION_VIM9;
380}
381
382/*
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200383 * Lookup a variable (without s: prefix) in the current script.
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200384 * "cctx" is NULL at the script level.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100385 * Returns OK or FAIL.
386 */
Bram Moolenaar15e5e532021-04-07 21:21:13 +0200387 static int
388script_var_exists(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100389{
Bram Moolenaar9c4f5522020-09-25 21:47:28 +0200390 if (current_sctx.sc_sid <= 0)
391 return FAIL;
Bram Moolenaar15e5e532021-04-07 21:21:13 +0200392 if (script_is_vim9())
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200393 {
394 // Check script variables that were visible where the function was
395 // defined.
396 if (find_script_var(name, len, cctx) != NULL)
397 return OK;
398 }
399 else
400 {
401 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
402 dictitem_T *di;
403 int cc;
404
405 // Check script variables that are currently visible
406 cc = name[len];
407 name[len] = NUL;
408 di = find_var_in_ht(ht, 0, name, TRUE);
409 name[len] = cc;
410 if (di != NULL)
411 return OK;
412 }
413
414 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100415}
416
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100417/*
Bram Moolenaare0890d62021-02-17 14:52:14 +0100418 * Return TRUE if "name" is a local variable, argument, script variable or
419 * imported.
420 */
421 static int
422variable_exists(char_u *name, size_t len, cctx_T *cctx)
423{
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100424 return (cctx != NULL
425 && (lookup_local(name, len, NULL, cctx) == OK
426 || arg_exists(name, len, NULL, NULL, NULL, cctx) == OK))
Bram Moolenaar15e5e532021-04-07 21:21:13 +0200427 || script_var_exists(name, len, cctx) == OK
Bram Moolenaare0890d62021-02-17 14:52:14 +0100428 || find_imported(name, len, cctx) != NULL;
429}
430
431/*
Bram Moolenaar6914e872021-03-06 21:01:09 +0100432 * Return TRUE if "name" is a local variable, argument, script variable,
433 * imported or function.
434 */
435 static int
Bram Moolenaar77b10ff2021-03-14 13:21:35 +0100436item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx)
Bram Moolenaar6914e872021-03-06 21:01:09 +0100437{
438 int is_global;
Bram Moolenaar77b10ff2021-03-14 13:21:35 +0100439 char_u *p;
Bram Moolenaar6914e872021-03-06 21:01:09 +0100440
441 if (variable_exists(name, len, cctx))
442 return TRUE;
443
Bram Moolenaar77b10ff2021-03-14 13:21:35 +0100444 // This is similar to what is in lookup_scriptitem():
445 // Find a function, so that a following "->" works.
446 // Require "(" or "->" to follow, "Cmd" is a user command while "Cmd()" is
447 // a function call.
448 p = skipwhite(name + len);
449
450 if (name[len] == '(' || (p[0] == '-' && p[1] == '>'))
451 {
452 // Do not check for an internal function, since it might also be a
453 // valid command, such as ":split" versuse "split()".
454 // Skip "g:" before a function name.
455 is_global = (name[0] == 'g' && name[1] == ':');
456 return find_func(is_global ? name + 2 : name, is_global, cctx) != NULL;
457 }
458 return FALSE;
Bram Moolenaar6914e872021-03-06 21:01:09 +0100459}
460
461/*
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100462 * Check if "p[len]" is already defined, either in script "import_sid" or in
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200463 * compilation context "cctx". "cctx" is NULL at the script level.
Bram Moolenaar0f769812020-09-12 18:32:34 +0200464 * Does not check the global namespace.
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100465 * If "is_arg" is TRUE the error message is for an argument name.
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100466 * Return FAIL and give an error if it defined.
467 */
468 int
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100469check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100470{
Bram Moolenaar0f769812020-09-12 18:32:34 +0200471 int c = p[len];
472 ufunc_T *ufunc = NULL;
Bram Moolenaarad486a02020-08-01 23:22:18 +0200473
Bram Moolenaarda479c72021-04-10 21:01:38 +0200474 // underscore argument is OK
475 if (len == 1 && *p == '_')
476 return OK;
477
Bram Moolenaar15e5e532021-04-07 21:21:13 +0200478 if (script_var_exists(p, len, cctx) == OK)
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100479 {
480 if (is_arg)
481 semsg(_(e_argument_already_declared_in_script_str), p);
482 else
483 semsg(_(e_variable_already_declared_in_script_str), p);
484 return FAIL;
485 }
486
Bram Moolenaarad486a02020-08-01 23:22:18 +0200487 p[len] = NUL;
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100488 if ((cctx != NULL
Bram Moolenaar709664c2020-12-12 14:33:41 +0100489 && (lookup_local(p, len, NULL, cctx) == OK
Bram Moolenaarfbbcd002020-10-15 12:46:44 +0200490 || arg_exists(p, len, NULL, NULL, NULL, cctx) == OK))
Bram Moolenaarad486a02020-08-01 23:22:18 +0200491 || find_imported(p, len, cctx) != NULL
Bram Moolenaar0f769812020-09-12 18:32:34 +0200492 || (ufunc = find_func_even_dead(p, FALSE, cctx)) != NULL)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100493 {
Bram Moolenaar0f769812020-09-12 18:32:34 +0200494 // A local or script-local function can shadow a global function.
495 if (ufunc == NULL || !func_is_global(ufunc)
496 || (p[0] == 'g' && p[1] == ':'))
497 {
Bram Moolenaar057e84a2021-02-28 16:55:11 +0100498 if (is_arg)
499 semsg(_(e_argument_name_shadows_existing_variable_str), p);
500 else
501 semsg(_(e_name_already_defined_str), p);
Bram Moolenaar0f769812020-09-12 18:32:34 +0200502 p[len] = c;
Bram Moolenaar0f769812020-09-12 18:32:34 +0200503 return FAIL;
504 }
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100505 }
Bram Moolenaarad486a02020-08-01 23:22:18 +0200506 p[len] = c;
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100507 return OK;
508}
509
Bram Moolenaar65b95452020-07-19 14:03:09 +0200510
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100511/////////////////////////////////////////////////////////////////////
512// Following generate_ functions expect the caller to call ga_grow().
513
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200514#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return NULL
515#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return OK
Bram Moolenaar080457c2020-03-03 21:53:32 +0100516
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100517/*
518 * Generate an instruction without arguments.
519 * Returns a pointer to the new instruction, NULL if failed.
520 */
521 static isn_T *
522generate_instr(cctx_T *cctx, isntype_T isn_type)
523{
524 garray_T *instr = &cctx->ctx_instr;
525 isn_T *isn;
526
Bram Moolenaar080457c2020-03-03 21:53:32 +0100527 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100528 if (ga_grow(instr, 1) == FAIL)
529 return NULL;
530 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
531 isn->isn_type = isn_type;
532 isn->isn_lnum = cctx->ctx_lnum + 1;
533 ++instr->ga_len;
534
535 return isn;
536}
537
538/*
539 * Generate an instruction without arguments.
540 * "drop" will be removed from the stack.
541 * Returns a pointer to the new instruction, NULL if failed.
542 */
543 static isn_T *
544generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
545{
546 garray_T *stack = &cctx->ctx_type_stack;
547
Bram Moolenaar080457c2020-03-03 21:53:32 +0100548 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100549 stack->ga_len -= drop;
550 return generate_instr(cctx, isn_type);
551}
552
553/*
554 * Generate instruction "isn_type" and put "type" on the type stack.
555 */
556 static isn_T *
557generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
558{
559 isn_T *isn;
560 garray_T *stack = &cctx->ctx_type_stack;
561
562 if ((isn = generate_instr(cctx, isn_type)) == NULL)
563 return NULL;
564
565 if (ga_grow(stack, 1) == FAIL)
566 return NULL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +0200567 ((type_T **)stack->ga_data)[stack->ga_len] = type == NULL ? &t_any : type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100568 ++stack->ga_len;
569
570 return isn;
571}
572
573/*
574 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200575 * But only for simple types.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100576 */
577 static int
578may_generate_2STRING(int offset, cctx_T *cctx)
579{
580 isn_T *isn;
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200581 isntype_T isntype = ISN_2STRING;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100582 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar9e1d9e32021-01-11 20:17:34 +0100583 type_T **type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100584
Bram Moolenaar9e1d9e32021-01-11 20:17:34 +0100585 RETURN_OK_IF_SKIP(cctx);
586 type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200587 switch ((*type)->tt_type)
588 {
589 // nothing to be done
590 case VAR_STRING: return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100591
Bram Moolenaar418f1df2020-08-12 21:34:49 +0200592 // conversion possible
593 case VAR_SPECIAL:
594 case VAR_BOOL:
595 case VAR_NUMBER:
596 case VAR_FLOAT:
597 break;
598
599 // conversion possible (with runtime check)
600 case VAR_ANY:
601 case VAR_UNKNOWN:
602 isntype = ISN_2STRING_ANY;
603 break;
604
605 // conversion not possible
606 case VAR_VOID:
607 case VAR_BLOB:
608 case VAR_FUNC:
609 case VAR_PARTIAL:
610 case VAR_LIST:
611 case VAR_DICT:
612 case VAR_JOB:
613 case VAR_CHANNEL:
614 to_string_error((*type)->tt_type);
615 return FAIL;
616 }
617
618 *type = &t_string;
619 if ((isn = generate_instr(cctx, isntype)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100620 return FAIL;
621 isn->isn_arg.number = offset;
622
623 return OK;
624}
625
626 static int
627check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
628{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200629 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100630 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200631 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100632 {
633 if (*op == '+')
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200634 emsg(_(e_wrong_argument_type_for_plus));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100635 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200636 semsg(_(e_char_requires_number_or_float_arguments), *op);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100637 return FAIL;
638 }
639 return OK;
640}
641
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200642 static int
643generate_add_instr(
644 cctx_T *cctx,
645 vartype_T vartype,
646 type_T *type1,
647 type_T *type2)
648{
Bram Moolenaar399ea812020-12-15 21:28:57 +0100649 garray_T *stack = &cctx->ctx_type_stack;
650 isn_T *isn = generate_instr_drop(cctx,
651 vartype == VAR_NUMBER ? ISN_OPNR
652 : vartype == VAR_LIST ? ISN_ADDLIST
653 : vartype == VAR_BLOB ? ISN_ADDBLOB
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200654#ifdef FEAT_FLOAT
Bram Moolenaar399ea812020-12-15 21:28:57 +0100655 : vartype == VAR_FLOAT ? ISN_OPFLOAT
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200656#endif
Bram Moolenaar399ea812020-12-15 21:28:57 +0100657 : ISN_OPANY, 1);
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200658
659 if (vartype != VAR_LIST && vartype != VAR_BLOB
660 && type1->tt_type != VAR_ANY
661 && type2->tt_type != VAR_ANY
662 && check_number_or_float(
663 type1->tt_type, type2->tt_type, (char_u *)"+") == FAIL)
664 return FAIL;
665
666 if (isn != NULL)
667 isn->isn_arg.op.op_type = EXPR_ADD;
Bram Moolenaar399ea812020-12-15 21:28:57 +0100668
669 // When concatenating two lists with different member types the member type
670 // becomes "any".
671 if (vartype == VAR_LIST
672 && type1->tt_type == VAR_LIST && type2->tt_type == VAR_LIST
673 && type1->tt_member != type2->tt_member)
674 (((type_T **)stack->ga_data)[stack->ga_len - 1]) = &t_list_any;
675
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200676 return isn == NULL ? FAIL : OK;
677}
678
679/*
680 * Get the type to use for an instruction for an operation on "type1" and
681 * "type2". If they are matching use a type-specific instruction. Otherwise
682 * fall back to runtime type checking.
683 */
684 static vartype_T
685operator_type(type_T *type1, type_T *type2)
686{
687 if (type1->tt_type == type2->tt_type
688 && (type1->tt_type == VAR_NUMBER
689 || type1->tt_type == VAR_LIST
690#ifdef FEAT_FLOAT
691 || type1->tt_type == VAR_FLOAT
692#endif
693 || type1->tt_type == VAR_BLOB))
694 return type1->tt_type;
695 return VAR_ANY;
696}
697
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100698/*
699 * Generate an instruction with two arguments. The instruction depends on the
700 * type of the arguments.
701 */
702 static int
703generate_two_op(cctx_T *cctx, char_u *op)
704{
705 garray_T *stack = &cctx->ctx_type_stack;
706 type_T *type1;
707 type_T *type2;
708 vartype_T vartype;
709 isn_T *isn;
710
Bram Moolenaar080457c2020-03-03 21:53:32 +0100711 RETURN_OK_IF_SKIP(cctx);
712
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200713 // Get the known type of the two items on the stack.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100714 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
715 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200716 vartype = operator_type(type1, type2);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100717
718 switch (*op)
719 {
Bram Moolenaardd29f1b2020-08-07 20:46:20 +0200720 case '+':
721 if (generate_add_instr(cctx, vartype, type1, type2) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100722 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100723 break;
724
725 case '-':
726 case '*':
727 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
728 op) == FAIL)
729 return FAIL;
730 if (vartype == VAR_NUMBER)
731 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
732#ifdef FEAT_FLOAT
733 else if (vartype == VAR_FLOAT)
734 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
735#endif
736 else
737 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
738 if (isn != NULL)
739 isn->isn_arg.op.op_type = *op == '*'
740 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
741 break;
742
Bram Moolenaar4c683752020-04-05 21:38:23 +0200743 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100744 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200745 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100746 && type2->tt_type != VAR_NUMBER))
747 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200748 emsg(_(e_percent_requires_number_arguments));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100749 return FAIL;
750 }
751 isn = generate_instr_drop(cctx,
752 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
753 if (isn != NULL)
754 isn->isn_arg.op.op_type = EXPR_REM;
755 break;
756 }
757
758 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200759 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100760 {
761 type_T *type = &t_any;
762
763#ifdef FEAT_FLOAT
764 // float+number and number+float results in float
765 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
766 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
767 type = &t_float;
768#endif
769 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
770 }
771
772 return OK;
773}
774
775/*
Bram Moolenaara5565e42020-05-09 15:44:01 +0200776 * Get the instruction to use for comparing "type1" with "type2"
777 * Return ISN_DROP when failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100778 */
Bram Moolenaara5565e42020-05-09 15:44:01 +0200779 static isntype_T
Bram Moolenaar657137c2021-01-09 15:45:23 +0100780get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100781{
782 isntype_T isntype = ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100783
Bram Moolenaar4c683752020-04-05 21:38:23 +0200784 if (type1 == VAR_UNKNOWN)
785 type1 = VAR_ANY;
786 if (type2 == VAR_UNKNOWN)
787 type2 = VAR_ANY;
788
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100789 if (type1 == type2)
790 {
791 switch (type1)
792 {
793 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
794 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
795 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
796 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
797 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
798 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
799 case VAR_LIST: isntype = ISN_COMPARELIST; break;
800 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
801 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100802 default: isntype = ISN_COMPAREANY; break;
803 }
804 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200805 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100806 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
Bram Moolenaar6914e872021-03-06 21:01:09 +0100807 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100808 isntype = ISN_COMPAREANY;
809
Bram Moolenaar657137c2021-01-09 15:45:23 +0100810 if ((exprtype == EXPR_IS || exprtype == EXPR_ISNOT)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100811 && (isntype == ISN_COMPAREBOOL
812 || isntype == ISN_COMPARESPECIAL
813 || isntype == ISN_COMPARENR
814 || isntype == ISN_COMPAREFLOAT))
815 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200816 semsg(_(e_cannot_use_str_with_str),
Bram Moolenaar657137c2021-01-09 15:45:23 +0100817 exprtype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200818 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100819 }
820 if (isntype == ISN_DROP
Bram Moolenaar657137c2021-01-09 15:45:23 +0100821 || ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100822 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
823 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
Bram Moolenaar657137c2021-01-09 15:45:23 +0100824 || ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
825 && exprtype != EXPR_IS && exprtype != EXPR_ISNOT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100826 && (type1 == VAR_BLOB || type2 == VAR_BLOB
827 || type1 == VAR_LIST || type2 == VAR_LIST))))
828 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +0200829 semsg(_(e_cannot_compare_str_with_str),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100830 vartype_name(type1), vartype_name(type2));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200831 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100832 }
Bram Moolenaara5565e42020-05-09 15:44:01 +0200833 return isntype;
834}
835
Bram Moolenaar543e6f32020-07-10 22:45:38 +0200836 int
Bram Moolenaar657137c2021-01-09 15:45:23 +0100837check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2)
Bram Moolenaar543e6f32020-07-10 22:45:38 +0200838{
839 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
840 return FAIL;
841 return OK;
842}
843
Bram Moolenaara5565e42020-05-09 15:44:01 +0200844/*
845 * Generate an ISN_COMPARE* instruction with a boolean result.
846 */
847 static int
Bram Moolenaar657137c2021-01-09 15:45:23 +0100848generate_COMPARE(cctx_T *cctx, exprtype_T exprtype, int ic)
Bram Moolenaara5565e42020-05-09 15:44:01 +0200849{
850 isntype_T isntype;
851 isn_T *isn;
852 garray_T *stack = &cctx->ctx_type_stack;
853 vartype_T type1;
854 vartype_T type2;
855
856 RETURN_OK_IF_SKIP(cctx);
857
858 // Get the known type of the two items on the stack. If they are matching
859 // use a type-specific instruction. Otherwise fall back to runtime type
860 // checking.
861 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
862 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar657137c2021-01-09 15:45:23 +0100863 isntype = get_compare_isn(exprtype, type1, type2);
Bram Moolenaara5565e42020-05-09 15:44:01 +0200864 if (isntype == ISN_DROP)
865 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100866
867 if ((isn = generate_instr(cctx, isntype)) == NULL)
868 return FAIL;
Bram Moolenaar657137c2021-01-09 15:45:23 +0100869 isn->isn_arg.op.op_type = exprtype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100870 isn->isn_arg.op.op_ic = ic;
871
872 // takes two arguments, puts one bool back
873 if (stack->ga_len >= 2)
874 {
875 --stack->ga_len;
876 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
877 }
878
879 return OK;
880}
881
882/*
883 * Generate an ISN_2BOOL instruction.
884 */
885 static int
886generate_2BOOL(cctx_T *cctx, int invert)
887{
888 isn_T *isn;
889 garray_T *stack = &cctx->ctx_type_stack;
890
Bram Moolenaar080457c2020-03-03 21:53:32 +0100891 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100892 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
893 return FAIL;
894 isn->isn_arg.number = invert;
895
896 // type becomes bool
897 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
898
899 return OK;
900}
901
Bram Moolenaar2bb26582020-10-03 22:52:39 +0200902/*
903 * Generate an ISN_COND2BOOL instruction.
904 */
905 static int
906generate_COND2BOOL(cctx_T *cctx)
907{
908 isn_T *isn;
909 garray_T *stack = &cctx->ctx_type_stack;
910
911 RETURN_OK_IF_SKIP(cctx);
912 if ((isn = generate_instr(cctx, ISN_COND2BOOL)) == NULL)
913 return FAIL;
914
915 // type becomes bool
916 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
917
918 return OK;
919}
920
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100921 static int
Bram Moolenaar5e654232020-09-16 15:22:00 +0200922generate_TYPECHECK(
923 cctx_T *cctx,
924 type_T *expected,
Bram Moolenaare32e5162021-01-21 20:21:29 +0100925 int offset,
926 int argidx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100927{
928 isn_T *isn;
929 garray_T *stack = &cctx->ctx_type_stack;
930
Bram Moolenaar080457c2020-03-03 21:53:32 +0100931 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100932 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
933 return FAIL;
Bram Moolenaar5e654232020-09-16 15:22:00 +0200934 isn->isn_arg.type.ct_type = alloc_type(expected);
Bram Moolenaarb3005ce2021-01-22 17:51:06 +0100935 isn->isn_arg.type.ct_off = (int8_T)offset;
936 isn->isn_arg.type.ct_arg_idx = (int8_T)argidx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100937
Bram Moolenaar5e654232020-09-16 15:22:00 +0200938 // type becomes expected
939 ((type_T **)stack->ga_data)[stack->ga_len + offset] = expected;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100940
941 return OK;
942}
943
Bram Moolenaaraa210a32021-01-02 15:41:03 +0100944 static int
945generate_SETTYPE(
946 cctx_T *cctx,
947 type_T *expected)
948{
949 isn_T *isn;
950
951 RETURN_OK_IF_SKIP(cctx);
952 if ((isn = generate_instr(cctx, ISN_SETTYPE)) == NULL)
953 return FAIL;
954 isn->isn_arg.type.ct_type = alloc_type(expected);
955 return OK;
956}
957
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100958/*
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200959 * Return TRUE if "actual" could be "expected" and a runtime typecheck is to be
960 * used. Return FALSE if the types will never match.
961 */
Bram Moolenaar193f6202020-11-16 20:08:35 +0100962 int
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200963use_typecheck(type_T *actual, type_T *expected)
964{
965 if (actual->tt_type == VAR_ANY
966 || actual->tt_type == VAR_UNKNOWN
967 || (actual->tt_type == VAR_FUNC
968 && (expected->tt_type == VAR_FUNC
969 || expected->tt_type == VAR_PARTIAL)
Bram Moolenaar328eac22021-01-07 19:23:08 +0100970 && (actual->tt_member == &t_any || actual->tt_argcount < 0)
971 && ((actual->tt_member == &t_void)
972 == (expected->tt_member == &t_void))))
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200973 return TRUE;
974 if ((actual->tt_type == VAR_LIST || actual->tt_type == VAR_DICT)
975 && actual->tt_type == expected->tt_type)
976 // This takes care of a nested list or dict.
977 return use_typecheck(actual->tt_member, expected->tt_member);
978 return FALSE;
979}
980
981/*
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200982 * Check that
Bram Moolenaar5e654232020-09-16 15:22:00 +0200983 * - "actual" matches "expected" type or
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200984 * - "actual" is a type that can be "expected" type: add a runtime check; or
985 * - return FAIL.
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200986 * If "actual_is_const" is TRUE then the type won't change at runtime, do not
987 * generate a TYPECHECK.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200988 */
Bram Moolenaar351ead02021-01-16 16:07:01 +0100989 int
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200990need_type(
991 type_T *actual,
992 type_T *expected,
993 int offset,
Bram Moolenaar351ead02021-01-16 16:07:01 +0100994 int arg_idx,
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +0200995 cctx_T *cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +0200996 int silent,
997 int actual_is_const)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200998{
Bram Moolenaarf785aa12021-02-11 21:19:34 +0100999 where_T where;
1000
Bram Moolenaar4ed124c2020-09-09 20:03:46 +02001001 if (expected == &t_bool && actual != &t_bool
1002 && (actual->tt_flags & TTFLAG_BOOL_OK))
1003 {
1004 // Using "0", "1" or the result of an expression with "&&" or "||" as a
1005 // boolean is OK but requires a conversion.
1006 generate_2BOOL(cctx, FALSE);
1007 return OK;
1008 }
1009
Bram Moolenaarf785aa12021-02-11 21:19:34 +01001010 where.wt_index = arg_idx;
1011 where.wt_variable = FALSE;
1012 if (check_type(expected, actual, FALSE, where) == OK)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001013 return OK;
Bram Moolenaar5e654232020-09-16 15:22:00 +02001014
1015 // If the actual type can be the expected type add a runtime check.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02001016 // If it's a constant a runtime check makes no sense.
1017 if (!actual_is_const && use_typecheck(actual, expected))
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001018 {
Bram Moolenaare32e5162021-01-21 20:21:29 +01001019 generate_TYPECHECK(cctx, expected, offset, arg_idx);
Bram Moolenaar5e654232020-09-16 15:22:00 +02001020 return OK;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001021 }
Bram Moolenaar5e654232020-09-16 15:22:00 +02001022
1023 if (!silent)
Bram Moolenaar351ead02021-01-16 16:07:01 +01001024 arg_type_mismatch(expected, actual, arg_idx);
Bram Moolenaar5e654232020-09-16 15:22:00 +02001025 return FAIL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001026}
1027
1028/*
Bram Moolenaarea2d4072020-11-12 12:08:51 +01001029 * Check that the top of the type stack has a type that can be used as a
1030 * condition. Give an error and return FAIL if not.
1031 */
1032 static int
1033bool_on_stack(cctx_T *cctx)
1034{
1035 garray_T *stack = &cctx->ctx_type_stack;
1036 type_T *type;
1037
1038 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
1039 if (type == &t_bool)
1040 return OK;
1041
Bram Moolenaaraf8ea0d2021-04-11 18:24:46 +02001042 if (type == &t_any || type == &t_number || type == &t_number_bool)
Bram Moolenaarea2d4072020-11-12 12:08:51 +01001043 // Number 0 and 1 are OK to use as a bool. "any" could also be a bool.
1044 // This requires a runtime type check.
1045 return generate_COND2BOOL(cctx);
1046
Bram Moolenaar351ead02021-01-16 16:07:01 +01001047 return need_type(type, &t_bool, -1, 0, cctx, FALSE, FALSE);
Bram Moolenaarea2d4072020-11-12 12:08:51 +01001048}
1049
1050/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001051 * Generate an ISN_PUSHNR instruction.
1052 */
1053 static int
1054generate_PUSHNR(cctx_T *cctx, varnumber_T number)
1055{
1056 isn_T *isn;
Bram Moolenaar29a86ff2020-09-09 14:55:31 +02001057 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001058
Bram Moolenaar080457c2020-03-03 21:53:32 +01001059 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001060 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
1061 return FAIL;
1062 isn->isn_arg.number = number;
1063
Bram Moolenaar29a86ff2020-09-09 14:55:31 +02001064 if (number == 0 || number == 1)
Bram Moolenaar29a86ff2020-09-09 14:55:31 +02001065 // A 0 or 1 number can also be used as a bool.
Bram Moolenaar3868f592020-12-25 13:20:41 +01001066 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_number_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001067 return OK;
1068}
1069
1070/*
1071 * Generate an ISN_PUSHBOOL instruction.
1072 */
1073 static int
1074generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
1075{
1076 isn_T *isn;
1077
Bram Moolenaar080457c2020-03-03 21:53:32 +01001078 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001079 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
1080 return FAIL;
1081 isn->isn_arg.number = number;
1082
1083 return OK;
1084}
1085
1086/*
1087 * Generate an ISN_PUSHSPEC instruction.
1088 */
1089 static int
1090generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
1091{
1092 isn_T *isn;
1093
Bram Moolenaar080457c2020-03-03 21:53:32 +01001094 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001095 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
1096 return FAIL;
1097 isn->isn_arg.number = number;
1098
1099 return OK;
1100}
1101
1102#ifdef FEAT_FLOAT
1103/*
1104 * Generate an ISN_PUSHF instruction.
1105 */
1106 static int
1107generate_PUSHF(cctx_T *cctx, float_T fnumber)
1108{
1109 isn_T *isn;
1110
Bram Moolenaar080457c2020-03-03 21:53:32 +01001111 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001112 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
1113 return FAIL;
1114 isn->isn_arg.fnumber = fnumber;
1115
1116 return OK;
1117}
1118#endif
1119
1120/*
1121 * Generate an ISN_PUSHS instruction.
1122 * Consumes "str".
1123 */
1124 static int
1125generate_PUSHS(cctx_T *cctx, char_u *str)
1126{
1127 isn_T *isn;
1128
Bram Moolenaar508b5612021-01-02 18:17:26 +01001129 if (cctx->ctx_skip == SKIP_YES)
1130 {
1131 vim_free(str);
1132 return OK;
1133 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001134 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
1135 return FAIL;
1136 isn->isn_arg.string = str;
1137
1138 return OK;
1139}
1140
1141/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001142 * Generate an ISN_PUSHCHANNEL instruction.
1143 * Consumes "channel".
1144 */
1145 static int
1146generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
1147{
1148 isn_T *isn;
1149
Bram Moolenaar080457c2020-03-03 21:53:32 +01001150 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001151 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
1152 return FAIL;
1153 isn->isn_arg.channel = channel;
1154
1155 return OK;
1156}
1157
1158/*
1159 * Generate an ISN_PUSHJOB instruction.
1160 * Consumes "job".
1161 */
1162 static int
1163generate_PUSHJOB(cctx_T *cctx, job_T *job)
1164{
1165 isn_T *isn;
1166
Bram Moolenaar080457c2020-03-03 21:53:32 +01001167 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001168 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001169 return FAIL;
1170 isn->isn_arg.job = job;
1171
1172 return OK;
1173}
1174
1175/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001176 * Generate an ISN_PUSHBLOB instruction.
1177 * Consumes "blob".
1178 */
1179 static int
1180generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
1181{
1182 isn_T *isn;
1183
Bram Moolenaar080457c2020-03-03 21:53:32 +01001184 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001185 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
1186 return FAIL;
1187 isn->isn_arg.blob = blob;
1188
1189 return OK;
1190}
1191
1192/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001193 * Generate an ISN_PUSHFUNC instruction with name "name".
1194 * Consumes "name".
1195 */
1196 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001197generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001198{
1199 isn_T *isn;
1200
Bram Moolenaar080457c2020-03-03 21:53:32 +01001201 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001202 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001203 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02001204 isn->isn_arg.string = name == NULL ? NULL : vim_strsave(name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001205
1206 return OK;
1207}
1208
1209/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001210 * Generate an ISN_GETITEM instruction with "index".
1211 */
1212 static int
1213generate_GETITEM(cctx_T *cctx, int index)
1214{
1215 isn_T *isn;
1216 garray_T *stack = &cctx->ctx_type_stack;
1217 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
1218 type_T *item_type = &t_any;
1219
1220 RETURN_OK_IF_SKIP(cctx);
1221
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001222 if (type->tt_type != VAR_LIST)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001223 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001224 // cannot happen, caller has checked the type
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001225 emsg(_(e_listreq));
1226 return FAIL;
1227 }
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001228 item_type = type->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001229 if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
1230 return FAIL;
1231 isn->isn_arg.number = index;
1232
1233 // add the item type to the type stack
1234 if (ga_grow(stack, 1) == FAIL)
1235 return FAIL;
1236 ((type_T **)stack->ga_data)[stack->ga_len] = item_type;
1237 ++stack->ga_len;
1238 return OK;
1239}
1240
1241/*
Bram Moolenaar9af78762020-06-16 11:34:42 +02001242 * Generate an ISN_SLICE instruction with "count".
1243 */
1244 static int
1245generate_SLICE(cctx_T *cctx, int count)
1246{
1247 isn_T *isn;
1248
1249 RETURN_OK_IF_SKIP(cctx);
1250 if ((isn = generate_instr(cctx, ISN_SLICE)) == NULL)
1251 return FAIL;
1252 isn->isn_arg.number = count;
1253 return OK;
1254}
1255
1256/*
1257 * Generate an ISN_CHECKLEN instruction with "min_len".
1258 */
1259 static int
1260generate_CHECKLEN(cctx_T *cctx, int min_len, int more_OK)
1261{
1262 isn_T *isn;
1263
1264 RETURN_OK_IF_SKIP(cctx);
1265
1266 if ((isn = generate_instr(cctx, ISN_CHECKLEN)) == NULL)
1267 return FAIL;
1268 isn->isn_arg.checklen.cl_min_len = min_len;
1269 isn->isn_arg.checklen.cl_more_OK = more_OK;
1270
1271 return OK;
1272}
1273
1274/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001275 * Generate an ISN_STORE instruction.
1276 */
1277 static int
1278generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
1279{
1280 isn_T *isn;
1281
Bram Moolenaar080457c2020-03-03 21:53:32 +01001282 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001283 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
1284 return FAIL;
1285 if (name != NULL)
1286 isn->isn_arg.string = vim_strsave(name);
1287 else
1288 isn->isn_arg.number = idx;
1289
1290 return OK;
1291}
1292
1293/*
Bram Moolenaarab360522021-01-10 14:02:28 +01001294 * Generate an ISN_STOREOUTER instruction.
1295 */
1296 static int
1297generate_STOREOUTER(cctx_T *cctx, int idx, int level)
1298{
1299 isn_T *isn;
1300
1301 RETURN_OK_IF_SKIP(cctx);
1302 if ((isn = generate_instr_drop(cctx, ISN_STOREOUTER, 1)) == NULL)
1303 return FAIL;
1304 isn->isn_arg.outer.outer_idx = idx;
1305 isn->isn_arg.outer.outer_depth = level;
1306
1307 return OK;
1308}
1309
1310/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001311 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
1312 */
1313 static int
1314generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
1315{
1316 isn_T *isn;
1317
Bram Moolenaar080457c2020-03-03 21:53:32 +01001318 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001319 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
1320 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +01001321 isn->isn_arg.storenr.stnr_idx = idx;
1322 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001323
1324 return OK;
1325}
1326
1327/*
1328 * Generate an ISN_STOREOPT instruction
1329 */
1330 static int
1331generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
1332{
1333 isn_T *isn;
1334
Bram Moolenaar080457c2020-03-03 21:53:32 +01001335 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1c199f92020-08-07 21:28:34 +02001336 if ((isn = generate_instr_drop(cctx, ISN_STOREOPT, 1)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001337 return FAIL;
1338 isn->isn_arg.storeopt.so_name = vim_strsave(name);
1339 isn->isn_arg.storeopt.so_flags = opt_flags;
1340
1341 return OK;
1342}
1343
1344/*
1345 * Generate an ISN_LOAD or similar instruction.
1346 */
1347 static int
1348generate_LOAD(
1349 cctx_T *cctx,
1350 isntype_T isn_type,
1351 int idx,
1352 char_u *name,
1353 type_T *type)
1354{
1355 isn_T *isn;
1356
Bram Moolenaar080457c2020-03-03 21:53:32 +01001357 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001358 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
1359 return FAIL;
1360 if (name != NULL)
1361 isn->isn_arg.string = vim_strsave(name);
1362 else
1363 isn->isn_arg.number = idx;
1364
1365 return OK;
1366}
1367
1368/*
Bram Moolenaarab360522021-01-10 14:02:28 +01001369 * Generate an ISN_LOADOUTER instruction
1370 */
1371 static int
1372generate_LOADOUTER(
1373 cctx_T *cctx,
1374 int idx,
1375 int nesting,
1376 type_T *type)
1377{
1378 isn_T *isn;
1379
1380 RETURN_OK_IF_SKIP(cctx);
1381 if ((isn = generate_instr_type(cctx, ISN_LOADOUTER, type)) == NULL)
1382 return FAIL;
1383 isn->isn_arg.outer.outer_idx = idx;
1384 isn->isn_arg.outer.outer_depth = nesting;
1385
1386 return OK;
1387}
1388
1389/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001390 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001391 */
1392 static int
1393generate_LOADV(
1394 cctx_T *cctx,
1395 char_u *name,
1396 int error)
1397{
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001398 int di_flags;
1399 int vidx = find_vim_var(name, &di_flags);
1400 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001401
Bram Moolenaar080457c2020-03-03 21:53:32 +01001402 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001403 if (vidx < 0)
1404 {
1405 if (error)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02001406 semsg(_(e_variable_not_found_str), name);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001407 return FAIL;
1408 }
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02001409 type = typval2type_vimvar(get_vim_var_tv(vidx), cctx->ctx_type_list);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001410
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001411 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001412}
1413
1414/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001415 * Generate an ISN_UNLET instruction.
1416 */
1417 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001418generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001419{
1420 isn_T *isn;
1421
1422 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001423 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001424 return FAIL;
1425 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1426 isn->isn_arg.unlet.ul_forceit = forceit;
1427
1428 return OK;
1429}
1430
1431/*
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02001432 * Generate an ISN_LOCKCONST instruction.
1433 */
1434 static int
1435generate_LOCKCONST(cctx_T *cctx)
1436{
1437 isn_T *isn;
1438
1439 RETURN_OK_IF_SKIP(cctx);
1440 if ((isn = generate_instr(cctx, ISN_LOCKCONST)) == NULL)
1441 return FAIL;
1442 return OK;
1443}
1444
1445/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001446 * Generate an ISN_LOADS instruction.
1447 */
1448 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001449generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001450 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001451 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001452 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001453 int sid,
1454 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001455{
1456 isn_T *isn;
1457
Bram Moolenaar080457c2020-03-03 21:53:32 +01001458 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001459 if (isn_type == ISN_LOADS)
1460 isn = generate_instr_type(cctx, isn_type, type);
1461 else
1462 isn = generate_instr_drop(cctx, isn_type, 1);
1463 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001464 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001465 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1466 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001467
1468 return OK;
1469}
1470
1471/*
1472 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1473 */
1474 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001475generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001476 cctx_T *cctx,
1477 isntype_T isn_type,
1478 int sid,
1479 int idx,
1480 type_T *type)
1481{
1482 isn_T *isn;
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01001483 scriptref_T *sref;
1484 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001485
Bram Moolenaar080457c2020-03-03 21:53:32 +01001486 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001487 if (isn_type == ISN_LOADSCRIPT)
1488 isn = generate_instr_type(cctx, isn_type, type);
1489 else
1490 isn = generate_instr_drop(cctx, isn_type, 1);
1491 if (isn == NULL)
1492 return FAIL;
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01001493
1494 // This requires three arguments, which doesn't fit in an instruction, thus
1495 // we need to allocate a struct for this.
1496 sref = ALLOC_ONE(scriptref_T);
1497 if (sref == NULL)
1498 return FAIL;
1499 isn->isn_arg.script.scriptref = sref;
1500 sref->sref_sid = sid;
1501 sref->sref_idx = idx;
1502 sref->sref_seq = si->sn_script_seq;
Bram Moolenaar07a65d22020-12-26 20:09:15 +01001503 sref->sref_type = type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001504 return OK;
1505}
1506
1507/*
1508 * Generate an ISN_NEWLIST instruction.
1509 */
1510 static int
1511generate_NEWLIST(cctx_T *cctx, int count)
1512{
1513 isn_T *isn;
1514 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001515 type_T *type;
1516 type_T *member;
1517
Bram Moolenaar080457c2020-03-03 21:53:32 +01001518 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001519 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1520 return FAIL;
1521 isn->isn_arg.number = count;
1522
Bram Moolenaar127542b2020-08-09 17:22:04 +02001523 // get the member type from all the items on the stack.
Bram Moolenaar9c2b0662020-09-01 19:56:15 +02001524 if (count == 0)
1525 member = &t_void;
1526 else
1527 member = get_member_type_from_stack(
Bram Moolenaar127542b2020-08-09 17:22:04 +02001528 ((type_T **)stack->ga_data) + stack->ga_len, count, 1,
1529 cctx->ctx_type_list);
1530 type = get_list_type(member, cctx->ctx_type_list);
1531
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001532 // drop the value types
1533 stack->ga_len -= count;
1534
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001535 // add the list type to the type stack
1536 if (ga_grow(stack, 1) == FAIL)
1537 return FAIL;
1538 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1539 ++stack->ga_len;
1540
1541 return OK;
1542}
1543
1544/*
1545 * Generate an ISN_NEWDICT instruction.
1546 */
1547 static int
1548generate_NEWDICT(cctx_T *cctx, int count)
1549{
1550 isn_T *isn;
1551 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001552 type_T *type;
1553 type_T *member;
1554
Bram Moolenaar080457c2020-03-03 21:53:32 +01001555 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001556 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1557 return FAIL;
1558 isn->isn_arg.number = count;
1559
Bram Moolenaar9c2b0662020-09-01 19:56:15 +02001560 if (count == 0)
1561 member = &t_void;
1562 else
1563 member = get_member_type_from_stack(
Bram Moolenaar127542b2020-08-09 17:22:04 +02001564 ((type_T **)stack->ga_data) + stack->ga_len, count, 2,
1565 cctx->ctx_type_list);
1566 type = get_dict_type(member, cctx->ctx_type_list);
1567
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001568 // drop the key and value types
1569 stack->ga_len -= 2 * count;
1570
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001571 // add the dict type to the type stack
1572 if (ga_grow(stack, 1) == FAIL)
1573 return FAIL;
1574 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1575 ++stack->ga_len;
1576
1577 return OK;
1578}
1579
1580/*
1581 * Generate an ISN_FUNCREF instruction.
1582 */
1583 static int
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001584generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001585{
1586 isn_T *isn;
1587 garray_T *stack = &cctx->ctx_type_stack;
1588
Bram Moolenaar080457c2020-03-03 21:53:32 +01001589 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001590 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1591 return FAIL;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001592 isn->isn_arg.funcref.fr_func = ufunc->uf_dfunc_idx;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02001593 cctx->ctx_has_closure = 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001594
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01001595 // If the referenced function is a closure, it may use items further up in
Bram Moolenaarab360522021-01-10 14:02:28 +01001596 // the nested context, including this one.
1597 if (ufunc->uf_flags & FC_CLOSURE)
1598 cctx->ctx_ufunc->uf_flags |= FC_CLOSURE;
1599
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001600 if (ga_grow(stack, 1) == FAIL)
1601 return FAIL;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02001602 ((type_T **)stack->ga_data)[stack->ga_len] =
1603 ufunc->uf_func_type == NULL ? &t_func_any : ufunc->uf_func_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001604 ++stack->ga_len;
1605
1606 return OK;
1607}
1608
1609/*
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001610 * Generate an ISN_NEWFUNC instruction.
Bram Moolenaar58a52f22020-12-22 18:56:55 +01001611 * "lambda_name" and "func_name" must be in allocated memory and will be
1612 * consumed.
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001613 */
1614 static int
1615generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
1616{
1617 isn_T *isn;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001618
Bram Moolenaar58a52f22020-12-22 18:56:55 +01001619 if (cctx->ctx_skip == SKIP_YES)
1620 {
1621 vim_free(lambda_name);
1622 vim_free(func_name);
1623 return OK;
1624 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001625 if ((isn = generate_instr(cctx, ISN_NEWFUNC)) == NULL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01001626 {
1627 vim_free(lambda_name);
1628 vim_free(func_name);
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001629 return FAIL;
Bram Moolenaar58a52f22020-12-22 18:56:55 +01001630 }
1631 isn->isn_arg.newfunc.nf_lambda = lambda_name;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001632 isn->isn_arg.newfunc.nf_global = func_name;
1633
1634 return OK;
1635}
1636
1637/*
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01001638 * Generate an ISN_DEF instruction: list functions
1639 */
1640 static int
1641generate_DEF(cctx_T *cctx, char_u *name, size_t len)
1642{
1643 isn_T *isn;
1644
1645 RETURN_OK_IF_SKIP(cctx);
1646 if ((isn = generate_instr(cctx, ISN_DEF)) == NULL)
1647 return FAIL;
1648 if (len > 0)
1649 {
1650 isn->isn_arg.string = vim_strnsave(name, len);
1651 if (isn->isn_arg.string == NULL)
1652 return FAIL;
1653 }
1654 return OK;
1655}
1656
1657/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001658 * Generate an ISN_JUMP instruction.
1659 */
1660 static int
1661generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1662{
1663 isn_T *isn;
1664 garray_T *stack = &cctx->ctx_type_stack;
1665
Bram Moolenaar080457c2020-03-03 21:53:32 +01001666 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001667 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1668 return FAIL;
1669 isn->isn_arg.jump.jump_when = when;
1670 isn->isn_arg.jump.jump_where = where;
1671
1672 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1673 --stack->ga_len;
1674
1675 return OK;
1676}
1677
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02001678/*
1679 * Generate an ISN_JUMP_IF_ARG_SET instruction.
1680 */
1681 static int
1682generate_JUMP_IF_ARG_SET(cctx_T *cctx, int arg_off)
1683{
1684 isn_T *isn;
1685
1686 RETURN_OK_IF_SKIP(cctx);
1687 if ((isn = generate_instr(cctx, ISN_JUMP_IF_ARG_SET)) == NULL)
1688 return FAIL;
1689 isn->isn_arg.jumparg.jump_arg_off = arg_off;
1690 // jump_where is set later
1691 return OK;
1692}
1693
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001694 static int
1695generate_FOR(cctx_T *cctx, int loop_idx)
1696{
1697 isn_T *isn;
1698 garray_T *stack = &cctx->ctx_type_stack;
1699
Bram Moolenaar080457c2020-03-03 21:53:32 +01001700 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001701 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1702 return FAIL;
1703 isn->isn_arg.forloop.for_idx = loop_idx;
1704
1705 if (ga_grow(stack, 1) == FAIL)
1706 return FAIL;
1707 // type doesn't matter, will be stored next
1708 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1709 ++stack->ga_len;
1710
1711 return OK;
1712}
Bram Moolenaarc150c092021-02-13 15:02:46 +01001713/*
1714 * Generate an ISN_TRYCONT instruction.
1715 */
1716 static int
1717generate_TRYCONT(cctx_T *cctx, int levels, int where)
1718{
1719 isn_T *isn;
1720
1721 RETURN_OK_IF_SKIP(cctx);
1722 if ((isn = generate_instr(cctx, ISN_TRYCONT)) == NULL)
1723 return FAIL;
1724 isn->isn_arg.trycont.tct_levels = levels;
1725 isn->isn_arg.trycont.tct_where = where;
1726
1727 return OK;
1728}
1729
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001730
1731/*
1732 * Generate an ISN_BCALL instruction.
Bram Moolenaar389df252020-07-09 21:20:47 +02001733 * "method_call" is TRUE for "value->method()"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001734 * Return FAIL if the number of arguments is wrong.
1735 */
1736 static int
Bram Moolenaar389df252020-07-09 21:20:47 +02001737generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001738{
1739 isn_T *isn;
1740 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar389df252020-07-09 21:20:47 +02001741 int argoff;
Bram Moolenaara1224cb2020-10-22 12:31:49 +02001742 type_T **argtypes = NULL;
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01001743 type_T *maptype = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001744
Bram Moolenaar080457c2020-03-03 21:53:32 +01001745 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar389df252020-07-09 21:20:47 +02001746 argoff = check_internal_func(func_idx, argcount);
1747 if (argoff < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001748 return FAIL;
1749
Bram Moolenaar389df252020-07-09 21:20:47 +02001750 if (method_call && argoff > 1)
1751 {
1752 if ((isn = generate_instr(cctx, ISN_SHUFFLE)) == NULL)
1753 return FAIL;
1754 isn->isn_arg.shuffle.shfl_item = argcount;
1755 isn->isn_arg.shuffle.shfl_up = argoff - 1;
1756 }
1757
Bram Moolenaaraf7a9062020-10-21 16:49:17 +02001758 if (argcount > 0)
1759 {
1760 // Check the types of the arguments.
1761 argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
Bram Moolenaar351ead02021-01-16 16:07:01 +01001762 if (internal_func_check_arg_types(argtypes, func_idx, argcount,
1763 cctx) == FAIL)
Bram Moolenaar94738d82020-10-21 14:25:07 +02001764 return FAIL;
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01001765 if (internal_func_is_map(func_idx))
1766 maptype = *argtypes;
Bram Moolenaaraf7a9062020-10-21 16:49:17 +02001767 }
Bram Moolenaar94738d82020-10-21 14:25:07 +02001768
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001769 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1770 return FAIL;
1771 isn->isn_arg.bfunc.cbf_idx = func_idx;
1772 isn->isn_arg.bfunc.cbf_argcount = argcount;
1773
Bram Moolenaar94738d82020-10-21 14:25:07 +02001774 // Drop the argument types and push the return type.
1775 stack->ga_len -= argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001776 if (ga_grow(stack, 1) == FAIL)
1777 return FAIL;
1778 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001779 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar94738d82020-10-21 14:25:07 +02001780 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001781
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01001782 if (maptype != NULL && maptype->tt_member != NULL
1783 && maptype->tt_member != &t_any)
1784 // Check that map() didn't change the item types.
Bram Moolenaare32e5162021-01-21 20:21:29 +01001785 generate_TYPECHECK(cctx, maptype, -1, 1);
Bram Moolenaar75ab91f2021-01-10 22:42:50 +01001786
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001787 return OK;
1788}
1789
1790/*
Bram Moolenaar1dcae592020-10-19 19:02:42 +02001791 * Generate an ISN_LISTAPPEND instruction. Works like add().
1792 * Argument count is already checked.
1793 */
1794 static int
1795generate_LISTAPPEND(cctx_T *cctx)
1796{
1797 garray_T *stack = &cctx->ctx_type_stack;
1798 type_T *list_type;
1799 type_T *item_type;
1800 type_T *expected;
1801
1802 // Caller already checked that list_type is a list.
1803 list_type = ((type_T **)stack->ga_data)[stack->ga_len - 2];
1804 item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
1805 expected = list_type->tt_member;
Bram Moolenaar351ead02021-01-16 16:07:01 +01001806 if (need_type(item_type, expected, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar1dcae592020-10-19 19:02:42 +02001807 return FAIL;
1808
1809 if (generate_instr(cctx, ISN_LISTAPPEND) == NULL)
1810 return FAIL;
1811
1812 --stack->ga_len; // drop the argument
1813 return OK;
1814}
1815
1816/*
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02001817 * Generate an ISN_BLOBAPPEND instruction. Works like add().
1818 * Argument count is already checked.
1819 */
1820 static int
1821generate_BLOBAPPEND(cctx_T *cctx)
1822{
1823 garray_T *stack = &cctx->ctx_type_stack;
1824 type_T *item_type;
1825
1826 // Caller already checked that blob_type is a blob.
1827 item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar351ead02021-01-16 16:07:01 +01001828 if (need_type(item_type, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02001829 return FAIL;
1830
1831 if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL)
1832 return FAIL;
1833
1834 --stack->ga_len; // drop the argument
1835 return OK;
1836}
1837
1838/*
Bram Moolenaarb2049902021-01-24 12:53:53 +01001839 * Return TRUE if "ufunc" should be compiled, taking into account whether
1840 * "profile" indicates profiling is to be done.
1841 */
1842 int
Bram Moolenaarf002a412021-01-24 13:34:18 +01001843func_needs_compiling(ufunc_T *ufunc, int profile UNUSED)
Bram Moolenaarb2049902021-01-24 12:53:53 +01001844{
1845 switch (ufunc->uf_def_status)
1846 {
Bram Moolenaar701cc6c2021-04-10 13:33:48 +02001847 case UF_TO_BE_COMPILED:
1848 return TRUE;
1849
Bram Moolenaarb2049902021-01-24 12:53:53 +01001850 case UF_COMPILED:
1851 {
Bram Moolenaarf002a412021-01-24 13:34:18 +01001852#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01001853 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1854 + ufunc->uf_dfunc_idx;
1855
1856 return profile ? dfunc->df_instr_prof == NULL
1857 : dfunc->df_instr == NULL;
Bram Moolenaarf002a412021-01-24 13:34:18 +01001858#else
1859 break;
1860#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01001861 }
Bram Moolenaar701cc6c2021-04-10 13:33:48 +02001862
1863 case UF_NOT_COMPILED:
1864 case UF_COMPILE_ERROR:
1865 case UF_COMPILING:
1866 break;
Bram Moolenaarb2049902021-01-24 12:53:53 +01001867 }
Bram Moolenaarf002a412021-01-24 13:34:18 +01001868 return FALSE;
Bram Moolenaarb2049902021-01-24 12:53:53 +01001869}
1870
1871/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001872 * Generate an ISN_DCALL or ISN_UCALL instruction.
1873 * Return FAIL if the number of arguments is wrong.
1874 */
1875 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001876generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001877{
1878 isn_T *isn;
1879 garray_T *stack = &cctx->ctx_type_stack;
1880 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001881 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001882
Bram Moolenaar080457c2020-03-03 21:53:32 +01001883 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001884 if (argcount > regular_args && !has_varargs(ufunc))
1885 {
Bram Moolenaarb185a402020-09-18 22:42:00 +02001886 semsg(_(e_toomanyarg), printable_func_name(ufunc));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001887 return FAIL;
1888 }
1889 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1890 {
Bram Moolenaarb185a402020-09-18 22:42:00 +02001891 semsg(_(e_toofewarg), printable_func_name(ufunc));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001892 return FAIL;
1893 }
1894
Bram Moolenaar701cc6c2021-04-10 13:33:48 +02001895 if (ufunc->uf_def_status != UF_NOT_COMPILED
1896 && ufunc->uf_def_status != UF_COMPILE_ERROR)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001897 {
1898 int i;
1899
1900 for (i = 0; i < argcount; ++i)
1901 {
1902 type_T *expected;
1903 type_T *actual;
1904
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02001905 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1906 if (actual == &t_special
1907 && i >= regular_args - ufunc->uf_def_args.ga_len)
1908 {
1909 // assume v:none used for default argument value
1910 continue;
1911 }
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001912 if (i < regular_args)
1913 {
1914 if (ufunc->uf_arg_types == NULL)
1915 continue;
1916 expected = ufunc->uf_arg_types[i];
1917 }
Bram Moolenaar2a389082021-04-09 20:24:31 +02001918 else if (ufunc->uf_va_type == NULL
1919 || ufunc->uf_va_type == &t_list_any)
Bram Moolenaar2f8cbc42020-09-16 17:22:59 +02001920 // possibly a lambda or "...: any"
Bram Moolenaar79e8db92020-08-14 22:16:33 +02001921 expected = &t_any;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001922 else
1923 expected = ufunc->uf_va_type->tt_member;
Bram Moolenaare32e5162021-01-21 20:21:29 +01001924 if (need_type(actual, expected, -argcount + i, i + 1, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02001925 TRUE, FALSE) == FAIL)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001926 {
1927 arg_type_mismatch(expected, actual, i + 1);
1928 return FAIL;
1929 }
1930 }
Bram Moolenaare5ea3462021-01-25 21:01:48 +01001931 if (func_needs_compiling(ufunc, PROFILING(ufunc))
Bram Moolenaarb2049902021-01-24 12:53:53 +01001932 && compile_def_function(ufunc, ufunc->uf_ret_type == NULL,
Bram Moolenaare5ea3462021-01-25 21:01:48 +01001933 PROFILING(ufunc), NULL) == FAIL)
Bram Moolenaarb2049902021-01-24 12:53:53 +01001934 return FAIL;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001935 }
1936
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001937 if ((isn = generate_instr(cctx,
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001938 ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
Bram Moolenaar822ba242020-05-24 23:00:18 +02001939 : ISN_UCALL)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001940 return FAIL;
Bram Moolenaara05e5242020-09-19 18:19:19 +02001941 if (isn->isn_type == ISN_DCALL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001942 {
1943 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1944 isn->isn_arg.dfunc.cdf_argcount = argcount;
1945 }
1946 else
1947 {
1948 // A user function may be deleted and redefined later, can't use the
1949 // ufunc pointer, need to look it up again at runtime.
1950 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1951 isn->isn_arg.ufunc.cuf_argcount = argcount;
1952 }
1953
1954 stack->ga_len -= argcount; // drop the arguments
1955 if (ga_grow(stack, 1) == FAIL)
1956 return FAIL;
1957 // add return value
1958 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1959 ++stack->ga_len;
1960
1961 return OK;
1962}
1963
1964/*
1965 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1966 */
1967 static int
1968generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1969{
1970 isn_T *isn;
1971 garray_T *stack = &cctx->ctx_type_stack;
1972
Bram Moolenaar080457c2020-03-03 21:53:32 +01001973 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001974 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1975 return FAIL;
1976 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1977 isn->isn_arg.ufunc.cuf_argcount = argcount;
1978
1979 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001980 if (ga_grow(stack, 1) == FAIL)
1981 return FAIL;
1982 // add return value
1983 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1984 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001985
1986 return OK;
1987}
1988
1989/*
1990 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001991 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001992 */
1993 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001994generate_PCALL(
1995 cctx_T *cctx,
1996 int argcount,
1997 char_u *name,
1998 type_T *type,
1999 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002000{
2001 isn_T *isn;
2002 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002003 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002004
Bram Moolenaar080457c2020-03-03 21:53:32 +01002005 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002006
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002007 if (type->tt_type == VAR_ANY)
2008 ret_type = &t_any;
2009 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02002010 {
2011 if (type->tt_argcount != -1)
2012 {
2013 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
2014
2015 if (argcount < type->tt_min_argcount - varargs)
2016 {
Bram Moolenaar6cf7e3b2020-10-28 14:31:16 +01002017 semsg(_(e_toofewarg), name);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02002018 return FAIL;
2019 }
2020 if (!varargs && argcount > type->tt_argcount)
2021 {
Bram Moolenaar6cf7e3b2020-10-28 14:31:16 +01002022 semsg(_(e_toomanyarg), name);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02002023 return FAIL;
2024 }
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01002025 if (type->tt_args != NULL)
2026 {
2027 int i;
2028
2029 for (i = 0; i < argcount; ++i)
2030 {
Bram Moolenaar1088b692021-04-09 22:12:44 +02002031 int offset = -argcount + i - (at_top ? 0 : 1);
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01002032 type_T *actual = ((type_T **)stack->ga_data)[
2033 stack->ga_len + offset];
2034 type_T *expected;
2035
Bram Moolenaar32b3f822021-01-06 21:59:39 +01002036 if (varargs && i >= type->tt_argcount - 1)
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01002037 expected = type->tt_args[
Bram Moolenaar32b3f822021-01-06 21:59:39 +01002038 type->tt_argcount - 1]->tt_member;
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02002039 else if (i >= type->tt_min_argcount
2040 && actual == &t_special)
2041 expected = &t_any;
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01002042 else
2043 expected = type->tt_args[i];
Bram Moolenaare32e5162021-01-21 20:21:29 +01002044 if (need_type(actual, expected, offset, i + 1,
Bram Moolenaarb4d16cb2020-11-05 18:45:46 +01002045 cctx, TRUE, FALSE) == FAIL)
2046 {
2047 arg_type_mismatch(expected, actual, i + 1);
2048 return FAIL;
2049 }
2050 }
2051 }
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02002052 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002053 ret_type = type->tt_member;
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02002054 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002055 else
2056 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002057 semsg(_(e_not_callable_type_str), name);
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002058 return FAIL;
2059 }
2060
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002061 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
2062 return FAIL;
2063 isn->isn_arg.pfunc.cpf_top = at_top;
2064 isn->isn_arg.pfunc.cpf_argcount = argcount;
2065
2066 stack->ga_len -= argcount; // drop the arguments
2067
2068 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002069 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002070
Bram Moolenaarbd5da372020-03-31 23:13:10 +02002071 // If partial is above the arguments it must be cleared and replaced with
2072 // the return value.
2073 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
2074 return FAIL;
2075
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002076 return OK;
2077}
2078
2079/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002080 * Generate an ISN_STRINGMEMBER instruction.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002081 */
2082 static int
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002083generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002084{
2085 isn_T *isn;
2086 garray_T *stack = &cctx->ctx_type_stack;
2087 type_T *type;
2088
Bram Moolenaar080457c2020-03-03 21:53:32 +01002089 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02002090 if ((isn = generate_instr(cctx, ISN_STRINGMEMBER)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002091 return FAIL;
Bram Moolenaar71ccd032020-06-12 22:59:11 +02002092 isn->isn_arg.string = vim_strnsave(name, len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002093
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01002094 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002095 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01002096 if (type->tt_type != VAR_DICT && type != &t_any)
2097 {
2098 emsg(_(e_dictreq));
2099 return FAIL;
2100 }
2101 // change dict type to dict member type
2102 if (type->tt_type == VAR_DICT)
Bram Moolenaar31a11b92021-01-10 19:23:27 +01002103 {
2104 ((type_T **)stack->ga_data)[stack->ga_len - 1] =
2105 type->tt_member == &t_unknown ? &t_any : type->tt_member;
2106 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002107
2108 return OK;
2109}
2110
2111/*
2112 * Generate an ISN_ECHO instruction.
2113 */
2114 static int
2115generate_ECHO(cctx_T *cctx, int with_white, int count)
2116{
2117 isn_T *isn;
2118
Bram Moolenaar080457c2020-03-03 21:53:32 +01002119 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002120 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
2121 return FAIL;
2122 isn->isn_arg.echo.echo_with_white = with_white;
2123 isn->isn_arg.echo.echo_count = count;
2124
2125 return OK;
2126}
2127
Bram Moolenaarad39c092020-02-26 18:23:43 +01002128/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002129 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01002130 */
2131 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002132generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01002133{
2134 isn_T *isn;
2135
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02002136 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01002137 return FAIL;
2138 isn->isn_arg.number = count;
2139
2140 return OK;
2141}
2142
Bram Moolenaarc3516f72020-09-08 22:45:35 +02002143/*
2144 * Generate an ISN_PUT instruction.
2145 */
2146 static int
2147generate_PUT(cctx_T *cctx, int regname, linenr_T lnum)
2148{
2149 isn_T *isn;
2150
2151 RETURN_OK_IF_SKIP(cctx);
2152 if ((isn = generate_instr(cctx, ISN_PUT)) == NULL)
2153 return FAIL;
2154 isn->isn_arg.put.put_regname = regname;
2155 isn->isn_arg.put.put_lnum = lnum;
2156 return OK;
2157}
2158
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002159 static int
2160generate_EXEC(cctx_T *cctx, char_u *line)
2161{
2162 isn_T *isn;
2163
Bram Moolenaar080457c2020-03-03 21:53:32 +01002164 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002165 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
2166 return FAIL;
2167 isn->isn_arg.string = vim_strsave(line);
2168 return OK;
2169}
2170
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02002171 static int
2172generate_EXECCONCAT(cctx_T *cctx, int count)
2173{
2174 isn_T *isn;
2175
2176 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
2177 return FAIL;
2178 isn->isn_arg.number = count;
2179 return OK;
2180}
2181
Bram Moolenaar08597872020-12-10 19:43:40 +01002182/*
2183 * Generate ISN_RANGE. Consumes "range". Return OK/FAIL.
2184 */
2185 static int
2186generate_RANGE(cctx_T *cctx, char_u *range)
2187{
2188 isn_T *isn;
2189 garray_T *stack = &cctx->ctx_type_stack;
2190
2191 if ((isn = generate_instr(cctx, ISN_RANGE)) == NULL)
2192 return FAIL;
2193 isn->isn_arg.string = range;
2194
2195 if (ga_grow(stack, 1) == FAIL)
2196 return FAIL;
2197 ((type_T **)stack->ga_data)[stack->ga_len] = &t_number;
2198 ++stack->ga_len;
2199 return OK;
2200}
2201
Bram Moolenaar792f7862020-11-23 08:31:18 +01002202 static int
2203generate_UNPACK(cctx_T *cctx, int var_count, int semicolon)
2204{
2205 isn_T *isn;
2206
2207 RETURN_OK_IF_SKIP(cctx);
2208 if ((isn = generate_instr(cctx, ISN_UNPACK)) == NULL)
2209 return FAIL;
2210 isn->isn_arg.unpack.unp_count = var_count;
2211 isn->isn_arg.unpack.unp_semicolon = semicolon;
2212 return OK;
2213}
2214
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002215/*
Bram Moolenaar02194d22020-10-24 23:08:38 +02002216 * Generate an instruction for any command modifiers.
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002217 */
2218 static int
Bram Moolenaare1004402020-10-24 20:49:43 +02002219generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002220{
2221 isn_T *isn;
2222
Bram Moolenaarfa984412021-03-25 22:15:28 +01002223 if (has_cmdmod(cmod))
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002224 {
Bram Moolenaar02194d22020-10-24 23:08:38 +02002225 cctx->ctx_has_cmdmod = TRUE;
2226
2227 if ((isn = generate_instr(cctx, ISN_CMDMOD)) == NULL)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002228 return FAIL;
Bram Moolenaar02194d22020-10-24 23:08:38 +02002229 isn->isn_arg.cmdmod.cf_cmdmod = ALLOC_ONE(cmdmod_T);
2230 if (isn->isn_arg.cmdmod.cf_cmdmod == NULL)
2231 return FAIL;
2232 mch_memmove(isn->isn_arg.cmdmod.cf_cmdmod, cmod, sizeof(cmdmod_T));
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01002233 // filter program now belongs to the instruction
Bram Moolenaar02194d22020-10-24 23:08:38 +02002234 cmod->cmod_filter_regmatch.regprog = NULL;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002235 }
Bram Moolenaar02194d22020-10-24 23:08:38 +02002236
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002237 return OK;
2238}
2239
2240 static int
Bram Moolenaar02194d22020-10-24 23:08:38 +02002241generate_undo_cmdmods(cctx_T *cctx)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002242{
Bram Moolenaarf665e972020-12-05 19:17:16 +01002243 if (cctx->ctx_has_cmdmod && generate_instr(cctx, ISN_CMDMOD_REV) == NULL)
2244 return FAIL;
Bram Moolenaar7cd24222021-01-12 18:58:39 +01002245 cctx->ctx_has_cmdmod = FALSE;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002246 return OK;
2247}
2248
Bram Moolenaarfa984412021-03-25 22:15:28 +01002249 static int
2250misplaced_cmdmod(cctx_T *cctx)
Bram Moolenaara91a7132021-03-25 21:12:15 +01002251{
2252 garray_T *instr = &cctx->ctx_instr;
2253
Bram Moolenaara91a7132021-03-25 21:12:15 +01002254 if (cctx->ctx_has_cmdmod
2255 && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
2256 == ISN_CMDMOD)
2257 {
Bram Moolenaarfa984412021-03-25 22:15:28 +01002258 emsg(_(e_misplaced_command_modifier));
2259 return TRUE;
Bram Moolenaara91a7132021-03-25 21:12:15 +01002260 }
Bram Moolenaarfa984412021-03-25 22:15:28 +01002261 return FALSE;
Bram Moolenaara91a7132021-03-25 21:12:15 +01002262}
2263
2264/*
2265 * Get the index of the current instruction.
2266 * This compenstates for a preceding ISN_CMDMOD and ISN_PROF_START.
2267 */
2268 static int
2269current_instr_idx(cctx_T *cctx)
2270{
2271 garray_T *instr = &cctx->ctx_instr;
2272 int idx = instr->ga_len;
2273
2274 if (cctx->ctx_has_cmdmod && ((isn_T *)instr->ga_data)[idx - 1]
2275 .isn_type == ISN_CMDMOD)
2276 --idx;
2277#ifdef FEAT_PROFILE
2278 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[idx - 1]
2279 .isn_type == ISN_PROF_START)
2280 --idx;
2281#endif
2282 return idx;
2283}
2284
Bram Moolenaarf002a412021-01-24 13:34:18 +01002285#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01002286 static void
2287may_generate_prof_end(cctx_T *cctx, int prof_lnum)
2288{
2289 if (cctx->ctx_profiling && prof_lnum >= 0)
Bram Moolenaarb2049902021-01-24 12:53:53 +01002290 generate_instr(cctx, ISN_PROF_END);
Bram Moolenaarb2049902021-01-24 12:53:53 +01002291}
Bram Moolenaarf002a412021-01-24 13:34:18 +01002292#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01002293
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002294/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002295 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002296 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002297 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002298 static lvar_T *
Bram Moolenaare8211a32020-10-09 22:04:29 +02002299reserve_local(
2300 cctx_T *cctx,
2301 char_u *name,
2302 size_t len,
2303 int isConst,
2304 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002305{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002306 lvar_T *lvar;
2307
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002308 if (arg_exists(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002309 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002310 emsg_namelen(_(e_str_is_used_as_argument), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002311 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002312 }
2313
2314 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002315 return NULL;
2316 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaare8211a32020-10-09 22:04:29 +02002317 CLEAR_POINTER(lvar);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002318
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002319 // Every local variable uses the next entry on the stack. We could re-use
2320 // the last ones when leaving a scope, but then variables used in a closure
2321 // might get overwritten. To keep things simple do not re-use stack
2322 // entries. This is less efficient, but memory is cheap these days.
2323 lvar->lv_idx = cctx->ctx_locals_count++;
2324
Bram Moolenaar71ccd032020-06-12 22:59:11 +02002325 lvar->lv_name = vim_strnsave(name, len == 0 ? STRLEN(name) : len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002326 lvar->lv_const = isConst;
2327 lvar->lv_type = type;
2328
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002329 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002330}
2331
2332/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002333 * Remove local variables above "new_top".
2334 */
2335 static void
2336unwind_locals(cctx_T *cctx, int new_top)
2337{
2338 if (cctx->ctx_locals.ga_len > new_top)
2339 {
2340 int idx;
2341 lvar_T *lvar;
2342
2343 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
2344 {
2345 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
2346 vim_free(lvar->lv_name);
2347 }
2348 }
2349 cctx->ctx_locals.ga_len = new_top;
2350}
2351
2352/*
2353 * Free all local variables.
2354 */
2355 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002356free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01002357{
2358 unwind_locals(cctx, 0);
2359 ga_clear(&cctx->ctx_locals);
2360}
2361
2362/*
Bram Moolenaar08251752021-01-11 21:20:18 +01002363 * If "check_writable" is ASSIGN_CONST give an error if the variable was
2364 * defined with :final or :const, if "check_writable" is ASSIGN_FINAL give an
2365 * error if the variable was defined with :const.
2366 */
2367 static int
2368check_item_writable(svar_T *sv, int check_writable, char_u *name)
2369{
2370 if ((check_writable == ASSIGN_CONST && sv->sv_const != 0)
2371 || (check_writable == ASSIGN_FINAL
2372 && sv->sv_const == ASSIGN_CONST))
2373 {
2374 semsg(_(e_readonlyvar), name);
2375 return FAIL;
2376 }
2377 return OK;
2378}
2379
2380/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002381 * Find "name" in script-local items of script "sid".
Bram Moolenaar08251752021-01-11 21:20:18 +01002382 * Pass "check_writable" to check_item_writable().
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002383 * Returns the index in "sn_var_vals" if found.
2384 * If found but not in "sn_var_vals" returns -1.
Bram Moolenaar08251752021-01-11 21:20:18 +01002385 * If not found or the variable is not writable returns -2.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002386 */
2387 int
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002388get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002389{
2390 hashtab_T *ht;
2391 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002392 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002393 svar_T *sv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002394 int idx;
2395
Bram Moolenaare3d46852020-08-29 13:39:17 +02002396 if (!SCRIPT_ID_VALID(sid))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002397 return -1;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002398 if (sid == current_sctx.sc_sid)
2399 {
Bram Moolenaar209f0202020-10-15 13:57:56 +02002400 sallvar_T *sav = find_script_var(name, 0, cctx);
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002401
2402 if (sav == NULL)
2403 return -2;
2404 idx = sav->sav_var_vals_idx;
2405 sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
Bram Moolenaar08251752021-01-11 21:20:18 +01002406 if (check_item_writable(sv, check_writable, name) == FAIL)
2407 return -2;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002408 return idx;
2409 }
2410
2411 // First look the name up in the hashtable.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002412 ht = &SCRIPT_VARS(sid);
2413 di = find_var_in_ht(ht, 0, name, TRUE);
2414 if (di == NULL)
2415 return -2;
2416
2417 // Now find the svar_T index in sn_var_vals.
2418 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2419 {
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002420 sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002421 if (sv->sv_tv == &di->di_tv)
2422 {
Bram Moolenaar08251752021-01-11 21:20:18 +01002423 if (check_item_writable(sv, check_writable, name) == FAIL)
2424 return -2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002425 return idx;
2426 }
2427 }
2428 return -1;
2429}
2430
2431/*
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02002432 * Find "name" in imported items of the current script or in "cctx" if not
2433 * NULL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002434 */
2435 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002436find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002437{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002438 int idx;
2439
Bram Moolenaare3d46852020-08-29 13:39:17 +02002440 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02002441 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002442 if (cctx != NULL)
2443 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2444 {
2445 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2446 + idx;
2447
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002448 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2449 : STRLEN(import->imp_name) == len
2450 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002451 return import;
2452 }
2453
Bram Moolenaarefa94442020-08-08 22:16:00 +02002454 return find_imported_in_script(name, len, current_sctx.sc_sid);
2455}
2456
2457 imported_T *
2458find_imported_in_script(char_u *name, size_t len, int sid)
2459{
Bram Moolenaare3d46852020-08-29 13:39:17 +02002460 scriptitem_T *si;
Bram Moolenaarefa94442020-08-08 22:16:00 +02002461 int idx;
2462
Bram Moolenaare3d46852020-08-29 13:39:17 +02002463 if (!SCRIPT_ID_VALID(sid))
2464 return NULL;
2465 si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002466 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2467 {
2468 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2469
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002470 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2471 : STRLEN(import->imp_name) == len
2472 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002473 return import;
2474 }
2475 return NULL;
2476}
2477
2478/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002479 * Free all imported variables.
2480 */
2481 static void
2482free_imported(cctx_T *cctx)
2483{
2484 int idx;
2485
2486 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2487 {
2488 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2489
2490 vim_free(import->imp_name);
2491 }
2492 ga_clear(&cctx->ctx_imports);
2493}
2494
2495/*
Bram Moolenaar23c55272020-06-21 16:58:13 +02002496 * Return a pointer to the next line that isn't empty or only contains a
2497 * comment. Skips over white space.
2498 * Returns NULL if there is none.
2499 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002500 char_u *
2501peek_next_line_from_context(cctx_T *cctx)
Bram Moolenaar23c55272020-06-21 16:58:13 +02002502{
2503 int lnum = cctx->ctx_lnum;
2504
2505 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
2506 {
2507 char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002508 char_u *p;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002509
Bram Moolenaarba60cc42020-08-12 19:15:33 +02002510 // ignore NULLs inserted for continuation lines
2511 if (line != NULL)
2512 {
2513 p = skipwhite(line);
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01002514 if (vim9_bad_comment(p))
2515 return NULL;
Bram Moolenaarba60cc42020-08-12 19:15:33 +02002516 if (*p != NUL && !vim9_comment_start(p))
2517 return p;
2518 }
Bram Moolenaar23c55272020-06-21 16:58:13 +02002519 }
2520 return NULL;
2521}
2522
2523/*
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002524 * Called when checking for a following operator at "arg". When the rest of
2525 * the line is empty or only a comment, peek the next line. If there is a next
2526 * line return a pointer to it and set "nextp".
2527 * Otherwise skip over white space.
2528 */
2529 static char_u *
2530may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp)
2531{
2532 char_u *p = skipwhite(arg);
2533
2534 *nextp = NULL;
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002535 if (*p == NUL || (VIM_ISWHITE(*arg) && vim9_comment_start(p)))
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002536 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002537 *nextp = peek_next_line_from_context(cctx);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002538 if (*nextp != NULL)
2539 return *nextp;
2540 }
2541 return p;
2542}
2543
2544/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002545 * Get the next line of the function from "cctx".
Bram Moolenaar23c55272020-06-21 16:58:13 +02002546 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
Bram Moolenaare6085c52020-04-12 20:19:16 +02002547 * Returns NULL when at the end.
2548 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002549 char_u *
Bram Moolenaar23c55272020-06-21 16:58:13 +02002550next_line_from_context(cctx_T *cctx, int skip_comment)
Bram Moolenaare6085c52020-04-12 20:19:16 +02002551{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002552 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002553
2554 do
2555 {
2556 ++cctx->ctx_lnum;
2557 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002558 {
2559 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002560 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002561 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002562 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002563 cctx->ctx_line_start = line;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02002564 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002565 } while (line == NULL || *skipwhite(line) == NUL
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02002566 || (skip_comment && vim9_comment_start(skipwhite(line))));
Bram Moolenaare6085c52020-04-12 20:19:16 +02002567 return line;
2568}
2569
2570/*
Bram Moolenaar5afd0812021-01-03 18:33:13 +01002571 * Skip over white space at "whitep" and assign to "*arg".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002572 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002573 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002574 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2575 */
2576 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002577may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002578{
Bram Moolenaar5afd0812021-01-03 18:33:13 +01002579 *arg = skipwhite(whitep);
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01002580 if (vim9_bad_comment(*arg))
2581 return FAIL;
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002582 if (**arg == NUL || (VIM_ISWHITE(*whitep) && vim9_comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002583 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002584 char_u *next = next_line_from_context(cctx, TRUE);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002585
2586 if (next == NULL)
2587 return FAIL;
2588 *arg = skipwhite(next);
2589 }
2590 return OK;
2591}
2592
Bram Moolenaara7eedf32020-07-10 21:50:41 +02002593/*
2594 * Idem, and give an error when failed.
2595 */
2596 static int
2597may_get_next_line_error(char_u *whitep, char_u **arg, cctx_T *cctx)
2598{
2599 if (may_get_next_line(whitep, arg, cctx) == FAIL)
2600 {
Bram Moolenaar8ff16e02020-12-07 21:49:52 +01002601 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002602 emsg(_(e_line_incomplete));
Bram Moolenaara7eedf32020-07-10 21:50:41 +02002603 return FAIL;
2604 }
2605 return OK;
2606}
2607
2608
Bram Moolenaara5565e42020-05-09 15:44:01 +02002609// Structure passed between the compile_expr* functions to keep track of
2610// constants that have been parsed but for which no code was produced yet. If
2611// possible expressions on these constants are applied at compile time. If
2612// that is not possible, the code to push the constants needs to be generated
2613// before other instructions.
Bram Moolenaar1c747212020-05-09 18:28:34 +02002614// Using 50 should be more than enough of 5 levels of ().
2615#define PPSIZE 50
Bram Moolenaara5565e42020-05-09 15:44:01 +02002616typedef struct {
Bram Moolenaar1c747212020-05-09 18:28:34 +02002617 typval_T pp_tv[PPSIZE]; // stack of ppconst constants
Bram Moolenaara5565e42020-05-09 15:44:01 +02002618 int pp_used; // active entries in pp_tv[]
Bram Moolenaar334a8b42020-10-19 16:07:42 +02002619 int pp_is_const; // all generated code was constants, used for a
2620 // list or dict with constant members
Bram Moolenaara5565e42020-05-09 15:44:01 +02002621} ppconst_T;
2622
Bram Moolenaar334a8b42020-10-19 16:07:42 +02002623static int compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const);
Bram Moolenaar1c747212020-05-09 18:28:34 +02002624static int compile_expr0(char_u **arg, cctx_T *cctx);
2625static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2626
Bram Moolenaara5565e42020-05-09 15:44:01 +02002627/*
2628 * Generate a PUSH instruction for "tv".
2629 * "tv" will be consumed or cleared.
2630 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
2631 */
2632 static int
2633generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
2634{
2635 if (tv != NULL)
2636 {
2637 switch (tv->v_type)
2638 {
2639 case VAR_UNKNOWN:
2640 break;
2641 case VAR_BOOL:
2642 generate_PUSHBOOL(cctx, tv->vval.v_number);
2643 break;
2644 case VAR_SPECIAL:
2645 generate_PUSHSPEC(cctx, tv->vval.v_number);
2646 break;
2647 case VAR_NUMBER:
2648 generate_PUSHNR(cctx, tv->vval.v_number);
2649 break;
2650#ifdef FEAT_FLOAT
2651 case VAR_FLOAT:
2652 generate_PUSHF(cctx, tv->vval.v_float);
2653 break;
2654#endif
2655 case VAR_BLOB:
2656 generate_PUSHBLOB(cctx, tv->vval.v_blob);
2657 tv->vval.v_blob = NULL;
2658 break;
2659 case VAR_STRING:
2660 generate_PUSHS(cctx, tv->vval.v_string);
2661 tv->vval.v_string = NULL;
2662 break;
2663 default:
2664 iemsg("constant type not supported");
2665 clear_tv(tv);
2666 return FAIL;
2667 }
2668 tv->v_type = VAR_UNKNOWN;
2669 }
2670 return OK;
2671}
2672
2673/*
2674 * Generate code for any ppconst entries.
2675 */
2676 static int
2677generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
2678{
2679 int i;
2680 int ret = OK;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002681 int save_skip = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002682
Bram Moolenaar9b68c822020-06-18 19:31:08 +02002683 cctx->ctx_skip = SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002684 for (i = 0; i < ppconst->pp_used; ++i)
2685 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
2686 ret = FAIL;
2687 ppconst->pp_used = 0;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002688 cctx->ctx_skip = save_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002689 return ret;
2690}
2691
2692/*
2693 * Clear ppconst constants. Used when failing.
2694 */
2695 static void
2696clear_ppconst(ppconst_T *ppconst)
2697{
2698 int i;
2699
2700 for (i = 0; i < ppconst->pp_used; ++i)
2701 clear_tv(&ppconst->pp_tv[i]);
2702 ppconst->pp_used = 0;
2703}
2704
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002705/*
Bram Moolenaare42939a2021-04-05 17:11:17 +02002706 * Compile getting a member from a list/dict/string/blob. Stack has the
2707 * indexable value and the index.
2708 */
2709 static int
2710compile_member(int is_slice, cctx_T *cctx)
2711{
2712 type_T **typep;
2713 garray_T *stack = &cctx->ctx_type_stack;
2714 vartype_T vtype;
2715 type_T *valtype;
2716
2717 // We can index a list and a dict. If we don't know the type
2718 // we can use the index value type.
2719 // TODO: If we don't know use an instruction to figure it out at
2720 // runtime.
2721 typep = ((type_T **)stack->ga_data) + stack->ga_len
2722 - (is_slice ? 3 : 2);
2723 vtype = (*typep)->tt_type;
2724 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2725 // If the index is a string, the variable must be a Dict.
2726 if (*typep == &t_any && valtype == &t_string)
2727 vtype = VAR_DICT;
2728 if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB)
2729 {
2730 if (need_type(valtype, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
2731 return FAIL;
2732 if (is_slice)
2733 {
2734 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2];
2735 if (need_type(valtype, &t_number, -2, 0, cctx,
2736 FALSE, FALSE) == FAIL)
2737 return FAIL;
2738 }
2739 }
2740
2741 if (vtype == VAR_DICT)
2742 {
2743 if (is_slice)
2744 {
2745 emsg(_(e_cannot_slice_dictionary));
2746 return FAIL;
2747 }
2748 if ((*typep)->tt_type == VAR_DICT)
2749 {
2750 *typep = (*typep)->tt_member;
2751 if (*typep == &t_unknown)
2752 // empty dict was used
2753 *typep = &t_any;
2754 }
2755 else
2756 {
2757 if (need_type(*typep, &t_dict_any, -2, 0, cctx,
2758 FALSE, FALSE) == FAIL)
2759 return FAIL;
2760 *typep = &t_any;
2761 }
2762 if (may_generate_2STRING(-1, cctx) == FAIL)
2763 return FAIL;
2764 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
2765 return FAIL;
2766 }
2767 else if (vtype == VAR_STRING)
2768 {
2769 *typep = &t_string;
2770 if ((is_slice
2771 ? generate_instr_drop(cctx, ISN_STRSLICE, 2)
2772 : generate_instr_drop(cctx, ISN_STRINDEX, 1)) == FAIL)
2773 return FAIL;
2774 }
2775 else if (vtype == VAR_BLOB)
2776 {
Bram Moolenaarcfc30232021-04-11 20:26:34 +02002777 if (is_slice)
2778 {
2779 *typep = &t_blob;
2780 if (generate_instr_drop(cctx, ISN_BLOBSLICE, 2) == FAIL)
2781 return FAIL;
2782 }
2783 else
2784 {
2785 *typep = &t_number;
2786 if (generate_instr_drop(cctx, ISN_BLOBINDEX, 1) == FAIL)
2787 return FAIL;
2788 }
Bram Moolenaare42939a2021-04-05 17:11:17 +02002789 }
2790 else if (vtype == VAR_LIST || *typep == &t_any)
2791 {
2792 if (is_slice)
2793 {
2794 if (generate_instr_drop(cctx,
2795 vtype == VAR_LIST ? ISN_LISTSLICE : ISN_ANYSLICE,
2796 2) == FAIL)
2797 return FAIL;
2798 }
2799 else
2800 {
2801 if ((*typep)->tt_type == VAR_LIST)
2802 {
2803 *typep = (*typep)->tt_member;
2804 if (*typep == &t_unknown)
2805 // empty list was used
2806 *typep = &t_any;
2807 }
2808 if (generate_instr_drop(cctx,
2809 vtype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX, 1) == FAIL)
2810 return FAIL;
2811 }
2812 }
2813 else
2814 {
2815 emsg(_(e_string_list_dict_or_blob_required));
2816 return FAIL;
2817 }
2818 return OK;
2819}
2820
2821/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002822 * Generate an instruction to load script-local variable "name", without the
2823 * leading "s:".
2824 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002825 */
2826 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002827compile_load_scriptvar(
2828 cctx_T *cctx,
2829 char_u *name, // variable NUL terminated
2830 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002831 char_u **end, // end of variable
2832 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002833{
Bram Moolenaare3d46852020-08-29 13:39:17 +02002834 scriptitem_T *si;
2835 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002836 imported_T *import;
2837
Bram Moolenaare3d46852020-08-29 13:39:17 +02002838 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
2839 return FAIL;
2840 si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar08251752021-01-11 21:20:18 +01002841 idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx);
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002842 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002843 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002844 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002845 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2846 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002847 }
2848 if (idx >= 0)
2849 {
2850 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2851
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002852 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002853 current_sctx.sc_sid, idx, sv->sv_type);
2854 return OK;
2855 }
2856
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002857 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002858 if (import != NULL)
2859 {
Bram Moolenaara6294952020-12-27 13:39:50 +01002860 if (import->imp_flags & IMP_FLAGS_STAR)
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002861 {
2862 char_u *p = skipwhite(*end);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002863 char_u *exp_name;
2864 int cc;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002865 ufunc_T *ufunc;
2866 type_T *type;
2867
2868 // Used "import * as Name", need to lookup the member.
2869 if (*p != '.')
2870 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002871 semsg(_(e_expected_dot_after_name_str), start);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002872 return FAIL;
2873 }
2874 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002875 if (VIM_ISWHITE(*p))
2876 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002877 emsg(_(e_no_white_space_allowed_after_dot));
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002878 return FAIL;
2879 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002880
Bram Moolenaar1c991142020-07-04 13:15:31 +02002881 // isolate one name
2882 exp_name = p;
2883 while (eval_isnamec(*p))
2884 ++p;
2885 cc = *p;
2886 *p = NUL;
2887
Bram Moolenaaredba7072021-03-13 21:14:18 +01002888 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
2889 cctx, TRUE);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002890 *p = cc;
2891 p = skipwhite(p);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002892 *end = p;
2893
Bram Moolenaar529fb5a2021-04-01 12:57:57 +02002894 if (idx < 0)
2895 {
2896 if (*p == '(' && ufunc != NULL)
2897 {
2898 generate_PUSHFUNC(cctx, ufunc->uf_name, import->imp_type);
2899 return OK;
2900 }
2901 return FAIL;
2902 }
2903
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002904 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2905 import->imp_sid,
2906 idx,
2907 type);
2908 }
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002909 else if (import->imp_funcname != NULL)
2910 generate_PUSHFUNC(cctx, import->imp_funcname, import->imp_type);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002911 else
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002912 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2913 import->imp_sid,
2914 import->imp_var_vals_idx,
2915 import->imp_type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002916 return OK;
2917 }
2918
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002919 if (error)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002920 semsg(_(e_item_not_found_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002921 return FAIL;
2922}
2923
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002924 static int
2925generate_funcref(cctx_T *cctx, char_u *name)
2926{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002927 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002928
2929 if (ufunc == NULL)
2930 return FAIL;
2931
Bram Moolenaarb8070e32020-07-23 20:56:04 +02002932 // Need to compile any default values to get the argument types.
Bram Moolenaare5ea3462021-01-25 21:01:48 +01002933 if (func_needs_compiling(ufunc, PROFILING(ufunc))
2934 && compile_def_function(ufunc, TRUE, PROFILING(ufunc), NULL)
Bram Moolenaarb2049902021-01-24 12:53:53 +01002935 == FAIL)
2936 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002937 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002938}
2939
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002940/*
2941 * Compile a variable name into a load instruction.
2942 * "end" points to just after the name.
Bram Moolenaar0f769812020-09-12 18:32:34 +02002943 * "is_expr" is TRUE when evaluating an expression, might be a funcref.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002944 * When "error" is FALSE do not give an error when not found.
2945 */
2946 static int
Bram Moolenaar0f769812020-09-12 18:32:34 +02002947compile_load(
2948 char_u **arg,
2949 char_u *end_arg,
2950 cctx_T *cctx,
2951 int is_expr,
2952 int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002953{
2954 type_T *type;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002955 char_u *name = NULL;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002956 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002957 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002958 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002959
2960 if (*(*arg + 1) == ':')
2961 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002962 if (end <= *arg + 2)
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002963 {
2964 isntype_T isn_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002965
Bram Moolenaarfa596382021-04-07 21:58:16 +02002966 // load dictionary of namespace
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002967 switch (**arg)
2968 {
2969 case 'g': isn_type = ISN_LOADGDICT; break;
2970 case 'w': isn_type = ISN_LOADWDICT; break;
2971 case 't': isn_type = ISN_LOADTDICT; break;
2972 case 'b': isn_type = ISN_LOADBDICT; break;
2973 default:
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002974 semsg(_(e_namespace_not_supported_str), *arg);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002975 goto theend;
2976 }
2977 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
2978 goto theend;
2979 res = OK;
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002980 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002981 else
2982 {
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002983 isntype_T isn_type = ISN_DROP;
2984
Bram Moolenaarfa596382021-04-07 21:58:16 +02002985 // load namespaced variable
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002986 name = vim_strnsave(*arg + 2, end - (*arg + 2));
2987 if (name == NULL)
2988 return FAIL;
2989
2990 switch (**arg)
2991 {
2992 case 'v': res = generate_LOADV(cctx, name, error);
2993 break;
Bram Moolenaarfa596382021-04-07 21:58:16 +02002994 case 's': if (is_expr && ASCII_ISUPPER(*name)
2995 && find_func(name, FALSE, cctx) != NULL)
2996 res = generate_funcref(cctx, name);
2997 else
2998 res = compile_load_scriptvar(cctx, name,
Bram Moolenaarca51cc02021-04-01 21:38:53 +02002999 NULL, &end, error);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003000 break;
Bram Moolenaar03290b82020-12-19 16:30:44 +01003001 case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
Bram Moolenaarfa596382021-04-07 21:58:16 +02003002 {
3003 if (is_expr && ASCII_ISUPPER(*name)
3004 && find_func(name, FALSE, cctx) != NULL)
3005 res = generate_funcref(cctx, name);
3006 else
3007 isn_type = ISN_LOADG;
3008 }
Bram Moolenaar03290b82020-12-19 16:30:44 +01003009 else
3010 {
3011 isn_type = ISN_LOADAUTO;
3012 vim_free(name);
3013 name = vim_strnsave(*arg, end - *arg);
3014 if (name == NULL)
3015 return FAIL;
3016 }
3017 break;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003018 case 'w': isn_type = ISN_LOADW; break;
3019 case 't': isn_type = ISN_LOADT; break;
3020 case 'b': isn_type = ISN_LOADB; break;
Bram Moolenaar918a4242020-12-06 14:37:08 +01003021 default: // cannot happen, just in case
3022 semsg(_(e_namespace_not_supported_str), *arg);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003023 goto theend;
3024 }
3025 if (isn_type != ISN_DROP)
3026 {
3027 // Global, Buffer-local, Window-local and Tabpage-local
3028 // variables can be defined later, thus we don't check if it
Bram Moolenaarfa596382021-04-07 21:58:16 +02003029 // exists, give an error at runtime.
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003030 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
3031 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003032 }
3033 }
3034 else
3035 {
3036 size_t len = end - *arg;
3037 int idx;
3038 int gen_load = FALSE;
Bram Moolenaarab360522021-01-10 14:02:28 +01003039 int gen_load_outer = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003040
3041 name = vim_strnsave(*arg, end - *arg);
3042 if (name == NULL)
3043 return FAIL;
3044
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02003045 if (arg_exists(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003046 {
Bram Moolenaarab360522021-01-10 14:02:28 +01003047 if (gen_load_outer == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02003048 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003049 }
3050 else
3051 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01003052 lvar_T lvar;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02003053
Bram Moolenaar709664c2020-12-12 14:33:41 +01003054 if (lookup_local(*arg, len, &lvar, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003055 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01003056 type = lvar.lv_type;
3057 idx = lvar.lv_idx;
Bram Moolenaarab360522021-01-10 14:02:28 +01003058 if (lvar.lv_from_outer != 0)
3059 gen_load_outer = lvar.lv_from_outer;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003060 else
3061 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003062 }
3063 else
3064 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003065 // "var" can be script-local even without using "s:" if it
Bram Moolenaar53900992020-08-22 19:02:02 +02003066 // already exists in a Vim9 script or when it's imported.
Bram Moolenaar15e5e532021-04-07 21:21:13 +02003067 if (script_var_exists(*arg, len, cctx) == OK
Bram Moolenaar53900992020-08-22 19:02:02 +02003068 || find_imported(name, 0, cctx) != NULL)
3069 res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003070
Bram Moolenaar0f769812020-09-12 18:32:34 +02003071 // When evaluating an expression and the name starts with an
Bram Moolenaarfa596382021-04-07 21:58:16 +02003072 // uppercase letter it can be a user defined function.
3073 // generate_funcref() will fail if the function can't be found.
3074 if (res == FAIL && is_expr && ASCII_ISUPPER(*name))
Bram Moolenaara5565e42020-05-09 15:44:01 +02003075 res = generate_funcref(cctx, name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003076 }
3077 }
3078 if (gen_load)
3079 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarab360522021-01-10 14:02:28 +01003080 if (gen_load_outer > 0)
Bram Moolenaarfd777482020-08-12 19:42:01 +02003081 {
Bram Moolenaarab360522021-01-10 14:02:28 +01003082 res = generate_LOADOUTER(cctx, idx, gen_load_outer, type);
Bram Moolenaarfd777482020-08-12 19:42:01 +02003083 cctx->ctx_outer_used = TRUE;
3084 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003085 }
3086
3087 *arg = end;
3088
3089theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01003090 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003091 semsg(_(e_variable_not_found_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003092 vim_free(name);
3093 return res;
3094}
3095
3096/*
3097 * Compile the argument expressions.
3098 * "arg" points to just after the "(" and is advanced to after the ")"
3099 */
3100 static int
3101compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
3102{
Bram Moolenaar2c330432020-04-13 14:41:35 +02003103 char_u *p = *arg;
3104 char_u *whitep = *arg;
Bram Moolenaar10e4f122020-09-20 22:43:52 +02003105 int must_end = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003106
Bram Moolenaare6085c52020-04-12 20:19:16 +02003107 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003108 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003109 if (may_get_next_line(whitep, &p, cctx) == FAIL)
3110 goto failret;
Bram Moolenaare6085c52020-04-12 20:19:16 +02003111 if (*p == ')')
3112 {
3113 *arg = p + 1;
3114 return OK;
3115 }
Bram Moolenaar10e4f122020-09-20 22:43:52 +02003116 if (must_end)
3117 {
3118 semsg(_(e_missing_comma_before_argument_str), p);
3119 return FAIL;
3120 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02003121
Bram Moolenaara5565e42020-05-09 15:44:01 +02003122 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003123 return FAIL;
3124 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003125
3126 if (*p != ',' && *skipwhite(p) == ',')
3127 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003128 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003129 p = skipwhite(p);
3130 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003131 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003132 {
3133 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02003134 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003135 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003136 }
Bram Moolenaar10e4f122020-09-20 22:43:52 +02003137 else
3138 must_end = TRUE;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003139 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003140 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003141 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003142failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02003143 emsg(_(e_missing_close));
3144 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003145}
3146
3147/*
3148 * Compile a function call: name(arg1, arg2)
3149 * "arg" points to "name", "arg + varlen" to the "(".
3150 * "argcount_init" is 1 for "value->method()"
3151 * Instructions:
3152 * EVAL arg1
3153 * EVAL arg2
3154 * BCALL / DCALL / UCALL
3155 */
3156 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003157compile_call(
3158 char_u **arg,
3159 size_t varlen,
3160 cctx_T *cctx,
3161 ppconst_T *ppconst,
3162 int argcount_init)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003163{
3164 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01003165 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003166 int argcount = argcount_init;
3167 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003168 char_u fname_buf[FLEN_FIXED + 1];
3169 char_u *tofree = NULL;
3170 int error = FCERR_NONE;
Bram Moolenaarb3a01942020-11-17 19:56:09 +01003171 ufunc_T *ufunc = NULL;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003172 int res = FAIL;
Bram Moolenaara1773442020-08-12 15:21:22 +02003173 int is_autoload;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003174
Bram Moolenaara5565e42020-05-09 15:44:01 +02003175 // we can evaluate "has('name')" at compile time
3176 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
3177 {
3178 char_u *s = skipwhite(*arg + varlen + 1);
3179 typval_T argvars[2];
3180
3181 argvars[0].v_type = VAR_UNKNOWN;
3182 if (*s == '"')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003183 (void)eval_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003184 else if (*s == '\'')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003185 (void)eval_lit_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003186 s = skipwhite(s);
Bram Moolenaar8cebd432020-11-08 12:49:47 +01003187 if (*s == ')' && argvars[0].v_type == VAR_STRING
3188 && !dynamic_feature(argvars[0].vval.v_string))
Bram Moolenaara5565e42020-05-09 15:44:01 +02003189 {
3190 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
3191
3192 *arg = s + 1;
3193 argvars[1].v_type = VAR_UNKNOWN;
3194 tv->v_type = VAR_NUMBER;
3195 tv->vval.v_number = 0;
3196 f_has(argvars, tv);
3197 clear_tv(&argvars[0]);
3198 ++ppconst->pp_used;
3199 return OK;
3200 }
Bram Moolenaar497f76b2020-05-09 16:44:22 +02003201 clear_tv(&argvars[0]);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003202 }
3203
3204 if (generate_ppconst(cctx, ppconst) == FAIL)
3205 return FAIL;
3206
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003207 if (varlen >= sizeof(namebuf))
3208 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003209 semsg(_(e_name_too_long_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003210 return FAIL;
3211 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003212 vim_strncpy(namebuf, *arg, varlen);
3213 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003214
3215 *arg = skipwhite(*arg + varlen + 1);
3216 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003217 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003218
Bram Moolenaar03290b82020-12-19 16:30:44 +01003219 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
Bram Moolenaara1773442020-08-12 15:21:22 +02003220 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003221 {
3222 int idx;
3223
3224 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003225 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003226 if (idx >= 0)
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003227 {
Bram Moolenaar3b690062021-02-01 20:14:51 +01003228 if (STRCMP(name, "flatten") == 0)
3229 {
3230 emsg(_(e_cannot_use_flatten_in_vim9_script));
3231 goto theend;
3232 }
3233
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003234 if (STRCMP(name, "add") == 0 && argcount == 2)
3235 {
3236 garray_T *stack = &cctx->ctx_type_stack;
3237 type_T *type = ((type_T **)stack->ga_data)[
3238 stack->ga_len - 2];
3239
Bram Moolenaare88c8e82020-11-01 17:03:37 +01003240 // add() can be compiled to instructions if we know the type
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003241 if (type->tt_type == VAR_LIST)
3242 {
3243 // inline "add(list, item)" so that the type can be checked
3244 res = generate_LISTAPPEND(cctx);
3245 idx = -1;
3246 }
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02003247 else if (type->tt_type == VAR_BLOB)
3248 {
3249 // inline "add(blob, nr)" so that the type can be checked
3250 res = generate_BLOBAPPEND(cctx);
3251 idx = -1;
3252 }
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003253 }
3254
3255 if (idx >= 0)
3256 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
3257 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003258 else
3259 semsg(_(e_unknownfunc), namebuf);
3260 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003261 }
3262
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01003263 // An argument or local variable can be a function reference, this
3264 // overrules a function name.
Bram Moolenaar709664c2020-12-12 14:33:41 +01003265 if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01003266 && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003267 {
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01003268 // If we can find the function by name generate the right call.
3269 // Skip global functions here, a local funcref takes precedence.
3270 ufunc = find_func(name, FALSE, cctx);
3271 if (ufunc != NULL && !func_is_global(ufunc))
3272 {
3273 res = generate_CALL(cctx, ufunc, argcount);
3274 goto theend;
3275 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003276 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003277
3278 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02003279 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaara1773442020-08-12 15:21:22 +02003280 // Not for eome#Func(), it will be loaded later.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003281 p = namebuf;
Bram Moolenaara1773442020-08-12 15:21:22 +02003282 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload
Bram Moolenaar0f769812020-09-12 18:32:34 +02003283 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003284 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003285 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003286 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003287
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003288 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003289 goto theend;
3290 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003291
Bram Moolenaar0f769812020-09-12 18:32:34 +02003292 // If we can find a global function by name generate the right call.
3293 if (ufunc != NULL)
3294 {
3295 res = generate_CALL(cctx, ufunc, argcount);
3296 goto theend;
3297 }
3298
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003299 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003300 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaara1773442020-08-12 15:21:22 +02003301 if (STRNCMP(namebuf, "g:", 2) == 0 || is_autoload)
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003302 res = generate_UCALL(cctx, name, argcount);
3303 else
3304 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003305
3306theend:
3307 vim_free(tofree);
3308 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003309}
3310
3311// like NAMESPACE_CHAR but with 'a' and 'l'.
3312#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
3313
3314/*
3315 * Find the end of a variable or function name. Unlike find_name_end() this
3316 * does not recognize magic braces.
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003317 * When "use_namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003318 * Return a pointer to just after the name. Equal to "arg" if there is no
3319 * valid name.
3320 */
Bram Moolenaar2bede172020-11-19 18:53:18 +01003321 char_u *
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003322to_name_end(char_u *arg, int use_namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003323{
3324 char_u *p;
3325
3326 // Quick check for valid starting character.
3327 if (!eval_isnamec1(*arg))
3328 return arg;
3329
3330 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
3331 // Include a namespace such as "s:var" and "v:var". But "n:" is not
3332 // and can be used in slice "[n:]".
3333 if (*p == ':' && (p != arg + 1
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003334 || !use_namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003335 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
3336 break;
3337 return p;
3338}
3339
3340/*
3341 * Like to_name_end() but also skip over a list or dict constant.
Bram Moolenaar1c991142020-07-04 13:15:31 +02003342 * This intentionally does not handle line continuation.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003343 */
3344 char_u *
3345to_name_const_end(char_u *arg)
3346{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003347 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003348 typval_T rettv;
3349
3350 if (p == arg && *arg == '[')
3351 {
3352
3353 // Can be "[1, 2, 3]->Func()".
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003354 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003355 p = arg;
3356 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003357 return p;
3358}
3359
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003360/*
3361 * parse a list: [expr, expr]
3362 * "*arg" points to the '['.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003363 * ppconst->pp_is_const is set if all items are a constant.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003364 */
3365 static int
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003366compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003367{
3368 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003369 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003370 int count = 0;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003371 int is_const;
3372 int is_all_const = TRUE; // reset when non-const encountered
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003373
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003374 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003375 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003376 if (may_get_next_line(whitep, &p, cctx) == FAIL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01003377 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003378 semsg(_(e_list_end), *arg);
3379 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003380 }
Bram Moolenaardb199212020-08-12 18:01:53 +02003381 if (*p == ',')
3382 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003383 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
Bram Moolenaardb199212020-08-12 18:01:53 +02003384 return FAIL;
3385 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003386 if (*p == ']')
3387 {
3388 ++p;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003389 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01003390 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003391 if (compile_expr0_ext(&p, cctx, &is_const) == FAIL)
Bram Moolenaarc1f00662020-10-03 13:41:53 +02003392 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003393 if (!is_const)
3394 is_all_const = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003395 ++count;
3396 if (*p == ',')
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003397 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003398 ++p;
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003399 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
3400 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003401 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003402 return FAIL;
3403 }
3404 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003405 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003406 p = skipwhite(p);
3407 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003408 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003409
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003410 ppconst->pp_is_const = is_all_const;
3411 return generate_NEWLIST(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003412}
3413
3414/*
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01003415 * Parse a lambda: "(arg, arg) => expr"
Bram Moolenaar7a6eaa02021-03-21 20:53:29 +01003416 * "*arg" points to the '('.
Bram Moolenaare462f522020-12-27 14:43:30 +01003417 * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003418 */
3419 static int
3420compile_lambda(char_u **arg, cctx_T *cctx)
3421{
Bram Moolenaare462f522020-12-27 14:43:30 +01003422 int r;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003423 typval_T rettv;
3424 ufunc_T *ufunc;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003425 evalarg_T evalarg;
3426
3427 CLEAR_FIELD(evalarg);
3428 evalarg.eval_flags = EVAL_EVALUATE;
3429 evalarg.eval_cctx = cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003430
3431 // Get the funcref in "rettv".
Bram Moolenaare462f522020-12-27 14:43:30 +01003432 r = get_lambda_tv(arg, &rettv, TRUE, &evalarg);
3433 if (r != OK)
Bram Moolenaar2ea79ad2020-10-18 23:32:13 +02003434 {
3435 clear_evalarg(&evalarg, NULL);
Bram Moolenaare462f522020-12-27 14:43:30 +01003436 return r;
Bram Moolenaar2ea79ad2020-10-18 23:32:13 +02003437 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01003438
Bram Moolenaar65c44152020-12-24 15:14:01 +01003439 // "rettv" will now be a partial referencing the function.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003440 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003441 ++ufunc->uf_refcount;
3442 clear_tv(&rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003443
Bram Moolenaar65c44152020-12-24 15:14:01 +01003444 // Compile the function into instructions.
Bram Moolenaare5ea3462021-01-25 21:01:48 +01003445 compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003446
Bram Moolenaar67da21a2021-03-21 22:12:34 +01003447 // evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
3448 // points into it. Point to the original line to avoid a dangling pointer.
3449 if (evalarg.eval_tofree_cmdline != NULL)
3450 {
3451 size_t off = *arg - evalarg.eval_tofree_cmdline;
3452
3453 *arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
3454 + off;
3455 }
3456
Bram Moolenaar8e2730a2020-07-08 22:01:49 +02003457 clear_evalarg(&evalarg, NULL);
3458
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02003459 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar5a849da2020-08-08 16:47:30 +02003460 {
3461 // The return type will now be known.
3462 set_function_type(ufunc);
3463
Bram Moolenaarfdeab652020-09-19 15:16:50 +02003464 // The function reference count will be 1. When the ISN_FUNCREF
3465 // instruction is deleted the reference count is decremented and the
3466 // function is freed.
Bram Moolenaar5a849da2020-08-08 16:47:30 +02003467 return generate_FUNCREF(cctx, ufunc);
3468 }
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003469
3470 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003471 return FAIL;
3472}
3473
3474/*
Bram Moolenaare0de1712020-12-02 17:36:54 +01003475 * parse a dict: {key: val, [key]: val}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003476 * "*arg" points to the '{'.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003477 * ppconst->pp_is_const is set if all item values are a constant.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003478 */
3479 static int
Bram Moolenaare0de1712020-12-02 17:36:54 +01003480compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003481{
3482 garray_T *instr = &cctx->ctx_instr;
3483 int count = 0;
3484 dict_T *d = dict_alloc();
3485 dictitem_T *item;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003486 char_u *whitep = *arg + 1;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003487 char_u *p;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003488 int is_const;
3489 int is_all_const = TRUE; // reset when non-const encountered
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003490
3491 if (d == NULL)
3492 return FAIL;
Bram Moolenaard62d87d2021-01-04 17:40:12 +01003493 if (generate_ppconst(cctx, ppconst) == FAIL)
3494 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003495 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003496 {
Bram Moolenaar2bede172020-11-19 18:53:18 +01003497 char_u *key = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003498
Bram Moolenaar23c55272020-06-21 16:58:13 +02003499 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003500 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003501 *arg = NULL;
3502 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003503 }
3504
3505 if (**arg == '}')
3506 break;
3507
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003508 if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003509 {
Bram Moolenaar2bede172020-11-19 18:53:18 +01003510 isn_T *isn;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003511
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003512 // {[expr]: value} uses an evaluated key.
Bram Moolenaare0de1712020-12-02 17:36:54 +01003513 *arg = skipwhite(*arg + 1);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003514 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003515 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003516 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01003517 if (isn->isn_type == ISN_PUSHNR)
3518 {
3519 char buf[NUMBUFLEN];
3520
3521 // Convert to string at compile time.
3522 vim_snprintf(buf, NUMBUFLEN, "%lld", isn->isn_arg.number);
3523 isn->isn_type = ISN_PUSHS;
3524 isn->isn_arg.string = vim_strsave((char_u *)buf);
3525 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003526 if (isn->isn_type == ISN_PUSHS)
3527 key = isn->isn_arg.string;
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01003528 else if (may_generate_2STRING(-1, cctx) == FAIL)
3529 return FAIL;
Bram Moolenaare0de1712020-12-02 17:36:54 +01003530 *arg = skipwhite(*arg);
3531 if (**arg != ']')
Bram Moolenaar2bede172020-11-19 18:53:18 +01003532 {
Bram Moolenaare0de1712020-12-02 17:36:54 +01003533 emsg(_(e_missing_matching_bracket_after_dict_key));
3534 return FAIL;
Bram Moolenaar2bede172020-11-19 18:53:18 +01003535 }
Bram Moolenaare0de1712020-12-02 17:36:54 +01003536 ++*arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003537 }
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003538 else
3539 {
3540 // {"name": value},
3541 // {'name': value},
3542 // {name: value} use "name" as a literal key
3543 key = get_literal_key(arg);
3544 if (key == NULL)
3545 return FAIL;
3546 if (generate_PUSHS(cctx, key) == FAIL)
3547 return FAIL;
3548 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003549
3550 // Check for duplicate keys, if using string keys.
3551 if (key != NULL)
3552 {
3553 item = dict_find(d, key, -1);
3554 if (item != NULL)
3555 {
3556 semsg(_(e_duplicate_key), key);
3557 goto failret;
3558 }
3559 item = dictitem_alloc(key);
3560 if (item != NULL)
3561 {
3562 item->di_tv.v_type = VAR_UNKNOWN;
3563 item->di_tv.v_lock = 0;
3564 if (dict_add(d, item) == FAIL)
3565 dictitem_free(item);
3566 }
3567 }
3568
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003569 if (**arg != ':')
3570 {
Bram Moolenaar17a836c2020-08-12 17:35:58 +02003571 if (*skipwhite(*arg) == ':')
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003572 semsg(_(e_no_white_space_allowed_before_str_str), ":", *arg);
Bram Moolenaar17a836c2020-08-12 17:35:58 +02003573 else
3574 semsg(_(e_missing_dict_colon), *arg);
3575 return FAIL;
3576 }
3577 whitep = *arg + 1;
3578 if (!IS_WHITE_OR_NUL(*whitep))
3579 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003580 semsg(_(e_white_space_required_after_str_str), ":", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003581 return FAIL;
3582 }
3583
Bram Moolenaar23c55272020-06-21 16:58:13 +02003584 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003585 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003586 *arg = NULL;
3587 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003588 }
3589
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003590 if (compile_expr0_ext(arg, cctx, &is_const) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003591 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003592 if (!is_const)
3593 is_all_const = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003594 ++count;
3595
Bram Moolenaar2c330432020-04-13 14:41:35 +02003596 whitep = *arg;
Bram Moolenaar23c55272020-06-21 16:58:13 +02003597 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003598 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003599 *arg = NULL;
3600 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003601 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003602 if (**arg == '}')
3603 break;
3604 if (**arg != ',')
3605 {
3606 semsg(_(e_missing_dict_comma), *arg);
3607 goto failret;
3608 }
Bram Moolenaarc3d6e8a2020-08-12 18:34:28 +02003609 if (IS_WHITE_OR_NUL(*whitep))
3610 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003611 semsg(_(e_no_white_space_allowed_before_str_str), ",", whitep);
Bram Moolenaarc3d6e8a2020-08-12 18:34:28 +02003612 return FAIL;
3613 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003614 whitep = *arg + 1;
Bram Moolenaar9a13e182020-10-19 21:45:07 +02003615 if (!IS_WHITE_OR_NUL(*whitep))
3616 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003617 semsg(_(e_white_space_required_after_str_str), ",", *arg);
Bram Moolenaar9a13e182020-10-19 21:45:07 +02003618 return FAIL;
3619 }
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003620 *arg = skipwhite(whitep);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003621 }
3622
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003623 *arg = *arg + 1;
3624
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003625 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02003626 p = skipwhite(*arg);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003627 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003628 *arg += STRLEN(*arg);
3629
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003630 dict_unref(d);
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003631 ppconst->pp_is_const = is_all_const;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003632 return generate_NEWDICT(cctx, count);
3633
3634failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003635 if (*arg == NULL)
Bram Moolenaar44aefff2020-10-05 19:23:59 +02003636 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003637 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar44aefff2020-10-05 19:23:59 +02003638 *arg = (char_u *)"";
3639 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003640 dict_unref(d);
3641 return FAIL;
3642}
3643
3644/*
3645 * Compile "&option".
3646 */
3647 static int
3648compile_get_option(char_u **arg, cctx_T *cctx)
3649{
3650 typval_T rettv;
3651 char_u *start = *arg;
3652 int ret;
3653
3654 // parse the option and get the current value to get the type.
3655 rettv.v_type = VAR_UNKNOWN;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003656 ret = eval_option(arg, &rettv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003657 if (ret == OK)
3658 {
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003659 // include the '&' in the name, eval_option() expects it.
Bram Moolenaard5ea8f02021-01-01 14:49:15 +01003660 char_u *name = vim_strnsave(start, *arg - start);
3661 type_T *type = rettv.v_type == VAR_BOOL ? &t_bool
3662 : rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003663
3664 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
3665 vim_free(name);
3666 }
3667 clear_tv(&rettv);
3668
3669 return ret;
3670}
3671
3672/*
3673 * Compile "$VAR".
3674 */
3675 static int
3676compile_get_env(char_u **arg, cctx_T *cctx)
3677{
3678 char_u *start = *arg;
3679 int len;
3680 int ret;
3681 char_u *name;
3682
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003683 ++*arg;
3684 len = get_env_len(arg);
3685 if (len == 0)
3686 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003687 semsg(_(e_syntax_error_at_str), start - 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003688 return FAIL;
3689 }
3690
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003691 // include the '$' in the name, eval_env_var() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003692 name = vim_strnsave(start, len + 1);
3693 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
3694 vim_free(name);
3695 return ret;
3696}
3697
3698/*
3699 * Compile "@r".
3700 */
3701 static int
3702compile_get_register(char_u **arg, cctx_T *cctx)
3703{
3704 int ret;
3705
3706 ++*arg;
3707 if (**arg == NUL)
3708 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003709 semsg(_(e_syntax_error_at_str), *arg - 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003710 return FAIL;
3711 }
Bram Moolenaar7226e5b2020-08-02 17:33:26 +02003712 if (!valid_yank_reg(**arg, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003713 {
3714 emsg_invreg(**arg);
3715 return FAIL;
3716 }
3717 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3718 ++*arg;
3719 return ret;
3720}
3721
3722/*
3723 * Apply leading '!', '-' and '+' to constant "rettv".
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003724 * When "numeric_only" is TRUE do not apply '!'.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003725 */
3726 static int
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003727apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003728{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003729 char_u *p = *end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003730
3731 // this works from end to start
3732 while (p > start)
3733 {
3734 --p;
3735 if (*p == '-' || *p == '+')
3736 {
3737 // only '-' has an effect, for '+' we only check the type
3738#ifdef FEAT_FLOAT
3739 if (rettv->v_type == VAR_FLOAT)
3740 {
3741 if (*p == '-')
3742 rettv->vval.v_float = -rettv->vval.v_float;
3743 }
3744 else
3745#endif
3746 {
3747 varnumber_T val;
3748 int error = FALSE;
3749
3750 // tv_get_number_chk() accepts a string, but we don't want that
3751 // here
3752 if (check_not_string(rettv) == FAIL)
3753 return FAIL;
3754 val = tv_get_number_chk(rettv, &error);
3755 clear_tv(rettv);
3756 if (error)
3757 return FAIL;
3758 if (*p == '-')
3759 val = -val;
3760 rettv->v_type = VAR_NUMBER;
3761 rettv->vval.v_number = val;
3762 }
3763 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003764 else if (numeric_only)
3765 {
3766 ++p;
3767 break;
3768 }
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003769 else if (*p == '!')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003770 {
3771 int v = tv2bool(rettv);
3772
3773 // '!' is permissive in the type.
3774 clear_tv(rettv);
3775 rettv->v_type = VAR_BOOL;
3776 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3777 }
3778 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003779 *end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003780 return OK;
3781}
3782
3783/*
3784 * Recognize v: variables that are constants and set "rettv".
3785 */
3786 static void
3787get_vim_constant(char_u **arg, typval_T *rettv)
3788{
3789 if (STRNCMP(*arg, "v:true", 6) == 0)
3790 {
3791 rettv->v_type = VAR_BOOL;
3792 rettv->vval.v_number = VVAL_TRUE;
3793 *arg += 6;
3794 }
3795 else if (STRNCMP(*arg, "v:false", 7) == 0)
3796 {
3797 rettv->v_type = VAR_BOOL;
3798 rettv->vval.v_number = VVAL_FALSE;
3799 *arg += 7;
3800 }
3801 else if (STRNCMP(*arg, "v:null", 6) == 0)
3802 {
3803 rettv->v_type = VAR_SPECIAL;
3804 rettv->vval.v_number = VVAL_NULL;
3805 *arg += 6;
3806 }
3807 else if (STRNCMP(*arg, "v:none", 6) == 0)
3808 {
3809 rettv->v_type = VAR_SPECIAL;
3810 rettv->vval.v_number = VVAL_NONE;
3811 *arg += 6;
3812 }
3813}
3814
Bram Moolenaar657137c2021-01-09 15:45:23 +01003815 exprtype_T
Bram Moolenaar61a89812020-05-07 16:58:17 +02003816get_compare_type(char_u *p, int *len, int *type_is)
3817{
Bram Moolenaar657137c2021-01-09 15:45:23 +01003818 exprtype_T type = EXPR_UNKNOWN;
Bram Moolenaar61a89812020-05-07 16:58:17 +02003819 int i;
3820
3821 switch (p[0])
3822 {
3823 case '=': if (p[1] == '=')
3824 type = EXPR_EQUAL;
3825 else if (p[1] == '~')
3826 type = EXPR_MATCH;
3827 break;
3828 case '!': if (p[1] == '=')
3829 type = EXPR_NEQUAL;
3830 else if (p[1] == '~')
3831 type = EXPR_NOMATCH;
3832 break;
3833 case '>': if (p[1] != '=')
3834 {
3835 type = EXPR_GREATER;
3836 *len = 1;
3837 }
3838 else
3839 type = EXPR_GEQUAL;
3840 break;
3841 case '<': if (p[1] != '=')
3842 {
3843 type = EXPR_SMALLER;
3844 *len = 1;
3845 }
3846 else
3847 type = EXPR_SEQUAL;
3848 break;
3849 case 'i': if (p[1] == 's')
3850 {
3851 // "is" and "isnot"; but not a prefix of a name
3852 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3853 *len = 5;
3854 i = p[*len];
3855 if (!isalnum(i) && i != '_')
3856 {
3857 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3858 *type_is = TRUE;
3859 }
3860 }
3861 break;
3862 }
3863 return type;
3864}
3865
3866/*
Bram Moolenaar7e368202020-12-25 21:56:57 +01003867 * Skip over an expression, ignoring most errors.
3868 */
3869 static void
3870skip_expr_cctx(char_u **arg, cctx_T *cctx)
3871{
3872 evalarg_T evalarg;
3873
3874 CLEAR_FIELD(evalarg);
3875 evalarg.eval_cctx = cctx;
3876 skip_expr(arg, &evalarg);
3877}
3878
3879/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003880 * Compile code to apply '-', '+' and '!'.
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003881 * When "numeric_only" is TRUE do not apply '!'.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003882 */
3883 static int
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003884compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003885{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003886 char_u *p = *end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003887
3888 // this works from end to start
3889 while (p > start)
3890 {
3891 --p;
Bram Moolenaar79cdf802020-11-18 17:39:05 +01003892 while (VIM_ISWHITE(*p))
3893 --p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003894 if (*p == '-' || *p == '+')
3895 {
3896 int negate = *p == '-';
3897 isn_T *isn;
3898
3899 // TODO: check type
3900 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3901 {
3902 --p;
3903 if (*p == '-')
3904 negate = !negate;
3905 }
3906 // only '-' has an effect, for '+' we only check the type
3907 if (negate)
3908 isn = generate_instr(cctx, ISN_NEGATENR);
3909 else
3910 isn = generate_instr(cctx, ISN_CHECKNR);
3911 if (isn == NULL)
3912 return FAIL;
3913 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003914 else if (numeric_only)
3915 {
3916 ++p;
3917 break;
3918 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003919 else
3920 {
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003921 int invert = *p == '!';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003922
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003923 while (p > start && (p[-1] == '!' || VIM_ISWHITE(p[-1])))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003924 {
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003925 if (p[-1] == '!')
3926 invert = !invert;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003927 --p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003928 }
3929 if (generate_2BOOL(cctx, invert) == FAIL)
3930 return FAIL;
3931 }
3932 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003933 *end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003934 return OK;
3935}
3936
3937/*
Bram Moolenaar7e368202020-12-25 21:56:57 +01003938 * Compile "(expression)": recursive!
3939 * Return FAIL/OK.
3940 */
3941 static int
3942compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3943{
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003944 int ret;
Bram Moolenaar24156692021-01-14 20:35:49 +01003945 char_u *p = *arg + 1;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003946
Bram Moolenaar24156692021-01-14 20:35:49 +01003947 if (may_get_next_line_error(p, arg, cctx) == FAIL)
3948 return FAIL;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003949 if (ppconst->pp_used <= PPSIZE - 10)
3950 {
3951 ret = compile_expr1(arg, cctx, ppconst);
3952 }
3953 else
3954 {
3955 // Not enough space in ppconst, flush constants.
3956 if (generate_ppconst(cctx, ppconst) == FAIL)
3957 return FAIL;
3958 ret = compile_expr0(arg, cctx);
3959 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003960 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
3961 return FAIL;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003962 if (**arg == ')')
3963 ++*arg;
3964 else if (ret == OK)
3965 {
3966 emsg(_(e_missing_close));
3967 ret = FAIL;
3968 }
3969 return ret;
3970}
3971
3972/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003973 * Compile whatever comes after "name" or "name()".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003974 * Advances "*arg" only when something was recognized.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003975 */
3976 static int
3977compile_subscript(
3978 char_u **arg,
3979 cctx_T *cctx,
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003980 char_u *start_leader,
3981 char_u **end_leader,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003982 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003983{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003984 char_u *name_start = *end_leader;
3985
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003986 for (;;)
3987 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003988 char_u *p = skipwhite(*arg);
3989
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003990 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003991 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003992 char_u *next = peek_next_line_from_context(cctx);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003993
3994 // If a following line starts with "->{" or "->X" advance to that
3995 // line, so that a line break before "->" is allowed.
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003996 // Also if a following line starts with ".x".
3997 if (next != NULL &&
3998 ((next[0] == '-' && next[1] == '>'
3999 && (next[2] == '{' || ASCII_ISALPHA(next[2])))
Bram Moolenaarb13ab992020-07-27 21:43:28 +02004000 || (next[0] == '.' && eval_isdictc(next[1]))))
Bram Moolenaar23c55272020-06-21 16:58:13 +02004001 {
4002 next = next_line_from_context(cctx, TRUE);
4003 if (next == NULL)
4004 return FAIL;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004005 *arg = next;
4006 p = skipwhite(*arg);
Bram Moolenaar23c55272020-06-21 16:58:13 +02004007 }
4008 }
4009
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01004010 // Do not skip over white space to find the "(", "execute 'x' ()" is
Bram Moolenaar2d6b20d2020-07-25 19:30:59 +02004011 // not a function call.
4012 if (**arg == '(')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004013 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02004014 garray_T *stack = &cctx->ctx_type_stack;
4015 type_T *type;
4016 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004017
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004018 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004019 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004020 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004021
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004022 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02004023 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4024
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004025 *arg = skipwhite(p + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004026 if (compile_arguments(arg, cctx, &argcount) == FAIL)
4027 return FAIL;
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004028 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004029 return FAIL;
4030 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004031 else if (*p == '-' && p[1] == '>')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004032 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02004033 char_u *pstart = p;
4034
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004035 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004036 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004037 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004038
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004039 // something->method()
4040 // Apply the '!', '-' and '+' first:
4041 // -1.0->func() works like (-1.0)->func()
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004042 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004043 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004044
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004045 p += 2;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004046 *arg = skipwhite(p);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02004047 // No line break supported right after "->".
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01004048 if (**arg == '(')
Bram Moolenaar65c44152020-12-24 15:14:01 +01004049 {
Bram Moolenaar7e368202020-12-25 21:56:57 +01004050 int argcount = 1;
Bram Moolenaar2927c072021-04-05 19:41:21 +02004051 garray_T *stack = &cctx->ctx_type_stack;
4052 int type_idx_start = stack->ga_len;
Bram Moolenaar7e368202020-12-25 21:56:57 +01004053 type_T *type;
Bram Moolenaar2927c072021-04-05 19:41:21 +02004054 int expr_isn_start = cctx->ctx_instr.ga_len;
4055 int expr_isn_end;
4056 int arg_isn_count;
Bram Moolenaar7e368202020-12-25 21:56:57 +01004057
4058 // Funcref call: list->(Refs[2])(arg)
4059 // or lambda: list->((arg) => expr)(arg)
Bram Moolenaar2927c072021-04-05 19:41:21 +02004060 //
4061 // Fist compile the function expression.
4062 if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
Bram Moolenaar7e368202020-12-25 21:56:57 +01004063 return FAIL;
Bram Moolenaar2927c072021-04-05 19:41:21 +02004064
4065 // Remember the next instruction index, where the instructions
4066 // for arguments are being written.
4067 expr_isn_end = cctx->ctx_instr.ga_len;
4068
4069 // Compile the arguments.
Bram Moolenaar7e368202020-12-25 21:56:57 +01004070 if (**arg != '(')
4071 {
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01004072 if (*skipwhite(*arg) == '(')
4073 emsg(_(e_nowhitespace));
4074 else
4075 semsg(_(e_missing_paren), *arg);
Bram Moolenaar7e368202020-12-25 21:56:57 +01004076 return FAIL;
4077 }
Bram Moolenaar7e368202020-12-25 21:56:57 +01004078 *arg = skipwhite(*arg + 1);
4079 if (compile_arguments(arg, cctx, &argcount) == FAIL)
4080 return FAIL;
4081
Bram Moolenaar2927c072021-04-05 19:41:21 +02004082 // Move the instructions for the arguments to before the
4083 // instructions of the expression and move the type of the
4084 // expression after the argument types. This is what ISN_PCALL
4085 // expects.
Bram Moolenaar7e368202020-12-25 21:56:57 +01004086 stack = &cctx->ctx_type_stack;
Bram Moolenaar2927c072021-04-05 19:41:21 +02004087 arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end;
4088 if (arg_isn_count > 0)
4089 {
4090 int expr_isn_count = expr_isn_end - expr_isn_start;
4091 isn_T *isn = ALLOC_MULT(isn_T, expr_isn_count);
4092
4093 if (isn == NULL)
4094 return FAIL;
4095 mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data)
4096 + expr_isn_start,
4097 sizeof(isn_T) * expr_isn_count);
4098 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
4099 + expr_isn_start,
4100 ((isn_T *)cctx->ctx_instr.ga_data) + expr_isn_end,
4101 sizeof(isn_T) * arg_isn_count);
4102 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
4103 + expr_isn_start + arg_isn_count,
4104 isn, sizeof(isn_T) * expr_isn_count);
4105 vim_free(isn);
4106
4107 type = ((type_T **)stack->ga_data)[type_idx_start];
4108 mch_memmove(((type_T **)stack->ga_data) + type_idx_start,
4109 ((type_T **)stack->ga_data) + type_idx_start + 1,
4110 sizeof(type_T *)
4111 * (stack->ga_len - type_idx_start - 1));
4112 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
4113 }
4114
Bram Moolenaar7e368202020-12-25 21:56:57 +01004115 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4116 if (generate_PCALL(cctx, argcount,
4117 (char_u *)"[expression]", type, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004118 return FAIL;
4119 }
4120 else
4121 {
4122 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02004123 p = *arg;
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02004124 if (!eval_isnamec1(*p))
4125 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02004126 semsg(_(e_trailing_arg), pstart);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02004127 return FAIL;
4128 }
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02004129 if (ASCII_ISALPHA(*p) && p[1] == ':')
4130 p += 2;
Bram Moolenaarc5da1fb2020-08-05 15:43:44 +02004131 for ( ; eval_isnamec(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004132 ;
4133 if (*p != '(')
4134 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02004135 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004136 return FAIL;
4137 }
4138 // TODO: base value may not be the first argument
Bram Moolenaara5565e42020-05-09 15:44:01 +02004139 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004140 return FAIL;
4141 }
4142 }
Bram Moolenaarbadd8482020-07-31 22:38:17 +02004143 else if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004144 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004145 int is_slice = FALSE;
Bram Moolenaarb13af502020-02-17 21:12:08 +01004146
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004147 // list index: list[123]
Bram Moolenaara6e67e42020-05-15 23:36:40 +02004148 // dict member: dict[key]
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004149 // string index: text[123]
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004150 // blob index: blob[123]
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004151 // TODO: more arguments
4152 // TODO: recognize list or dict at runtime
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004153 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004154 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004155 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004156
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004157 ++p;
Bram Moolenaara7eedf32020-07-10 21:50:41 +02004158 if (may_get_next_line_error(p, arg, cctx) == FAIL)
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004159 return FAIL;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004160 if (**arg == ':')
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004161 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004162 // missing first index is equal to zero
4163 generate_PUSHNR(cctx, 0);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004164 }
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004165 else
4166 {
4167 if (compile_expr0(arg, cctx) == FAIL)
4168 return FAIL;
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004169 if (**arg == ':')
4170 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004171 semsg(_(e_white_space_required_before_and_after_str_at_str),
4172 ":", *arg);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004173 return FAIL;
4174 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004175 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004176 return FAIL;
4177 *arg = skipwhite(*arg);
4178 }
4179 if (**arg == ':')
4180 {
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004181 is_slice = TRUE;
4182 ++*arg;
4183 if (!IS_WHITE_OR_NUL(**arg) && **arg != ']')
4184 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004185 semsg(_(e_white_space_required_before_and_after_str_at_str),
4186 ":", *arg);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004187 return FAIL;
4188 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004189 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004190 return FAIL;
4191 if (**arg == ']')
4192 // missing second index is equal to end of string
4193 generate_PUSHNR(cctx, -1);
4194 else
4195 {
4196 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar918a4242020-12-06 14:37:08 +01004197 return FAIL;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004198 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004199 return FAIL;
4200 *arg = skipwhite(*arg);
4201 }
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004202 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004203
4204 if (**arg != ']')
4205 {
4206 emsg(_(e_missbrac));
4207 return FAIL;
4208 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01004209 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004210
Bram Moolenaare42939a2021-04-05 17:11:17 +02004211 if (compile_member(is_slice, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004212 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004213 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004214 else if (*p == '.' && p[1] != '.')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004215 {
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004216 // dictionary member: dict.name
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004217 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004218 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004219 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004220
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004221 *arg = p + 1;
Bram Moolenaar90193e62021-04-04 20:49:50 +02004222 if (IS_WHITE_OR_NUL(**arg))
Bram Moolenaarc1f00662020-10-03 13:41:53 +02004223 {
4224 emsg(_(e_missing_name_after_dot));
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004225 return FAIL;
Bram Moolenaarc1f00662020-10-03 13:41:53 +02004226 }
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004227 p = *arg;
Bram Moolenaarb13ab992020-07-27 21:43:28 +02004228 if (eval_isdictc(*p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004229 while (eval_isnamec(*p))
4230 MB_PTR_ADV(p);
4231 if (p == *arg)
4232 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004233 semsg(_(e_syntax_error_at_str), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004234 return FAIL;
4235 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004236 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004237 return FAIL;
4238 *arg = p;
4239 }
4240 else
4241 break;
4242 }
4243
4244 // TODO - see handle_subscript():
4245 // Turn "dict.Func" into a partial for "Func" bound to "dict".
4246 // Don't do this when "Func" is already a partial that was bound
4247 // explicitly (pt_auto is FALSE).
4248
4249 return OK;
4250}
4251
4252/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004253 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
4254 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004255 *
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004256 * If the value is a constant "ppconst->pp_used" will be non-zero.
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004257 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004258 *
4259 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004260 */
4261
4262/*
4263 * number number constant
4264 * 0zFFFFFFFF Blob constant
4265 * "string" string constant
4266 * 'string' literal string constant
4267 * &option-name option value
4268 * @r register contents
4269 * identifier variable value
4270 * function() function call
4271 * $VAR environment variable
4272 * (expression) nested expression
4273 * [expr, expr] List
Bram Moolenaare0de1712020-12-02 17:36:54 +01004274 * {key: val, [key]: val} Dictionary
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004275 *
4276 * Also handle:
4277 * ! in front logical NOT
4278 * - in front unary minus
4279 * + in front unary plus (ignored)
4280 * trailing (arg) funcref/partial call
4281 * trailing [] subscript in String or List
4282 * trailing .name entry in Dictionary
4283 * trailing ->name() method call
4284 */
4285 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004286compile_expr7(
4287 char_u **arg,
4288 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004289 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004290{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004291 char_u *start_leader, *end_leader;
4292 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004293 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02004294 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004295
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004296 ppconst->pp_is_const = FALSE;
4297
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004298 /*
4299 * Skip '!', '-' and '+' characters. They are handled later.
4300 */
4301 start_leader = *arg;
Bram Moolenaarb23279d2021-01-05 22:08:20 +01004302 if (eval_leader(arg, TRUE) == FAIL)
4303 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004304 end_leader = *arg;
4305
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004306 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004307 switch (**arg)
4308 {
4309 /*
4310 * Number constant.
4311 */
4312 case '0': // also for blob starting with 0z
4313 case '1':
4314 case '2':
4315 case '3':
4316 case '4':
4317 case '5':
4318 case '6':
4319 case '7':
4320 case '8':
4321 case '9':
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004322 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004323 return FAIL;
Bram Moolenaar4301a722020-08-11 20:51:08 +02004324 // Apply "-" and "+" just before the number now, right to
4325 // left. Matters especially when "->" follows. Stops at
4326 // '!'.
4327 if (apply_leader(rettv, TRUE,
4328 start_leader, &end_leader) == FAIL)
4329 {
4330 clear_tv(rettv);
4331 return FAIL;
4332 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004333 break;
4334
4335 /*
4336 * String constant: "string".
4337 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004338 case '"': if (eval_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004339 return FAIL;
4340 break;
4341
4342 /*
4343 * Literal string constant: 'str''ing'.
4344 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004345 case '\'': if (eval_lit_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004346 return FAIL;
4347 break;
4348
4349 /*
4350 * Constant Vim variable.
4351 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004352 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004353 ret = NOTDONE;
4354 break;
4355
4356 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004357 * "true" constant
4358 */
4359 case 't': if (STRNCMP(*arg, "true", 4) == 0
4360 && !eval_isnamec((*arg)[4]))
4361 {
4362 *arg += 4;
4363 rettv->v_type = VAR_BOOL;
4364 rettv->vval.v_number = VVAL_TRUE;
4365 }
4366 else
4367 ret = NOTDONE;
4368 break;
4369
4370 /*
4371 * "false" constant
4372 */
4373 case 'f': if (STRNCMP(*arg, "false", 5) == 0
4374 && !eval_isnamec((*arg)[5]))
4375 {
4376 *arg += 5;
4377 rettv->v_type = VAR_BOOL;
4378 rettv->vval.v_number = VVAL_FALSE;
4379 }
4380 else
4381 ret = NOTDONE;
4382 break;
4383
4384 /*
Bram Moolenaar67977822021-01-03 21:53:53 +01004385 * "null" constant
4386 */
4387 case 'n': if (STRNCMP(*arg, "null", 4) == 0
Bram Moolenaarc23555d2021-03-10 19:04:07 +01004388 && !eval_isnamec((*arg)[4]))
Bram Moolenaar67977822021-01-03 21:53:53 +01004389 {
4390 *arg += 4;
4391 rettv->v_type = VAR_SPECIAL;
4392 rettv->vval.v_number = VVAL_NULL;
4393 }
4394 else
4395 ret = NOTDONE;
4396 break;
4397
4398 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004399 * List: [expr, expr]
4400 */
Bram Moolenaare507ff12021-01-31 21:47:42 +01004401 case '[': if (generate_ppconst(cctx, ppconst) == FAIL)
4402 return FAIL;
4403 ret = compile_list(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004404 break;
4405
4406 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004407 * Dictionary: {'key': val, 'key': val}
4408 */
Bram Moolenaare507ff12021-01-31 21:47:42 +01004409 case '{': if (generate_ppconst(cctx, ppconst) == FAIL)
4410 return FAIL;
4411 ret = compile_dict(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004412 break;
4413
4414 /*
4415 * Option value: &name
4416 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004417 case '&': if (generate_ppconst(cctx, ppconst) == FAIL)
4418 return FAIL;
4419 ret = compile_get_option(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004420 break;
4421
4422 /*
4423 * Environment variable: $VAR.
4424 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004425 case '$': if (generate_ppconst(cctx, ppconst) == FAIL)
4426 return FAIL;
4427 ret = compile_get_env(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004428 break;
4429
4430 /*
4431 * Register contents: @r.
4432 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004433 case '@': if (generate_ppconst(cctx, ppconst) == FAIL)
4434 return FAIL;
4435 ret = compile_get_register(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004436 break;
4437 /*
4438 * nested expression: (expression).
Bram Moolenaar65c44152020-12-24 15:14:01 +01004439 * lambda: (arg, arg) => expr
4440 * funcref: (arg, arg) => { statement }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004441 */
Bram Moolenaare462f522020-12-27 14:43:30 +01004442 case '(': // if compile_lambda returns NOTDONE then it must be (expr)
4443 ret = compile_lambda(arg, cctx);
4444 if (ret == NOTDONE)
Bram Moolenaar7e368202020-12-25 21:56:57 +01004445 ret = compile_parenthesis(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004446 break;
4447
4448 default: ret = NOTDONE;
4449 break;
4450 }
4451 if (ret == FAIL)
4452 return FAIL;
4453
Bram Moolenaar1c747212020-05-09 18:28:34 +02004454 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004455 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004456 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004457 clear_tv(rettv);
4458 else
4459 // A constant expression can possibly be handled compile time,
4460 // return the value instead of generating code.
4461 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004462 }
4463 else if (ret == NOTDONE)
4464 {
4465 char_u *p;
4466 int r;
4467
4468 if (!eval_isnamec1(**arg))
4469 {
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01004470 if (!vim9_bad_comment(*arg))
4471 {
4472 if (ends_excmd(*skipwhite(*arg)))
4473 semsg(_(e_empty_expression_str), *arg);
4474 else
4475 semsg(_(e_name_expected_str), *arg);
4476 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004477 return FAIL;
4478 }
4479
4480 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01004481 p = to_name_end(*arg, TRUE);
Bram Moolenaar962c43b2021-04-10 17:18:09 +02004482 if (p - *arg == (size_t)1 && **arg == '_')
4483 {
4484 emsg(_(e_cannot_use_underscore_here));
4485 return FAIL;
4486 }
4487
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004488 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02004489 {
4490 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
4491 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004492 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02004493 {
4494 if (generate_ppconst(cctx, ppconst) == FAIL)
4495 return FAIL;
Bram Moolenaar0f769812020-09-12 18:32:34 +02004496 r = compile_load(arg, p, cctx, TRUE, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004497 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004498 if (r == FAIL)
4499 return FAIL;
4500 }
4501
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004502 // Handle following "[]", ".member", etc.
4503 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004504 if (compile_subscript(arg, cctx, start_leader, &end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02004505 ppconst) == FAIL)
4506 return FAIL;
4507 if (ppconst->pp_used > 0)
4508 {
4509 // apply the '!', '-' and '+' before the constant
4510 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004511 if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004512 return FAIL;
4513 return OK;
4514 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004515 if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004516 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004517 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004518}
4519
4520/*
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004521 * Give the "white on both sides" error, taking the operator from "p[len]".
4522 */
4523 void
4524error_white_both(char_u *op, int len)
4525{
4526 char_u buf[10];
4527
4528 vim_strncpy(buf, op, len);
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004529 semsg(_(e_white_space_required_before_and_after_str_at_str), buf, op);
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004530}
4531
4532/*
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004533 * <type>expr7: runtime type check / conversion
4534 */
4535 static int
4536compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
4537{
4538 type_T *want_type = NULL;
4539
4540 // Recognize <type>
4541 if (**arg == '<' && eval_isnamec1((*arg)[1]))
4542 {
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004543 ++*arg;
Bram Moolenaar9e68c322020-12-25 12:38:04 +01004544 want_type = parse_type(arg, cctx->ctx_type_list, TRUE);
4545 if (want_type == NULL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004546 return FAIL;
4547
4548 if (**arg != '>')
4549 {
4550 if (*skipwhite(*arg) == '>')
Bram Moolenaarba98fb52021-02-07 18:06:29 +01004551 semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg);
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004552 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004553 emsg(_(e_missing_gt));
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004554 return FAIL;
4555 }
4556 ++*arg;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004557 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004558 return FAIL;
4559 }
4560
4561 if (compile_expr7(arg, cctx, ppconst) == FAIL)
4562 return FAIL;
4563
4564 if (want_type != NULL)
4565 {
4566 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaard1103582020-08-14 22:44:25 +02004567 type_T *actual;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01004568 where_T where;
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004569
Bram Moolenaard1103582020-08-14 22:44:25 +02004570 generate_ppconst(cctx, ppconst);
4571 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarf785aa12021-02-11 21:19:34 +01004572 where.wt_index = 0;
4573 where.wt_variable = FALSE;
4574 if (check_type(want_type, actual, FALSE, where) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004575 {
Bram Moolenaar351ead02021-01-16 16:07:01 +01004576 if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004577 return FAIL;
4578 }
4579 }
4580
4581 return OK;
4582}
4583
4584/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004585 * * number multiplication
4586 * / number division
4587 * % number modulo
4588 */
4589 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004590compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004591{
4592 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004593 char_u *next;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004594 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004595
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004596 // get the first expression
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004597 if (compile_expr7t(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004598 return FAIL;
4599
4600 /*
4601 * Repeat computing, until no "*", "/" or "%" is following.
4602 */
4603 for (;;)
4604 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004605 op = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004606 if (*op != '*' && *op != '/' && *op != '%')
4607 break;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004608 if (next != NULL)
4609 {
4610 *arg = next_line_from_context(cctx, TRUE);
4611 op = skipwhite(*arg);
4612 }
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004613
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004614 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004615 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004616 error_white_both(op, 1);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004617 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004618 }
Bram Moolenaar918a4242020-12-06 14:37:08 +01004619 if (may_get_next_line_error(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004620 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004621
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004622 // get the second expression
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004623 if (compile_expr7t(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004624 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004625
4626 if (ppconst->pp_used == ppconst_used + 2
4627 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4628 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004629 {
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004630 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4631 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
4632 varnumber_T res = 0;
4633 int failed = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004634
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004635 // both are numbers: compute the result
4636 switch (*op)
4637 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004638 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004639 break;
Bram Moolenaare64f83c2021-01-19 22:16:41 +01004640 case '/': res = num_divide(tv1->vval.v_number,
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004641 tv2->vval.v_number, &failed);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004642 break;
Bram Moolenaare64f83c2021-01-19 22:16:41 +01004643 case '%': res = num_modulus(tv1->vval.v_number,
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004644 tv2->vval.v_number, &failed);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004645 break;
4646 }
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004647 if (failed)
4648 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004649 tv1->vval.v_number = res;
4650 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004651 }
4652 else
4653 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004654 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004655 generate_two_op(cctx, op);
4656 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004657 }
4658
4659 return OK;
4660}
4661
4662/*
Bram Moolenaard345fb92021-03-10 18:43:09 +01004663 * + number addition or list/blobl concatenation
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004664 * - number subtraction
4665 * .. string concatenation
4666 */
4667 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004668compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004669{
4670 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004671 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004672 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004673 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004674
4675 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004676 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004677 return FAIL;
4678
4679 /*
4680 * Repeat computing, until no "+", "-" or ".." is following.
4681 */
4682 for (;;)
4683 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004684 op = may_peek_next_line(cctx, *arg, &next);
4685 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004686 break;
4687 oplen = (*op == '.' ? 2 : 1);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004688 if (next != NULL)
4689 {
4690 *arg = next_line_from_context(cctx, TRUE);
4691 op = skipwhite(*arg);
4692 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004693
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004694 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004695 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004696 error_white_both(op, oplen);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004697 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004698 }
4699
Bram Moolenaare0de1712020-12-02 17:36:54 +01004700 if (may_get_next_line_error(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004701 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004702
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004703 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004704 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004705 return FAIL;
4706
Bram Moolenaara5565e42020-05-09 15:44:01 +02004707 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004708 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02004709 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
4710 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
4711 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4712 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004713 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004714 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4715 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004716
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004717 // concat/subtract/add constant numbers
4718 if (*op == '+')
4719 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
4720 else if (*op == '-')
4721 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
4722 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004723 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004724 // concatenate constant strings
4725 char_u *s1 = tv1->vval.v_string;
4726 char_u *s2 = tv2->vval.v_string;
4727 size_t len1 = STRLEN(s1);
4728
4729 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
4730 if (tv1->vval.v_string == NULL)
4731 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004732 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004733 return FAIL;
4734 }
4735 mch_memmove(tv1->vval.v_string, s1, len1);
4736 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004737 vim_free(s1);
4738 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004739 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004740 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004741 }
4742 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004743 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004744 generate_ppconst(cctx, ppconst);
Bram Moolenaard345fb92021-03-10 18:43:09 +01004745 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004746 if (*op == '.')
4747 {
4748 if (may_generate_2STRING(-2, cctx) == FAIL
4749 || may_generate_2STRING(-1, cctx) == FAIL)
4750 return FAIL;
4751 generate_instr_drop(cctx, ISN_CONCAT, 1);
4752 }
4753 else
4754 generate_two_op(cctx, op);
4755 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004756 }
4757
4758 return OK;
4759}
4760
4761/*
4762 * expr5a == expr5b
4763 * expr5a =~ expr5b
4764 * expr5a != expr5b
4765 * expr5a !~ expr5b
4766 * expr5a > expr5b
4767 * expr5a >= expr5b
4768 * expr5a < expr5b
4769 * expr5a <= expr5b
4770 * expr5a is expr5b
4771 * expr5a isnot expr5b
4772 *
4773 * Produces instructions:
4774 * EVAL expr5a Push result of "expr5a"
4775 * EVAL expr5b Push result of "expr5b"
4776 * COMPARE one of the compare instructions
4777 */
4778 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004779compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004780{
Bram Moolenaar657137c2021-01-09 15:45:23 +01004781 exprtype_T type = EXPR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004782 char_u *p;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004783 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004784 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004785 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004786 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004787
4788 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004789 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004790 return FAIL;
4791
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004792 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004793 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004794
4795 /*
4796 * If there is a comparative operator, use it.
4797 */
4798 if (type != EXPR_UNKNOWN)
4799 {
4800 int ic = FALSE; // Default: do not ignore case
4801
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004802 if (next != NULL)
4803 {
4804 *arg = next_line_from_context(cctx, TRUE);
4805 p = skipwhite(*arg);
4806 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004807 if (type_is && (p[len] == '?' || p[len] == '#'))
4808 {
4809 semsg(_(e_invexpr2), *arg);
4810 return FAIL;
4811 }
4812 // extra question mark appended: ignore case
4813 if (p[len] == '?')
4814 {
4815 ic = TRUE;
4816 ++len;
4817 }
4818 // extra '#' appended: match case (ignored)
4819 else if (p[len] == '#')
4820 ++len;
4821 // nothing appended: match case
4822
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004823 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004824 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004825 error_white_both(p, len);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004826 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004827 }
4828
4829 // get the second variable
Bram Moolenaar918a4242020-12-06 14:37:08 +01004830 if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004831 return FAIL;
4832
Bram Moolenaara5565e42020-05-09 15:44:01 +02004833 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004834 return FAIL;
4835
Bram Moolenaara5565e42020-05-09 15:44:01 +02004836 if (ppconst->pp_used == ppconst_used + 2)
4837 {
4838 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
4839 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
4840 int ret;
4841
4842 // Both sides are a constant, compute the result now.
4843 // First check for a valid combination of types, this is more
4844 // strict than typval_compare().
Bram Moolenaar543e6f32020-07-10 22:45:38 +02004845 if (check_compare_types(type, tv1, tv2) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004846 ret = FAIL;
4847 else
4848 {
4849 ret = typval_compare(tv1, tv2, type, ic);
4850 tv1->v_type = VAR_BOOL;
4851 tv1->vval.v_number = tv1->vval.v_number
4852 ? VVAL_TRUE : VVAL_FALSE;
4853 clear_tv(tv2);
4854 --ppconst->pp_used;
4855 }
4856 return ret;
4857 }
4858
4859 generate_ppconst(cctx, ppconst);
4860 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004861 }
4862
4863 return OK;
4864}
4865
Bram Moolenaar7f141552020-05-09 17:35:53 +02004866static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
4867
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004868/*
4869 * Compile || or &&.
4870 */
4871 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004872compile_and_or(
4873 char_u **arg,
4874 cctx_T *cctx,
4875 char *op,
4876 ppconst_T *ppconst,
4877 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004878{
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004879 char_u *next;
4880 char_u *p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004881 int opchar = *op;
4882
4883 if (p[0] == opchar && p[1] == opchar)
4884 {
4885 garray_T *instr = &cctx->ctx_instr;
4886 garray_T end_ga;
4887
4888 /*
4889 * Repeat until there is no following "||" or "&&"
4890 */
4891 ga_init2(&end_ga, sizeof(int), 10);
4892 while (p[0] == opchar && p[1] == opchar)
4893 {
Bram Moolenaara7511c02021-04-03 21:47:07 +02004894 long start_lnum = SOURCING_LNUM;
4895 int start_ctx_lnum = cctx->ctx_lnum;
4896 int save_lnum;
4897
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004898 if (next != NULL)
4899 {
4900 *arg = next_line_from_context(cctx, TRUE);
4901 p = skipwhite(*arg);
4902 }
4903
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004904 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
4905 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004906 semsg(_(e_white_space_required_before_and_after_str_at_str),
Bram Moolenaar90193e62021-04-04 20:49:50 +02004907 op, p);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004908 return FAIL;
4909 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004910
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004911 // TODO: use ppconst if the value is a constant and check
4912 // evaluating to bool
Bram Moolenaara5565e42020-05-09 15:44:01 +02004913 generate_ppconst(cctx, ppconst);
4914
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004915 // Every part must evaluate to a bool.
Bram Moolenaara7511c02021-04-03 21:47:07 +02004916 SOURCING_LNUM = start_lnum;
4917 save_lnum = cctx->ctx_lnum;
4918 cctx->ctx_lnum = start_ctx_lnum;
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004919 if (bool_on_stack(cctx) == FAIL)
4920 {
Bram Moolenaara7511c02021-04-03 21:47:07 +02004921 cctx->ctx_lnum = save_lnum;
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004922 ga_clear(&end_ga);
4923 return FAIL;
4924 }
Bram Moolenaara7511c02021-04-03 21:47:07 +02004925 cctx->ctx_lnum = save_lnum;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004926
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004927 if (ga_grow(&end_ga, 1) == FAIL)
4928 {
4929 ga_clear(&end_ga);
4930 return FAIL;
4931 }
4932 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
4933 ++end_ga.ga_len;
4934 generate_JUMP(cctx, opchar == '|'
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004935 ? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE, 0);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004936
4937 // eval the next expression
Bram Moolenaar918a4242020-12-06 14:37:08 +01004938 if (may_get_next_line_error(p + 2, arg, cctx) == FAIL)
Bram Moolenaar8bb0f542020-12-06 16:03:55 +01004939 {
4940 ga_clear(&end_ga);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004941 return FAIL;
Bram Moolenaar8bb0f542020-12-06 16:03:55 +01004942 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004943
Bram Moolenaara5565e42020-05-09 15:44:01 +02004944 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
4945 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004946 {
4947 ga_clear(&end_ga);
4948 return FAIL;
4949 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004950
4951 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004952 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004953 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004954
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004955 // Every part must evaluate to a bool.
4956 if (bool_on_stack(cctx) == FAIL)
4957 {
4958 ga_clear(&end_ga);
4959 return FAIL;
4960 }
4961
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004962 // Fill in the end label in all jumps.
4963 while (end_ga.ga_len > 0)
4964 {
4965 isn_T *isn;
4966
4967 --end_ga.ga_len;
4968 isn = ((isn_T *)instr->ga_data)
4969 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
4970 isn->isn_arg.jump.jump_where = instr->ga_len;
4971 }
4972 ga_clear(&end_ga);
4973 }
4974
4975 return OK;
4976}
4977
4978/*
4979 * expr4a && expr4a && expr4a logical AND
4980 *
4981 * Produces instructions:
4982 * EVAL expr4a Push result of "expr4a"
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004983 * COND2BOOL convert to bool if needed
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004984 * JUMP_IF_COND_FALSE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004985 * EVAL expr4b Push result of "expr4b"
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004986 * JUMP_IF_COND_FALSE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004987 * EVAL expr4c Push result of "expr4c"
4988 * end:
4989 */
4990 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004991compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004992{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004993 int ppconst_used = ppconst->pp_used;
4994
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004995 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004996 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004997 return FAIL;
4998
4999 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02005000 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005001}
5002
5003/*
5004 * expr3a || expr3b || expr3c logical OR
5005 *
5006 * Produces instructions:
5007 * EVAL expr3a Push result of "expr3a"
Bram Moolenaarea2d4072020-11-12 12:08:51 +01005008 * COND2BOOL convert to bool if needed
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005009 * JUMP_IF_COND_TRUE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005010 * EVAL expr3b Push result of "expr3b"
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005011 * JUMP_IF_COND_TRUE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005012 * EVAL expr3c Push result of "expr3c"
5013 * end:
5014 */
5015 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02005016compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005017{
Bram Moolenaara5565e42020-05-09 15:44:01 +02005018 int ppconst_used = ppconst->pp_used;
5019
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005020 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02005021 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005022 return FAIL;
5023
5024 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02005025 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005026}
5027
5028/*
5029 * Toplevel expression: expr2 ? expr1a : expr1b
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005030 * Produces instructions:
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005031 * EVAL expr2 Push result of "expr2"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005032 * JUMP_IF_FALSE alt jump if false
5033 * EVAL expr1a
5034 * JUMP_ALWAYS end
5035 * alt: EVAL expr1b
5036 * end:
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005037 *
5038 * Toplevel expression: expr2 ?? expr1
5039 * Produces instructions:
5040 * EVAL expr2 Push result of "expr2"
5041 * JUMP_AND_KEEP_IF_TRUE end jump if true
5042 * EVAL expr1
5043 * end:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005044 */
5045 static int
Bram Moolenaar7e368202020-12-25 21:56:57 +01005046compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005047{
5048 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005049 int ppconst_used = ppconst->pp_used;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02005050 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005051
Bram Moolenaar3988f642020-08-27 22:43:03 +02005052 // Ignore all kinds of errors when not producing code.
5053 if (cctx->ctx_skip == SKIP_YES)
5054 {
Bram Moolenaar7e368202020-12-25 21:56:57 +01005055 skip_expr_cctx(arg, cctx);
Bram Moolenaar3988f642020-08-27 22:43:03 +02005056 return OK;
5057 }
5058
Bram Moolenaar61a89812020-05-07 16:58:17 +02005059 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02005060 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005061 return FAIL;
5062
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02005063 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005064 if (*p == '?')
5065 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005066 int op_falsy = p[1] == '?';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005067 garray_T *instr = &cctx->ctx_instr;
5068 garray_T *stack = &cctx->ctx_type_stack;
5069 int alt_idx = instr->ga_len;
Bram Moolenaar38041da2020-06-21 22:17:18 +02005070 int end_idx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005071 isn_T *isn;
Bram Moolenaar38041da2020-06-21 22:17:18 +02005072 type_T *type1 = NULL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005073 int has_const_expr = FALSE;
5074 int const_value = FALSE;
5075 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005076
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02005077 if (next != NULL)
5078 {
5079 *arg = next_line_from_context(cctx, TRUE);
5080 p = skipwhite(*arg);
5081 }
5082
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005083 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1 + op_falsy]))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02005084 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01005085 semsg(_(e_white_space_required_before_and_after_str_at_str),
5086 op_falsy ? "??" : "?", *arg);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02005087 return FAIL;
5088 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005089
Bram Moolenaara5565e42020-05-09 15:44:01 +02005090 if (ppconst->pp_used == ppconst_used + 1)
5091 {
5092 // the condition is a constant, we know whether the ? or the :
5093 // expression is to be evaluated.
5094 has_const_expr = TRUE;
Bram Moolenaar13106602020-10-04 16:06:05 +02005095 if (op_falsy)
5096 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
5097 else
5098 {
5099 int error = FALSE;
5100
5101 const_value = tv_get_bool_chk(&ppconst->pp_tv[ppconst_used],
5102 &error);
5103 if (error)
5104 return FAIL;
5105 }
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005106 cctx->ctx_skip = save_skip == SKIP_YES ||
5107 (op_falsy ? const_value : !const_value) ? SKIP_YES : SKIP_NOT;
5108
5109 if (op_falsy && cctx->ctx_skip == SKIP_YES)
5110 // "left ?? right" and "left" is truthy: produce "left"
5111 generate_ppconst(cctx, ppconst);
5112 else
5113 {
5114 clear_tv(&ppconst->pp_tv[ppconst_used]);
5115 --ppconst->pp_used;
5116 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02005117 }
5118 else
5119 {
5120 generate_ppconst(cctx, ppconst);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005121 if (op_falsy)
5122 end_idx = instr->ga_len;
5123 generate_JUMP(cctx, op_falsy
5124 ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
5125 if (op_falsy)
5126 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaara5565e42020-05-09 15:44:01 +02005127 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005128
5129 // evaluate the second expression; any type is accepted
Bram Moolenaar918a4242020-12-06 14:37:08 +01005130 if (may_get_next_line_error(p + 1 + op_falsy, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02005131 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005132 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01005133 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005134
Bram Moolenaara5565e42020-05-09 15:44:01 +02005135 if (!has_const_expr)
5136 {
5137 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005138
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005139 if (!op_falsy)
5140 {
5141 // remember the type and drop it
5142 --stack->ga_len;
5143 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005144
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005145 end_idx = instr->ga_len;
5146 generate_JUMP(cctx, JUMP_ALWAYS, 0);
Bram Moolenaara5565e42020-05-09 15:44:01 +02005147
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005148 // jump here from JUMP_IF_FALSE
5149 isn = ((isn_T *)instr->ga_data) + alt_idx;
5150 isn->isn_arg.jump.jump_where = instr->ga_len;
5151 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02005152 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005153
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005154 if (!op_falsy)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005155 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005156 // Check for the ":".
5157 p = may_peek_next_line(cctx, *arg, &next);
5158 if (*p != ':')
5159 {
5160 emsg(_(e_missing_colon));
5161 return FAIL;
5162 }
5163 if (next != NULL)
5164 {
5165 *arg = next_line_from_context(cctx, TRUE);
5166 p = skipwhite(*arg);
5167 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02005168
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005169 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
5170 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01005171 semsg(_(e_white_space_required_before_and_after_str_at_str),
5172 ":", p);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005173 return FAIL;
5174 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005175
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005176 // evaluate the third expression
5177 if (has_const_expr)
5178 cctx->ctx_skip = save_skip == SKIP_YES || const_value
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005179 ? SKIP_YES : SKIP_NOT;
Bram Moolenaar918a4242020-12-06 14:37:08 +01005180 if (may_get_next_line_error(p + 1, arg, cctx) == FAIL)
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005181 return FAIL;
5182 if (compile_expr1(arg, cctx, ppconst) == FAIL)
5183 return FAIL;
5184 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005185
Bram Moolenaara5565e42020-05-09 15:44:01 +02005186 if (!has_const_expr)
5187 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005188 type_T **typep;
5189
Bram Moolenaara5565e42020-05-09 15:44:01 +02005190 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005191
Bram Moolenaara5565e42020-05-09 15:44:01 +02005192 // If the types differ, the result has a more generic type.
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005193 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
5194 common_type(type1, *typep, typep, cctx->ctx_type_list);
Bram Moolenaara5565e42020-05-09 15:44:01 +02005195
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005196 // jump here from JUMP_ALWAYS or JUMP_AND_KEEP_IF_TRUE
Bram Moolenaara5565e42020-05-09 15:44:01 +02005197 isn = ((isn_T *)instr->ga_data) + end_idx;
5198 isn->isn_arg.jump.jump_where = instr->ga_len;
5199 }
5200
5201 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005202 }
5203 return OK;
5204}
5205
5206/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02005207 * Toplevel expression.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02005208 * Sets "is_const" (if not NULL) to indicate the value is a constant.
5209 * Returns OK or FAIL.
Bram Moolenaara5565e42020-05-09 15:44:01 +02005210 */
5211 static int
Bram Moolenaar334a8b42020-10-19 16:07:42 +02005212compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const)
Bram Moolenaara5565e42020-05-09 15:44:01 +02005213{
5214 ppconst_T ppconst;
5215
5216 CLEAR_FIELD(ppconst);
5217 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
5218 {
5219 clear_ppconst(&ppconst);
5220 return FAIL;
5221 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02005222 if (is_const != NULL)
5223 *is_const = ppconst.pp_used > 0 || ppconst.pp_is_const;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005224 if (generate_ppconst(cctx, &ppconst) == FAIL)
5225 return FAIL;
5226 return OK;
5227}
5228
5229/*
Bram Moolenaar334a8b42020-10-19 16:07:42 +02005230 * Toplevel expression.
5231 */
5232 static int
5233compile_expr0(char_u **arg, cctx_T *cctx)
5234{
5235 return compile_expr0_ext(arg, cctx, NULL);
5236}
5237
5238/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005239 * compile "return [expr]"
5240 */
5241 static char_u *
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005242compile_return(char_u *arg, int check_return_type, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005243{
5244 char_u *p = arg;
5245 garray_T *stack = &cctx->ctx_type_stack;
5246 type_T *stack_type;
5247
5248 if (*p != NUL && *p != '|' && *p != '\n')
5249 {
5250 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02005251 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005252 return NULL;
5253
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005254 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar05a55512020-07-05 15:52:19 +02005255 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005256 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar6b553772020-12-31 13:31:23 +01005257 if (check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar328eac22021-01-07 19:23:08 +01005258 || cctx->ctx_ufunc->uf_ret_type == &t_unknown
5259 || cctx->ctx_ufunc->uf_ret_type == &t_any))
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005260 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005261 cctx->ctx_ufunc->uf_ret_type = stack_type;
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005262 }
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005263 else
Bram Moolenaar05a55512020-07-05 15:52:19 +02005264 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005265 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
5266 && stack_type->tt_type != VAR_VOID
5267 && stack_type->tt_type != VAR_UNKNOWN)
5268 {
5269 emsg(_(e_returning_value_in_function_without_return_type));
5270 return NULL;
5271 }
5272 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
Bram Moolenaar351ead02021-01-16 16:07:01 +01005273 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005274 return NULL;
5275 }
Bram Moolenaar05a55512020-07-05 15:52:19 +02005276 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005277 }
5278 else
5279 {
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005280 // "check_return_type" cannot be TRUE, only used for a lambda which
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02005281 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02005282 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
5283 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005284 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005285 emsg(_(e_missing_return_value));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005286 return NULL;
5287 }
5288
5289 // No argument, return zero.
5290 generate_PUSHNR(cctx, 0);
5291 }
Bram Moolenaar7cd24222021-01-12 18:58:39 +01005292
5293 // Undo any command modifiers.
5294 generate_undo_cmdmods(cctx);
5295
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005296 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005297 return NULL;
5298
5299 // "return val | endif" is possible
5300 return skipwhite(p);
5301}
5302
5303/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02005304 * Get a line from the compilation context, compatible with exarg_T getline().
5305 * Return a pointer to the line in allocated memory.
5306 * Return NULL for end-of-file or some error.
5307 */
5308 static char_u *
5309exarg_getline(
5310 int c UNUSED,
5311 void *cookie,
5312 int indent UNUSED,
Bram Moolenaar66250c92020-08-20 15:02:42 +02005313 getline_opt_T options UNUSED)
Bram Moolenaar04b12692020-05-04 23:24:44 +02005314{
5315 cctx_T *cctx = (cctx_T *)cookie;
Bram Moolenaar66250c92020-08-20 15:02:42 +02005316 char_u *p;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005317
Bram Moolenaar66250c92020-08-20 15:02:42 +02005318 for (;;)
Bram Moolenaar04b12692020-05-04 23:24:44 +02005319 {
Bram Moolenaar2914a202020-09-27 18:24:03 +02005320 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len - 1)
Bram Moolenaar66250c92020-08-20 15:02:42 +02005321 return NULL;
5322 ++cctx->ctx_lnum;
5323 p = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
5324 // Comment lines result in NULL pointers, skip them.
5325 if (p != NULL)
5326 return vim_strsave(p);
Bram Moolenaar04b12692020-05-04 23:24:44 +02005327 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02005328}
5329
Bram Moolenaar7a6eaa02021-03-21 20:53:29 +01005330 void
5331fill_exarg_from_cctx(exarg_T *eap, cctx_T *cctx)
5332{
5333 eap->getline = exarg_getline;
5334 eap->cookie = cctx;
5335}
5336
Bram Moolenaar04b12692020-05-04 23:24:44 +02005337/*
5338 * Compile a nested :def command.
5339 */
5340 static char_u *
5341compile_nested_function(exarg_T *eap, cctx_T *cctx)
5342{
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005343 int is_global = *eap->arg == 'g' && eap->arg[1] == ':';
Bram Moolenaar04b12692020-05-04 23:24:44 +02005344 char_u *name_start = eap->arg;
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005345 char_u *name_end = to_name_end(eap->arg, TRUE);
Bram Moolenaareef21022020-08-01 22:16:43 +02005346 char_u *lambda_name;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005347 ufunc_T *ufunc;
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005348 int r = FAIL;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005349
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02005350 if (eap->forceit)
Bram Moolenaar8b848ca2020-09-10 22:28:01 +02005351 {
5352 emsg(_(e_cannot_use_bang_with_nested_def));
5353 return NULL;
5354 }
5355
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01005356 if (*name_start == '/')
5357 {
5358 name_end = skip_regexp(name_start + 1, '/', TRUE);
5359 if (*name_end == '/')
5360 ++name_end;
5361 eap->nextcmd = check_nextcmd(name_end);
5362 }
5363 if (name_end == name_start || *skipwhite(name_end) != '(')
5364 {
5365 if (!ends_excmd2(name_start, name_end))
5366 {
5367 semsg(_(e_invalid_command_str), eap->cmd);
5368 return NULL;
5369 }
5370
5371 // "def" or "def Name": list functions
5372 if (generate_DEF(cctx, name_start, name_end - name_start) == FAIL)
5373 return NULL;
5374 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5375 }
5376
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005377 // Only g:Func() can use a namespace.
5378 if (name_start[1] == ':' && !is_global)
5379 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005380 semsg(_(e_namespace_not_supported_str), name_start);
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005381 return NULL;
5382 }
Bram Moolenaar057e84a2021-02-28 16:55:11 +01005383 if (check_defined(name_start, name_end - name_start, cctx, FALSE) == FAIL)
Bram Moolenaareef21022020-08-01 22:16:43 +02005384 return NULL;
5385
Bram Moolenaar04b12692020-05-04 23:24:44 +02005386 eap->arg = name_end;
Bram Moolenaar7a6eaa02021-03-21 20:53:29 +01005387 fill_exarg_from_cctx(eap, cctx);
5388
Bram Moolenaar04b12692020-05-04 23:24:44 +02005389 eap->forceit = FALSE;
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005390 lambda_name = vim_strsave(get_lambda_name());
5391 if (lambda_name == NULL)
5392 return NULL;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02005393 ufunc = define_function(eap, lambda_name);
Bram Moolenaar04b12692020-05-04 23:24:44 +02005394
Bram Moolenaar822ba242020-05-24 23:00:18 +02005395 if (ufunc == NULL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005396 {
5397 r = eap->skip ? OK : FAIL;
5398 goto theend;
5399 }
Bram Moolenaar8863bda2021-03-17 18:42:08 +01005400
5401 // copy over the block scope IDs before compiling
5402 if (!is_global && cctx->ctx_ufunc->uf_block_depth > 0)
5403 {
5404 int block_depth = cctx->ctx_ufunc->uf_block_depth;
5405
5406 ufunc->uf_block_ids = ALLOC_MULT(int, block_depth);
5407 if (ufunc->uf_block_ids != NULL)
5408 {
5409 mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids,
5410 sizeof(int) * block_depth);
5411 ufunc->uf_block_depth = block_depth;
5412 }
5413 }
5414
Bram Moolenaare5ea3462021-01-25 21:01:48 +01005415 if (func_needs_compiling(ufunc, PROFILING(ufunc))
5416 && compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx)
Bram Moolenaarb2049902021-01-24 12:53:53 +01005417 == FAIL)
Bram Moolenaar4ee711f2020-09-23 18:51:11 +02005418 {
5419 func_ptr_unref(ufunc);
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005420 goto theend;
Bram Moolenaar4ee711f2020-09-23 18:51:11 +02005421 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02005422
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005423 if (is_global)
5424 {
5425 char_u *func_name = vim_strnsave(name_start + 2,
5426 name_end - name_start - 2);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02005427
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005428 if (func_name == NULL)
5429 r = FAIL;
5430 else
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005431 {
Bram Moolenaareef21022020-08-01 22:16:43 +02005432 r = generate_NEWFUNC(cctx, lambda_name, func_name);
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005433 lambda_name = NULL;
5434 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005435 }
5436 else
5437 {
5438 // Define a local variable for the function reference.
Bram Moolenaare8211a32020-10-09 22:04:29 +02005439 lvar_T *lvar = reserve_local(cctx, name_start, name_end - name_start,
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005440 TRUE, ufunc->uf_func_type);
Bram Moolenaare8211a32020-10-09 22:04:29 +02005441
Bram Moolenaareef21022020-08-01 22:16:43 +02005442 if (lvar == NULL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005443 goto theend;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02005444 if (generate_FUNCREF(cctx, ufunc) == FAIL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005445 goto theend;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005446 r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
5447 }
Bram Moolenaar61a89812020-05-07 16:58:17 +02005448 // TODO: warning for trailing text?
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005449
5450theend:
5451 vim_free(lambda_name);
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005452 return r == FAIL ? NULL : (char_u *)"";
Bram Moolenaar04b12692020-05-04 23:24:44 +02005453}
5454
5455/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005456 * Return the length of an assignment operator, or zero if there isn't one.
5457 */
5458 int
5459assignment_len(char_u *p, int *heredoc)
5460{
5461 if (*p == '=')
5462 {
5463 if (p[1] == '<' && p[2] == '<')
5464 {
5465 *heredoc = TRUE;
5466 return 3;
5467 }
5468 return 1;
5469 }
5470 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
5471 return 2;
5472 if (STRNCMP(p, "..=", 3) == 0)
5473 return 3;
5474 return 0;
5475}
5476
5477// words that cannot be used as a variable
5478static char *reserved[] = {
5479 "true",
5480 "false",
Bram Moolenaar67977822021-01-03 21:53:53 +01005481 "null",
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005482 NULL
5483};
5484
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005485/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005486 * Generate the load instruction for "name".
5487 */
5488 static void
5489generate_loadvar(
5490 cctx_T *cctx,
5491 assign_dest_T dest,
5492 char_u *name,
5493 lvar_T *lvar,
5494 type_T *type)
5495{
5496 switch (dest)
5497 {
5498 case dest_option:
5499 // TODO: check the option exists
5500 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
5501 break;
5502 case dest_global:
Bram Moolenaar03290b82020-12-19 16:30:44 +01005503 if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
5504 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
5505 else
5506 generate_LOAD(cctx, ISN_LOADAUTO, 0, name, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005507 break;
5508 case dest_buffer:
5509 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
5510 break;
5511 case dest_window:
5512 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
5513 break;
5514 case dest_tab:
5515 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
5516 break;
5517 case dest_script:
5518 compile_load_scriptvar(cctx,
5519 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
5520 break;
5521 case dest_env:
5522 // Include $ in the name here
5523 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
5524 break;
5525 case dest_reg:
5526 generate_LOAD(cctx, ISN_LOADREG, name[1], NULL, &t_string);
5527 break;
5528 case dest_vimvar:
5529 generate_LOADV(cctx, name + 2, TRUE);
5530 break;
5531 case dest_local:
Bram Moolenaarab360522021-01-10 14:02:28 +01005532 if (lvar->lv_from_outer > 0)
5533 generate_LOADOUTER(cctx, lvar->lv_idx, lvar->lv_from_outer,
5534 type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005535 else
5536 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
5537 break;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01005538 case dest_expr:
5539 // list or dict value should already be on the stack.
5540 break;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005541 }
5542}
5543
Bram Moolenaardc234ca2020-11-28 18:52:33 +01005544/*
5545 * Skip over "[expr]" or ".member".
5546 * Does not check for any errors.
5547 */
5548 static char_u *
5549skip_index(char_u *start)
5550{
5551 char_u *p = start;
5552
5553 if (*p == '[')
5554 {
5555 p = skipwhite(p + 1);
5556 (void)skip_expr(&p, NULL);
5557 p = skipwhite(p);
5558 if (*p == ']')
5559 return p + 1;
5560 return p;
5561 }
5562 // if (*p == '.')
5563 return to_name_end(p + 1, TRUE);
5564}
5565
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005566 void
5567vim9_declare_error(char_u *name)
5568{
5569 char *scope = "";
5570
5571 switch (*name)
5572 {
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005573 case 'g': scope = _("global"); break;
5574 case 'b': scope = _("buffer"); break;
5575 case 'w': scope = _("window"); break;
5576 case 't': scope = _("tab"); break;
5577 case 'v': scope = "v:"; break;
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02005578 case '$': semsg(_(e_cannot_declare_an_environment_variable), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005579 return;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005580 case '&': semsg(_(e_cannot_declare_an_option), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005581 return;
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02005582 case '@': semsg(_(e_cannot_declare_a_register_str), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005583 return;
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005584 default: return;
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005585 }
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02005586 semsg(_(e_cannot_declare_a_scope_variable), scope, name);
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005587}
5588
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005589/*
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005590 * For one assignment figure out the type of destination. Return it in "dest".
5591 * When not recognized "dest" is not set.
5592 * For an option "opt_flags" is set.
5593 * For a v:var "vimvaridx" is set.
5594 * "type" is set to the destination type if known, unchanted otherwise.
5595 * Return FAIL if an error message was given.
5596 */
5597 static int
5598get_var_dest(
5599 char_u *name,
5600 assign_dest_T *dest,
5601 int cmdidx,
5602 int *opt_flags,
5603 int *vimvaridx,
5604 type_T **type,
5605 cctx_T *cctx)
5606{
5607 char_u *p;
5608
5609 if (*name == '&')
5610 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005611 int cc;
5612 long numval;
5613 getoption_T opt_type;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005614
5615 *dest = dest_option;
5616 if (cmdidx == CMD_final || cmdidx == CMD_const)
5617 {
5618 emsg(_(e_const_option));
5619 return FAIL;
5620 }
5621 p = name;
5622 p = find_option_end(&p, opt_flags);
5623 if (p == NULL)
5624 {
5625 // cannot happen?
5626 emsg(_(e_letunexp));
5627 return FAIL;
5628 }
5629 cc = *p;
5630 *p = NUL;
5631 opt_type = get_option_value(skip_option_env_lead(name),
5632 &numval, NULL, *opt_flags);
5633 *p = cc;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005634 switch (opt_type)
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005635 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005636 case gov_unknown:
5637 semsg(_(e_unknown_option), name);
5638 return FAIL;
5639 case gov_string:
5640 case gov_hidden_string:
5641 *type = &t_string;
5642 break;
5643 case gov_bool:
5644 case gov_hidden_bool:
5645 *type = &t_bool;
5646 break;
5647 case gov_number:
5648 case gov_hidden_number:
5649 *type = &t_number;
5650 break;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005651 }
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005652 }
5653 else if (*name == '$')
5654 {
5655 *dest = dest_env;
5656 *type = &t_string;
5657 }
5658 else if (*name == '@')
5659 {
5660 if (!valid_yank_reg(name[1], FALSE) || name[1] == '.')
5661 {
5662 emsg_invreg(name[1]);
5663 return FAIL;
5664 }
5665 *dest = dest_reg;
5666 *type = &t_string;
5667 }
5668 else if (STRNCMP(name, "g:", 2) == 0)
5669 {
5670 *dest = dest_global;
5671 }
5672 else if (STRNCMP(name, "b:", 2) == 0)
5673 {
5674 *dest = dest_buffer;
5675 }
5676 else if (STRNCMP(name, "w:", 2) == 0)
5677 {
5678 *dest = dest_window;
5679 }
5680 else if (STRNCMP(name, "t:", 2) == 0)
5681 {
5682 *dest = dest_tab;
5683 }
5684 else if (STRNCMP(name, "v:", 2) == 0)
5685 {
5686 typval_T *vtv;
5687 int di_flags;
5688
5689 *vimvaridx = find_vim_var(name + 2, &di_flags);
5690 if (*vimvaridx < 0)
5691 {
5692 semsg(_(e_variable_not_found_str), name);
5693 return FAIL;
5694 }
5695 // We use the current value of "sandbox" here, is that OK?
5696 if (var_check_ro(di_flags, name, FALSE))
5697 return FAIL;
5698 *dest = dest_vimvar;
5699 vtv = get_vim_var_tv(*vimvaridx);
5700 *type = typval2type_vimvar(vtv, cctx->ctx_type_list);
5701 }
5702 return OK;
5703}
5704
5705/*
5706 * Generate a STORE instruction for "dest", not being "dest_local".
5707 * Return FAIL when out of memory.
5708 */
5709 static int
5710generate_store_var(
5711 cctx_T *cctx,
5712 assign_dest_T dest,
5713 int opt_flags,
5714 int vimvaridx,
5715 int scriptvar_idx,
5716 int scriptvar_sid,
5717 type_T *type,
5718 char_u *name)
5719{
5720 switch (dest)
5721 {
5722 case dest_option:
5723 return generate_STOREOPT(cctx, skip_option_env_lead(name),
5724 opt_flags);
5725 case dest_global:
5726 // include g: with the name, easier to execute that way
Bram Moolenaar03290b82020-12-19 16:30:44 +01005727 return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL
5728 ? ISN_STOREG : ISN_STOREAUTO, 0, name);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005729 case dest_buffer:
5730 // include b: with the name, easier to execute that way
5731 return generate_STORE(cctx, ISN_STOREB, 0, name);
5732 case dest_window:
5733 // include w: with the name, easier to execute that way
5734 return generate_STORE(cctx, ISN_STOREW, 0, name);
5735 case dest_tab:
5736 // include t: with the name, easier to execute that way
5737 return generate_STORE(cctx, ISN_STORET, 0, name);
5738 case dest_env:
5739 return generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5740 case dest_reg:
5741 return generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5742 case dest_vimvar:
5743 return generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5744 case dest_script:
5745 if (scriptvar_idx < 0)
Bram Moolenaar643ce6c2021-04-06 21:17:27 +02005746 // "s:" may be included in the name.
5747 return generate_OLDSCRIPT(cctx, ISN_STORES, name,
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005748 scriptvar_sid, type);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005749 return generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
5750 scriptvar_sid, scriptvar_idx, type);
5751 case dest_local:
5752 case dest_expr:
5753 // cannot happen
5754 break;
5755 }
5756 return FAIL;
5757}
5758
Bram Moolenaar752fc692021-01-04 21:57:11 +01005759 static int
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02005760generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count)
5761{
5762 if (lhs->lhs_dest != dest_local)
5763 return generate_store_var(cctx, lhs->lhs_dest,
5764 lhs->lhs_opt_flags, lhs->lhs_vimvaridx,
5765 lhs->lhs_scriptvar_idx, lhs->lhs_scriptvar_sid,
5766 lhs->lhs_type, lhs->lhs_name);
5767
5768 if (lhs->lhs_lvar != NULL)
5769 {
5770 garray_T *instr = &cctx->ctx_instr;
5771 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
5772
5773 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE into
5774 // ISN_STORENR
5775 if (lhs->lhs_lvar->lv_from_outer == 0
5776 && instr->ga_len == instr_count + 1
5777 && isn->isn_type == ISN_PUSHNR)
5778 {
5779 varnumber_T val = isn->isn_arg.number;
5780 garray_T *stack = &cctx->ctx_type_stack;
5781
5782 isn->isn_type = ISN_STORENR;
5783 isn->isn_arg.storenr.stnr_idx = lhs->lhs_lvar->lv_idx;
5784 isn->isn_arg.storenr.stnr_val = val;
5785 if (stack->ga_len > 0)
5786 --stack->ga_len;
5787 }
5788 else if (lhs->lhs_lvar->lv_from_outer > 0)
5789 generate_STOREOUTER(cctx, lhs->lhs_lvar->lv_idx,
5790 lhs->lhs_lvar->lv_from_outer);
5791 else
5792 generate_STORE(cctx, ISN_STORE, lhs->lhs_lvar->lv_idx, NULL);
5793 }
5794 return OK;
5795}
5796
5797 static int
Bram Moolenaar752fc692021-01-04 21:57:11 +01005798is_decl_command(int cmdidx)
5799{
5800 return cmdidx == CMD_let || cmdidx == CMD_var
5801 || cmdidx == CMD_final || cmdidx == CMD_const;
5802}
5803
5804/*
5805 * Figure out the LHS type and other properties for an assignment or one item
5806 * of ":unlet" with an index.
5807 * Returns OK or FAIL.
5808 */
5809 static int
5810compile_lhs(
5811 char_u *var_start,
5812 lhs_T *lhs,
5813 int cmdidx,
5814 int heredoc,
5815 int oplen,
5816 cctx_T *cctx)
5817{
5818 char_u *var_end;
5819 int is_decl = is_decl_command(cmdidx);
5820
5821 CLEAR_POINTER(lhs);
5822 lhs->lhs_dest = dest_local;
5823 lhs->lhs_vimvaridx = -1;
5824 lhs->lhs_scriptvar_idx = -1;
5825
5826 // "dest_end" is the end of the destination, including "[expr]" or
5827 // ".name".
5828 // "var_end" is the end of the variable/option/etc. name.
5829 lhs->lhs_dest_end = skip_var_one(var_start, FALSE);
5830 if (*var_start == '@')
5831 var_end = var_start + 2;
5832 else
5833 {
5834 // skip over the leading "&", "&l:", "&g:" and "$"
5835 var_end = skip_option_env_lead(var_start);
5836 var_end = to_name_end(var_end, TRUE);
5837 }
5838
5839 // "a: type" is declaring variable "a" with a type, not dict "a:".
5840 if (is_decl && lhs->lhs_dest_end == var_start + 2
5841 && lhs->lhs_dest_end[-1] == ':')
5842 --lhs->lhs_dest_end;
5843 if (is_decl && var_end == var_start + 2 && var_end[-1] == ':')
5844 --var_end;
5845
5846 // compute the length of the destination without "[expr]" or ".name"
5847 lhs->lhs_varlen = var_end - var_start;
5848 lhs->lhs_name = vim_strnsave(var_start, lhs->lhs_varlen);
5849 if (lhs->lhs_name == NULL)
5850 return FAIL;
Bram Moolenaar08251752021-01-11 21:20:18 +01005851
5852 if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen)
5853 // Something follows after the variable: "var[idx]" or "var.key".
5854 lhs->lhs_has_index = TRUE;
5855
Bram Moolenaar752fc692021-01-04 21:57:11 +01005856 if (heredoc)
5857 lhs->lhs_type = &t_list_string;
5858 else
5859 lhs->lhs_type = &t_any;
5860
5861 if (cctx->ctx_skip != SKIP_YES)
5862 {
5863 int declare_error = FALSE;
5864
5865 if (get_var_dest(lhs->lhs_name, &lhs->lhs_dest, cmdidx,
5866 &lhs->lhs_opt_flags, &lhs->lhs_vimvaridx,
5867 &lhs->lhs_type, cctx) == FAIL)
5868 return FAIL;
Bram Moolenaard877a572021-04-01 19:42:48 +02005869 if (lhs->lhs_dest != dest_local
5870 && cmdidx != CMD_const && cmdidx != CMD_final)
Bram Moolenaar752fc692021-01-04 21:57:11 +01005871 {
5872 // Specific kind of variable recognized.
5873 declare_error = is_decl;
5874 }
5875 else
5876 {
5877 int idx;
5878
5879 // No specific kind of variable recognized, just a name.
5880 for (idx = 0; reserved[idx] != NULL; ++idx)
5881 if (STRCMP(reserved[idx], lhs->lhs_name) == 0)
5882 {
5883 semsg(_(e_cannot_use_reserved_name), lhs->lhs_name);
5884 return FAIL;
5885 }
5886
5887
5888 if (lookup_local(var_start, lhs->lhs_varlen,
5889 &lhs->lhs_local_lvar, cctx) == OK)
5890 lhs->lhs_lvar = &lhs->lhs_local_lvar;
5891 else
5892 {
5893 CLEAR_FIELD(lhs->lhs_arg_lvar);
5894 if (arg_exists(var_start, lhs->lhs_varlen,
5895 &lhs->lhs_arg_lvar.lv_idx, &lhs->lhs_arg_lvar.lv_type,
5896 &lhs->lhs_arg_lvar.lv_from_outer, cctx) == OK)
5897 {
5898 if (is_decl)
5899 {
5900 semsg(_(e_str_is_used_as_argument), lhs->lhs_name);
5901 return FAIL;
5902 }
5903 lhs->lhs_lvar = &lhs->lhs_arg_lvar;
5904 }
5905 }
5906 if (lhs->lhs_lvar != NULL)
5907 {
5908 if (is_decl)
5909 {
5910 semsg(_(e_variable_already_declared), lhs->lhs_name);
5911 return FAIL;
5912 }
5913 }
5914 else
5915 {
5916 int script_namespace = lhs->lhs_varlen > 1
5917 && STRNCMP(var_start, "s:", 2) == 0;
5918 int script_var = (script_namespace
5919 ? script_var_exists(var_start + 2, lhs->lhs_varlen - 2,
Bram Moolenaar15e5e532021-04-07 21:21:13 +02005920 cctx)
Bram Moolenaar752fc692021-01-04 21:57:11 +01005921 : script_var_exists(var_start, lhs->lhs_varlen,
Bram Moolenaar15e5e532021-04-07 21:21:13 +02005922 cctx)) == OK;
Bram Moolenaar752fc692021-01-04 21:57:11 +01005923 imported_T *import =
5924 find_imported(var_start, lhs->lhs_varlen, cctx);
5925
5926 if (script_namespace || script_var || import != NULL)
5927 {
5928 char_u *rawname = lhs->lhs_name
5929 + (lhs->lhs_name[1] == ':' ? 2 : 0);
5930
5931 if (is_decl)
5932 {
5933 if (script_namespace)
5934 semsg(_(e_cannot_declare_script_variable_in_function),
5935 lhs->lhs_name);
5936 else
Bram Moolenaar057e84a2021-02-28 16:55:11 +01005937 semsg(_(e_variable_already_declared_in_script_str),
Bram Moolenaar752fc692021-01-04 21:57:11 +01005938 lhs->lhs_name);
5939 return FAIL;
5940 }
5941 else if (cctx->ctx_ufunc->uf_script_ctx_version
5942 == SCRIPT_VERSION_VIM9
5943 && script_namespace
5944 && !script_var && import == NULL)
5945 {
5946 semsg(_(e_unknown_variable_str), lhs->lhs_name);
5947 return FAIL;
5948 }
5949
5950 lhs->lhs_dest = dest_script;
5951
5952 // existing script-local variables should have a type
5953 lhs->lhs_scriptvar_sid = current_sctx.sc_sid;
5954 if (import != NULL)
5955 lhs->lhs_scriptvar_sid = import->imp_sid;
5956 if (SCRIPT_ID_VALID(lhs->lhs_scriptvar_sid))
5957 {
Bram Moolenaar08251752021-01-11 21:20:18 +01005958 // Check writable only when no index follows.
Bram Moolenaar752fc692021-01-04 21:57:11 +01005959 lhs->lhs_scriptvar_idx = get_script_item_idx(
Bram Moolenaar08251752021-01-11 21:20:18 +01005960 lhs->lhs_scriptvar_sid, rawname,
5961 lhs->lhs_has_index ? ASSIGN_FINAL : ASSIGN_CONST,
5962 cctx);
Bram Moolenaar752fc692021-01-04 21:57:11 +01005963 if (lhs->lhs_scriptvar_idx >= 0)
5964 {
5965 scriptitem_T *si = SCRIPT_ITEM(
5966 lhs->lhs_scriptvar_sid);
5967 svar_T *sv =
5968 ((svar_T *)si->sn_var_vals.ga_data)
5969 + lhs->lhs_scriptvar_idx;
5970 lhs->lhs_type = sv->sv_type;
5971 }
5972 }
5973 }
Bram Moolenaar057e84a2021-02-28 16:55:11 +01005974 else if (check_defined(var_start, lhs->lhs_varlen, cctx, FALSE)
Bram Moolenaar752fc692021-01-04 21:57:11 +01005975 == FAIL)
5976 return FAIL;
5977 }
5978 }
5979
5980 if (declare_error)
5981 {
5982 vim9_declare_error(lhs->lhs_name);
5983 return FAIL;
5984 }
5985 }
5986
5987 // handle "a:name" as a name, not index "name" on "a"
5988 if (lhs->lhs_varlen > 1 || var_start[lhs->lhs_varlen] != ':')
5989 var_end = lhs->lhs_dest_end;
5990
5991 if (lhs->lhs_dest != dest_option)
5992 {
5993 if (is_decl && *var_end == ':')
5994 {
5995 char_u *p;
5996
5997 // parse optional type: "let var: type = expr"
5998 if (!VIM_ISWHITE(var_end[1]))
5999 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01006000 semsg(_(e_white_space_required_after_str_str), ":", var_end);
Bram Moolenaar752fc692021-01-04 21:57:11 +01006001 return FAIL;
6002 }
6003 p = skipwhite(var_end + 1);
6004 lhs->lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
6005 if (lhs->lhs_type == NULL)
6006 return FAIL;
6007 lhs->lhs_has_type = TRUE;
6008 }
6009 else if (lhs->lhs_lvar != NULL)
6010 lhs->lhs_type = lhs->lhs_lvar->lv_type;
6011 }
6012
Bram Moolenaare42939a2021-04-05 17:11:17 +02006013 if (oplen == 3 && !heredoc
6014 && lhs->lhs_dest != dest_global
6015 && !lhs->lhs_has_index
6016 && lhs->lhs_type->tt_type != VAR_STRING
6017 && lhs->lhs_type->tt_type != VAR_ANY)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006018 {
6019 emsg(_(e_can_only_concatenate_to_string));
6020 return FAIL;
6021 }
6022
6023 if (lhs->lhs_lvar == NULL && lhs->lhs_dest == dest_local
6024 && cctx->ctx_skip != SKIP_YES)
6025 {
6026 if (oplen > 1 && !heredoc)
6027 {
6028 // +=, /=, etc. require an existing variable
6029 semsg(_(e_cannot_use_operator_on_new_variable), lhs->lhs_name);
6030 return FAIL;
6031 }
6032 if (!is_decl)
6033 {
6034 semsg(_(e_unknown_variable_str), lhs->lhs_name);
6035 return FAIL;
6036 }
6037
Bram Moolenaar3f327882021-03-17 20:56:38 +01006038 // Check the name is valid for a funcref.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006039 if ((lhs->lhs_type->tt_type == VAR_FUNC
6040 || lhs->lhs_type->tt_type == VAR_PARTIAL)
Bram Moolenaar3f327882021-03-17 20:56:38 +01006041 && var_wrong_func_name(lhs->lhs_name, TRUE))
Bram Moolenaar752fc692021-01-04 21:57:11 +01006042 return FAIL;
Bram Moolenaar3f327882021-03-17 20:56:38 +01006043
6044 // New local variable.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006045 lhs->lhs_lvar = reserve_local(cctx, var_start, lhs->lhs_varlen,
6046 cmdidx == CMD_final || cmdidx == CMD_const, lhs->lhs_type);
6047 if (lhs->lhs_lvar == NULL)
6048 return FAIL;
6049 lhs->lhs_new_local = TRUE;
6050 }
6051
6052 lhs->lhs_member_type = lhs->lhs_type;
Bram Moolenaar08251752021-01-11 21:20:18 +01006053 if (lhs->lhs_has_index)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006054 {
6055 // Something follows after the variable: "var[idx]" or "var.key".
6056 // TODO: should we also handle "->func()" here?
6057 if (is_decl)
6058 {
6059 emsg(_(e_cannot_use_index_when_declaring_variable));
6060 return FAIL;
6061 }
6062
6063 if (var_start[lhs->lhs_varlen] == '['
6064 || var_start[lhs->lhs_varlen] == '.')
6065 {
6066 char_u *after = var_start + lhs->lhs_varlen;
6067 char_u *p;
6068
6069 // Only the last index is used below, if there are others
6070 // before it generate code for the expression. Thus for
6071 // "ll[1][2]" the expression is "ll[1]" and "[2]" is the index.
6072 for (;;)
6073 {
6074 p = skip_index(after);
6075 if (*p != '[' && *p != '.')
6076 break;
6077 after = p;
6078 }
6079 if (after > var_start + lhs->lhs_varlen)
6080 {
6081 lhs->lhs_varlen = after - var_start;
6082 lhs->lhs_dest = dest_expr;
6083 // We don't know the type before evaluating the expression,
6084 // use "any" until then.
6085 lhs->lhs_type = &t_any;
6086 }
6087
Bram Moolenaar752fc692021-01-04 21:57:11 +01006088 if (lhs->lhs_type->tt_member == NULL)
6089 lhs->lhs_member_type = &t_any;
6090 else
6091 lhs->lhs_member_type = lhs->lhs_type->tt_member;
6092 }
6093 else
6094 {
6095 semsg("Not supported yet: %s", var_start);
6096 return FAIL;
6097 }
6098 }
6099 return OK;
6100}
6101
6102/*
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02006103 * Figure out the LHS and check a few errors.
6104 */
6105 static int
6106compile_assign_lhs(
6107 char_u *var_start,
6108 lhs_T *lhs,
6109 int cmdidx,
6110 int is_decl,
6111 int heredoc,
6112 int oplen,
6113 cctx_T *cctx)
6114{
6115 if (compile_lhs(var_start, lhs, cmdidx, heredoc, oplen, cctx) == FAIL)
6116 return FAIL;
6117
6118 if (!lhs->lhs_has_index && lhs->lhs_lvar == &lhs->lhs_arg_lvar)
6119 {
6120 semsg(_(e_cannot_assign_to_argument), lhs->lhs_name);
6121 return FAIL;
6122 }
6123 if (!is_decl && lhs->lhs_lvar != NULL
6124 && lhs->lhs_lvar->lv_const && !lhs->lhs_has_index)
6125 {
6126 semsg(_(e_cannot_assign_to_constant), lhs->lhs_name);
6127 return FAIL;
6128 }
6129 return OK;
6130}
6131
6132/*
Bram Moolenaare42939a2021-04-05 17:11:17 +02006133 * For an assignment with an index, compile the "idx" in "var[idx]" or "key" in
6134 * "var.key".
Bram Moolenaar752fc692021-01-04 21:57:11 +01006135 */
6136 static int
Bram Moolenaare42939a2021-04-05 17:11:17 +02006137compile_assign_index(
Bram Moolenaar752fc692021-01-04 21:57:11 +01006138 char_u *var_start,
6139 lhs_T *lhs,
Bram Moolenaare42939a2021-04-05 17:11:17 +02006140 int *range,
Bram Moolenaar752fc692021-01-04 21:57:11 +01006141 cctx_T *cctx)
6142{
Bram Moolenaar752fc692021-01-04 21:57:11 +01006143 size_t varlen = lhs->lhs_varlen;
Bram Moolenaare42939a2021-04-05 17:11:17 +02006144 char_u *p;
6145 int r = OK;
Bram Moolenaar68452172021-04-12 21:21:02 +02006146 int need_white_before = TRUE;
6147 int empty_second;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006148
Bram Moolenaar752fc692021-01-04 21:57:11 +01006149 p = var_start + varlen;
6150 if (*p == '[')
6151 {
6152 p = skipwhite(p + 1);
Bram Moolenaar68452172021-04-12 21:21:02 +02006153 if (*p == ':')
6154 {
6155 // empty first index, push zero
6156 r = generate_PUSHNR(cctx, 0);
6157 need_white_before = FALSE;
6158 }
6159 else
6160 r = compile_expr0(&p, cctx);
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006161
6162 if (r == OK && *skipwhite(p) == ':')
6163 {
6164 // unlet var[idx : idx]
Bram Moolenaar68452172021-04-12 21:21:02 +02006165 // blob[idx : idx] = value
Bram Moolenaare42939a2021-04-05 17:11:17 +02006166 *range = TRUE;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006167 p = skipwhite(p);
Bram Moolenaar68452172021-04-12 21:21:02 +02006168 empty_second = *skipwhite(p + 1) == ']';
6169 if ((need_white_before && !IS_WHITE_OR_NUL(p[-1]))
6170 || (!empty_second && !IS_WHITE_OR_NUL(p[1])))
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006171 {
6172 semsg(_(e_white_space_required_before_and_after_str_at_str),
6173 ":", p);
6174 return FAIL;
6175 }
6176 p = skipwhite(p + 1);
Bram Moolenaar68452172021-04-12 21:21:02 +02006177 if (*p == ']')
6178 // empty second index, push "none"
6179 r = generate_PUSHSPEC(cctx, VVAL_NONE);
6180 else
6181 r = compile_expr0(&p, cctx);
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006182 }
6183
Bram Moolenaar752fc692021-01-04 21:57:11 +01006184 if (r == OK && *skipwhite(p) != ']')
6185 {
6186 // this should not happen
6187 emsg(_(e_missbrac));
6188 r = FAIL;
6189 }
6190 }
6191 else // if (*p == '.')
6192 {
6193 char_u *key_end = to_name_end(p + 1, TRUE);
6194 char_u *key = vim_strnsave(p + 1, key_end - p - 1);
6195
6196 r = generate_PUSHS(cctx, key);
6197 }
Bram Moolenaare42939a2021-04-05 17:11:17 +02006198 return r;
6199}
6200
6201/*
Bram Moolenaarb9c0cd82021-04-05 20:51:00 +02006202 * For a LHS with an index, load the variable to be indexed.
6203 */
6204 static int
6205compile_load_lhs(
6206 lhs_T *lhs,
6207 char_u *var_start,
6208 type_T *rhs_type,
6209 cctx_T *cctx)
6210{
6211 if (lhs->lhs_dest == dest_expr)
6212 {
6213 size_t varlen = lhs->lhs_varlen;
6214 int c = var_start[varlen];
6215 char_u *p = var_start;
6216 garray_T *stack = &cctx->ctx_type_stack;
6217
6218 // Evaluate "ll[expr]" of "ll[expr][idx]"
6219 var_start[varlen] = NUL;
6220 if (compile_expr0(&p, cctx) == OK && p != var_start + varlen)
6221 {
6222 // this should not happen
6223 emsg(_(e_missbrac));
Bram Moolenaarc9605f02021-04-06 21:29:32 +02006224 var_start[varlen] = c;
Bram Moolenaarb9c0cd82021-04-05 20:51:00 +02006225 return FAIL;
6226 }
6227 var_start[varlen] = c;
6228
6229 lhs->lhs_type = stack->ga_len == 0 ? &t_void
6230 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
6231 // now we can properly check the type
6232 if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL
6233 && rhs_type != &t_void
6234 && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx,
6235 FALSE, FALSE) == FAIL)
6236 return FAIL;
6237 }
6238 else
6239 generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name,
6240 lhs->lhs_lvar, lhs->lhs_type);
6241 return OK;
6242}
6243
6244/*
Bram Moolenaare42939a2021-04-05 17:11:17 +02006245 * Assignment to a list or dict member, or ":unlet" for the item, using the
6246 * information in "lhs".
6247 * Returns OK or FAIL.
6248 */
6249 static int
6250compile_assign_unlet(
6251 char_u *var_start,
6252 lhs_T *lhs,
6253 int is_assign,
6254 type_T *rhs_type,
6255 cctx_T *cctx)
6256{
Bram Moolenaare42939a2021-04-05 17:11:17 +02006257 vartype_T dest_type;
Bram Moolenaare42939a2021-04-05 17:11:17 +02006258 garray_T *stack = &cctx->ctx_type_stack;
6259 int range = FALSE;
6260
Bram Moolenaar68452172021-04-12 21:21:02 +02006261 if (compile_assign_index(var_start, lhs, &range, cctx) == FAIL)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006262 return FAIL;
Bram Moolenaar68452172021-04-12 21:21:02 +02006263 if (is_assign && range && lhs->lhs_type != &t_blob
6264 && lhs->lhs_type != &t_any)
6265 {
6266 semsg(_(e_cannot_use_range_with_assignment_str), var_start);
6267 return FAIL;
6268 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006269
6270 if (lhs->lhs_type == &t_any)
6271 {
6272 // Index on variable of unknown type: check at runtime.
6273 dest_type = VAR_ANY;
6274 }
6275 else
6276 {
6277 dest_type = lhs->lhs_type->tt_type;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006278 if (dest_type == VAR_DICT && range)
6279 {
6280 emsg(e_cannot_use_range_with_dictionary);
6281 return FAIL;
6282 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006283 if (dest_type == VAR_DICT && may_generate_2STRING(-1, cctx) == FAIL)
6284 return FAIL;
Bram Moolenaar51e93322021-04-17 20:44:56 +02006285 if (dest_type == VAR_LIST || dest_type == VAR_BLOB)
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006286 {
Bram Moolenaar51e93322021-04-17 20:44:56 +02006287 type_T *type;
6288
6289 if (range)
6290 {
6291 type = ((type_T **)stack->ga_data)[stack->ga_len - 2];
6292 if (need_type(type, &t_number,
6293 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006294 return FAIL;
Bram Moolenaar51e93322021-04-17 20:44:56 +02006295 }
6296 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6297 if ((dest_type != VAR_BLOB || type != &t_special)
6298 && need_type(type, &t_number,
6299 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006300 return FAIL;
6301 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006302 }
6303
6304 // Load the dict or list. On the stack we then have:
6305 // - value (for assignment, not for :unlet)
6306 // - index
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006307 // - for [a : b] second index
Bram Moolenaar752fc692021-01-04 21:57:11 +01006308 // - variable
Bram Moolenaarb9c0cd82021-04-05 20:51:00 +02006309 if (compile_load_lhs(lhs, var_start, rhs_type, cctx) == FAIL)
6310 return FAIL;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006311
Bram Moolenaar68452172021-04-12 21:21:02 +02006312 if (dest_type == VAR_LIST || dest_type == VAR_DICT
6313 || dest_type == VAR_BLOB || dest_type == VAR_ANY)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006314 {
6315 if (is_assign)
6316 {
Bram Moolenaar68452172021-04-12 21:21:02 +02006317 if (range)
6318 {
6319 if (generate_instr_drop(cctx, ISN_STORERANGE, 4) == NULL)
6320 return FAIL;
6321 }
6322 else
6323 {
6324 isn_T *isn = generate_instr_drop(cctx, ISN_STOREINDEX, 3);
Bram Moolenaar752fc692021-01-04 21:57:11 +01006325
Bram Moolenaar68452172021-04-12 21:21:02 +02006326 if (isn == NULL)
6327 return FAIL;
6328 isn->isn_arg.vartype = dest_type;
6329 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006330 }
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006331 else if (range)
6332 {
6333 if (generate_instr_drop(cctx, ISN_UNLETRANGE, 3) == NULL)
6334 return FAIL;
6335 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006336 else
6337 {
6338 if (generate_instr_drop(cctx, ISN_UNLETINDEX, 2) == NULL)
6339 return FAIL;
6340 }
6341 }
6342 else
6343 {
6344 emsg(_(e_indexable_type_required));
6345 return FAIL;
6346 }
6347
6348 return OK;
6349}
6350
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006351/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006352 * Compile declaration and assignment:
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006353 * "let name"
6354 * "var name = expr"
6355 * "final name = expr"
6356 * "const name = expr"
6357 * "name = expr"
6358 * "arg" points to "name".
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006359 * Return NULL for an error.
6360 * Return "arg" if it does not look like a variable list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006361 */
6362 static char_u *
6363compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
6364{
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006365 char_u *var_start;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006366 char_u *p;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006367 char_u *end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006368 char_u *ret = NULL;
6369 int var_count = 0;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006370 int var_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006371 int semicolon = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006372 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006373 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006374 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006375 int oplen = 0;
6376 int heredoc = FALSE;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006377 type_T *rhs_type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006378 char_u *sp;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006379 int is_decl = is_decl_command(cmdidx);
6380 lhs_T lhs;
Bram Moolenaar77709b12021-04-03 21:01:01 +02006381 long start_lnum = SOURCING_LNUM;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006382
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006383 // Skip over the "var" or "[var, var]" to get to any "=".
6384 p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
6385 if (p == NULL)
6386 return *arg == '[' ? arg : NULL;
6387
6388 if (var_count > 0 && is_decl)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006389 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02006390 // TODO: should we allow this, and figure out type inference from list
6391 // members?
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006392 emsg(_(e_cannot_use_list_for_declaration));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006393 return NULL;
6394 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006395 lhs.lhs_name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006396
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006397 sp = p;
6398 p = skipwhite(p);
6399 op = p;
6400 oplen = assignment_len(p, &heredoc);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006401
6402 if (var_count > 0 && oplen == 0)
6403 // can be something like "[1, 2]->func()"
6404 return arg;
6405
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006406 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !IS_WHITE_OR_NUL(op[oplen])))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006407 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02006408 error_white_both(op, oplen);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006409 return NULL;
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02006410 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006411
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006412 if (heredoc)
6413 {
6414 list_T *l;
6415 listitem_T *li;
6416
6417 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02006418 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006419 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02006420 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaarc0e29012020-09-27 14:22:48 +02006421 if (l == NULL)
6422 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006423
Bram Moolenaar078269b2020-09-21 20:35:55 +02006424 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006425 {
Bram Moolenaar078269b2020-09-21 20:35:55 +02006426 // Push each line and the create the list.
6427 FOR_ALL_LIST_ITEMS(l, li)
6428 {
6429 generate_PUSHS(cctx, li->li_tv.vval.v_string);
6430 li->li_tv.vval.v_string = NULL;
6431 }
6432 generate_NEWLIST(cctx, l->lv_len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006433 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006434 list_free(l);
6435 p += STRLEN(p);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006436 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006437 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006438 else if (var_count > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006439 {
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006440 char_u *wp;
6441
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006442 // for "[var, var] = expr" evaluate the expression here, loop over the
6443 // list of variables below.
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006444 // A line break may follow the "=".
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02006445
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006446 wp = op + oplen;
Bram Moolenaar8ff16e02020-12-07 21:49:52 +01006447 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006448 return FAIL;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006449 if (compile_expr0(&p, cctx) == FAIL)
6450 return NULL;
6451 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006452
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006453 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006454 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006455 type_T *stacktype;
6456
Bram Moolenaarec5929d2020-04-07 20:53:39 +02006457 stacktype = stack->ga_len == 0 ? &t_void
6458 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006459 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006460 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006461 emsg(_(e_cannot_use_void_value));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006462 goto theend;
6463 }
Bram Moolenaar351ead02021-01-16 16:07:01 +01006464 if (need_type(stacktype, &t_list_any, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006465 FALSE, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006466 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02006467 // TODO: check the length of a constant list here
Bram Moolenaar9af78762020-06-16 11:34:42 +02006468 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
6469 semicolon);
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006470 if (stacktype->tt_member != NULL)
6471 rhs_type = stacktype->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006472 }
6473 }
6474
6475 /*
6476 * Loop over variables in "[var, var] = expr".
6477 * For "var = expr" and "let var: type" this is done only once.
6478 */
6479 if (var_count > 0)
6480 var_start = skipwhite(arg + 1); // skip over the "["
6481 else
6482 var_start = arg;
6483 for (var_idx = 0; var_idx == 0 || var_idx < var_count; var_idx++)
6484 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006485 int instr_count = -1;
6486
Bram Moolenaarf93bbd02021-04-10 22:35:43 +02006487 if (var_start[0] == '_' && !eval_isnamec(var_start[1]))
6488 {
6489 // Ignore underscore in "[a, _, b] = list".
6490 if (var_count > 0)
6491 {
6492 var_start = skipwhite(var_start + 2);
6493 continue;
6494 }
6495 emsg(_(e_cannot_use_underscore_here));
6496 goto theend;
6497 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006498 vim_free(lhs.lhs_name);
6499
6500 /*
6501 * Figure out the LHS type and other properties.
6502 */
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02006503 if (compile_assign_lhs(var_start, &lhs, cmdidx,
6504 is_decl, heredoc, oplen, cctx) == FAIL)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006505 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006506 if (!heredoc)
6507 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006508 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006509 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006510 if (oplen > 0 && var_count == 0)
6511 {
6512 // skip over the "=" and the expression
6513 p = skipwhite(op + oplen);
6514 compile_expr0(&p, cctx);
6515 }
6516 }
6517 else if (oplen > 0)
6518 {
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006519 int is_const = FALSE;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006520 char_u *wp;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006521
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006522 // For "var = expr" evaluate the expression.
6523 if (var_count == 0)
6524 {
6525 int r;
6526
6527 // for "+=", "*=", "..=" etc. first load the current value
6528 if (*op != '=')
6529 {
Bram Moolenaarb9c0cd82021-04-05 20:51:00 +02006530 compile_load_lhs(&lhs, var_start, NULL, cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006531
Bram Moolenaar752fc692021-01-04 21:57:11 +01006532 if (lhs.lhs_has_index)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006533 {
Bram Moolenaare42939a2021-04-05 17:11:17 +02006534 int range = FALSE;
6535
6536 // Get member from list or dict. First compile the
6537 // index value.
6538 if (compile_assign_index(var_start, &lhs,
Bram Moolenaar68452172021-04-12 21:21:02 +02006539 &range, cctx) == FAIL)
Bram Moolenaare42939a2021-04-05 17:11:17 +02006540 goto theend;
Bram Moolenaar68452172021-04-12 21:21:02 +02006541 if (range)
6542 {
Bram Moolenaarb1419262021-04-14 20:54:07 +02006543 semsg(_(e_cannot_use_range_with_assignment_operator_str),
Bram Moolenaar68452172021-04-12 21:21:02 +02006544 var_start);
Bram Moolenaarf387f5d2021-04-15 13:42:21 +02006545 goto theend;
Bram Moolenaar68452172021-04-12 21:21:02 +02006546 }
Bram Moolenaare42939a2021-04-05 17:11:17 +02006547
6548 // Get the member.
6549 if (compile_member(FALSE, cctx) == FAIL)
6550 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006551 }
6552 }
6553
6554 // Compile the expression. Temporarily hide the new local
6555 // variable here, it is not available to this expression.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006556 if (lhs.lhs_new_local)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006557 --cctx->ctx_locals.ga_len;
6558 instr_count = instr->ga_len;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006559 wp = op + oplen;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006560 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
Bram Moolenaar21e51222020-12-04 12:43:29 +01006561 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006562 if (lhs.lhs_new_local)
Bram Moolenaar21e51222020-12-04 12:43:29 +01006563 ++cctx->ctx_locals.ga_len;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006564 goto theend;
Bram Moolenaar21e51222020-12-04 12:43:29 +01006565 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006566 r = compile_expr0_ext(&p, cctx, &is_const);
Bram Moolenaar752fc692021-01-04 21:57:11 +01006567 if (lhs.lhs_new_local)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006568 ++cctx->ctx_locals.ga_len;
6569 if (r == FAIL)
6570 goto theend;
6571 }
Bram Moolenaar9af78762020-06-16 11:34:42 +02006572 else if (semicolon && var_idx == var_count - 1)
6573 {
6574 // For "[var; var] = expr" get the rest of the list
6575 if (generate_SLICE(cctx, var_count - 1) == FAIL)
6576 goto theend;
6577 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006578 else
6579 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006580 // For "[var, var] = expr" get the "var_idx" item from the
6581 // list.
6582 if (generate_GETITEM(cctx, var_idx) == FAIL)
Bram Moolenaar7f764942020-12-02 15:11:18 +01006583 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006584 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006585
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006586 rhs_type = stack->ga_len == 0 ? &t_void
Bram Moolenaar6802cce2020-07-19 15:49:49 +02006587 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar752fc692021-01-04 21:57:11 +01006588 if (lhs.lhs_lvar != NULL && (is_decl || !lhs.lhs_has_type))
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006589 {
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006590 if ((rhs_type->tt_type == VAR_FUNC
6591 || rhs_type->tt_type == VAR_PARTIAL)
Bram Moolenaar3f327882021-03-17 20:56:38 +01006592 && !lhs.lhs_has_index
Bram Moolenaar752fc692021-01-04 21:57:11 +01006593 && var_wrong_func_name(lhs.lhs_name, TRUE))
Bram Moolenaar0f769812020-09-12 18:32:34 +02006594 goto theend;
6595
Bram Moolenaar752fc692021-01-04 21:57:11 +01006596 if (lhs.lhs_new_local && !lhs.lhs_has_type)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006597 {
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006598 if (rhs_type->tt_type == VAR_VOID)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006599 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006600 emsg(_(e_cannot_use_void_value));
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006601 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006602 }
6603 else
6604 {
Bram Moolenaar04bdd572020-09-23 13:25:32 +02006605 // An empty list or dict has a &t_unknown member,
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006606 // for a variable that implies &t_any.
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006607 if (rhs_type == &t_list_empty)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006608 lhs.lhs_lvar->lv_type = &t_list_any;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006609 else if (rhs_type == &t_dict_empty)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006610 lhs.lhs_lvar->lv_type = &t_dict_any;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006611 else if (rhs_type == &t_unknown)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006612 lhs.lhs_lvar->lv_type = &t_any;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006613 else
Bram Moolenaar752fc692021-01-04 21:57:11 +01006614 lhs.lhs_lvar->lv_type = rhs_type;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006615 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006616 }
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006617 else if (*op == '=')
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006618 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006619 type_T *use_type = lhs.lhs_lvar->lv_type;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006620
Bram Moolenaar77709b12021-04-03 21:01:01 +02006621 // Without operator check type here, otherwise below.
6622 // Use the line number of the assignment.
6623 SOURCING_LNUM = start_lnum;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006624 if (lhs.lhs_has_index)
6625 use_type = lhs.lhs_member_type;
Bram Moolenaar351ead02021-01-16 16:07:01 +01006626 if (need_type(rhs_type, use_type, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006627 FALSE, is_const) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006628 goto theend;
6629 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006630 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006631 else if (*p != '=' && need_type(rhs_type, lhs.lhs_member_type,
Bram Moolenaar351ead02021-01-16 16:07:01 +01006632 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006633 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006634 }
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006635 else if (cmdidx == CMD_final)
6636 {
6637 emsg(_(e_final_requires_a_value));
6638 goto theend;
6639 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006640 else if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006641 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02006642 emsg(_(e_const_requires_a_value));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006643 goto theend;
6644 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006645 else if (!lhs.lhs_has_type || lhs.lhs_dest == dest_option)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006646 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02006647 emsg(_(e_type_or_initialization_required));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006648 goto theend;
6649 }
6650 else
6651 {
6652 // variables are always initialized
6653 if (ga_grow(instr, 1) == FAIL)
6654 goto theend;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006655 switch (lhs.lhs_member_type->tt_type)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006656 {
6657 case VAR_BOOL:
6658 generate_PUSHBOOL(cctx, VVAL_FALSE);
6659 break;
6660 case VAR_FLOAT:
6661#ifdef FEAT_FLOAT
6662 generate_PUSHF(cctx, 0.0);
6663#endif
6664 break;
6665 case VAR_STRING:
6666 generate_PUSHS(cctx, NULL);
6667 break;
6668 case VAR_BLOB:
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02006669 generate_PUSHBLOB(cctx, blob_alloc());
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006670 break;
6671 case VAR_FUNC:
6672 generate_PUSHFUNC(cctx, NULL, &t_func_void);
6673 break;
6674 case VAR_LIST:
6675 generate_NEWLIST(cctx, 0);
6676 break;
6677 case VAR_DICT:
6678 generate_NEWDICT(cctx, 0);
6679 break;
6680 case VAR_JOB:
6681 generate_PUSHJOB(cctx, NULL);
6682 break;
6683 case VAR_CHANNEL:
6684 generate_PUSHCHANNEL(cctx, NULL);
6685 break;
6686 case VAR_NUMBER:
6687 case VAR_UNKNOWN:
6688 case VAR_ANY:
6689 case VAR_PARTIAL:
6690 case VAR_VOID:
6691 case VAR_SPECIAL: // cannot happen
6692 generate_PUSHNR(cctx, 0);
6693 break;
6694 }
6695 }
6696 if (var_count == 0)
6697 end = p;
6698 }
6699
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006700 // no need to parse more when skipping
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006701 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006702 break;
6703
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006704 if (oplen > 0 && *op != '=')
6705 {
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006706 type_T *expected;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006707 type_T *stacktype;
6708
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006709 if (*op == '.')
6710 expected = &t_string;
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006711 else
Bram Moolenaar752fc692021-01-04 21:57:11 +01006712 expected = lhs.lhs_member_type;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006713 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006714 if (
6715#ifdef FEAT_FLOAT
6716 // If variable is float operation with number is OK.
6717 !(expected == &t_float && stacktype == &t_number) &&
6718#endif
Bram Moolenaar351ead02021-01-16 16:07:01 +01006719 need_type(stacktype, expected, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006720 FALSE, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006721 goto theend;
6722
6723 if (*op == '.')
Bram Moolenaardd29f1b2020-08-07 20:46:20 +02006724 {
6725 if (generate_instr_drop(cctx, ISN_CONCAT, 1) == NULL)
6726 goto theend;
6727 }
6728 else if (*op == '+')
6729 {
6730 if (generate_add_instr(cctx,
Bram Moolenaar752fc692021-01-04 21:57:11 +01006731 operator_type(lhs.lhs_member_type, stacktype),
6732 lhs.lhs_member_type, stacktype) == FAIL)
Bram Moolenaardd29f1b2020-08-07 20:46:20 +02006733 goto theend;
6734 }
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006735 else if (generate_two_op(cctx, op) == FAIL)
6736 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006737 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006738
Bram Moolenaar752fc692021-01-04 21:57:11 +01006739 if (lhs.lhs_has_index)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006740 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006741 // Use the info in "lhs" to store the value at the index in the
6742 // list or dict.
6743 if (compile_assign_unlet(var_start, &lhs, TRUE, rhs_type, cctx)
6744 == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006745 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006746 }
6747 else
6748 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006749 if (is_decl && cmdidx == CMD_const && (lhs.lhs_dest == dest_script
Bram Moolenaard877a572021-04-01 19:42:48 +02006750 || lhs.lhs_dest == dest_global
Bram Moolenaar752fc692021-01-04 21:57:11 +01006751 || lhs.lhs_dest == dest_local))
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006752 // ":const var": lock the value, but not referenced variables
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02006753 generate_LOCKCONST(cctx);
6754
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006755 if (is_decl
Bram Moolenaar752fc692021-01-04 21:57:11 +01006756 && (lhs.lhs_type->tt_type == VAR_DICT
6757 || lhs.lhs_type->tt_type == VAR_LIST)
6758 && lhs.lhs_type->tt_member != NULL
6759 && lhs.lhs_type->tt_member != &t_any
6760 && lhs.lhs_type->tt_member != &t_unknown)
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006761 // Set the type in the list or dict, so that it can be checked,
6762 // also in legacy script.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006763 generate_SETTYPE(cctx, lhs.lhs_type);
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006764
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02006765 if (generate_store_lhs(cctx, &lhs, instr_count) == FAIL)
6766 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006767 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006768
6769 if (var_idx + 1 < var_count)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006770 var_start = skipwhite(lhs.lhs_dest_end + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006771 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006772
6773 // for "[var, var] = expr" drop the "expr" value
Bram Moolenaar9af78762020-06-16 11:34:42 +02006774 if (var_count > 0 && !semicolon)
6775 {
Bram Moolenaarec792292020-12-13 21:26:56 +01006776 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
Bram Moolenaar9af78762020-06-16 11:34:42 +02006777 goto theend;
6778 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006779
Bram Moolenaarb2097502020-07-19 17:17:02 +02006780 ret = skipwhite(end);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006781
6782theend:
Bram Moolenaar752fc692021-01-04 21:57:11 +01006783 vim_free(lhs.lhs_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006784 return ret;
6785}
6786
6787/*
Bram Moolenaar17126b12021-01-07 22:03:02 +01006788 * Check for an assignment at "eap->cmd", compile it if found.
6789 * Return NOTDONE if there is none, FAIL for failure, OK if done.
6790 */
6791 static int
6792may_compile_assignment(exarg_T *eap, char_u **line, cctx_T *cctx)
6793{
6794 char_u *pskip;
6795 char_u *p;
6796
6797 // Assuming the command starts with a variable or function name,
6798 // find what follows.
6799 // Skip over "var.member", "var[idx]" and the like.
6800 // Also "&opt = val", "$ENV = val" and "@r = val".
6801 pskip = (*eap->cmd == '&' || *eap->cmd == '$' || *eap->cmd == '@')
6802 ? eap->cmd + 1 : eap->cmd;
6803 p = to_name_end(pskip, TRUE);
6804 if (p > eap->cmd && *p != NUL)
6805 {
6806 char_u *var_end;
6807 int oplen;
6808 int heredoc;
6809
6810 if (eap->cmd[0] == '@')
6811 var_end = eap->cmd + 2;
6812 else
6813 var_end = find_name_end(pskip, NULL, NULL,
6814 FNE_CHECK_START | FNE_INCL_BR);
6815 oplen = assignment_len(skipwhite(var_end), &heredoc);
6816 if (oplen > 0)
6817 {
6818 size_t len = p - eap->cmd;
6819
6820 // Recognize an assignment if we recognize the variable
6821 // name:
6822 // "g:var = expr"
6823 // "local = expr" where "local" is a local var.
6824 // "script = expr" where "script" is a script-local var.
6825 // "import = expr" where "import" is an imported var
6826 // "&opt = expr"
6827 // "$ENV = expr"
6828 // "@r = expr"
6829 if (*eap->cmd == '&'
6830 || *eap->cmd == '$'
6831 || *eap->cmd == '@'
6832 || ((len) > 2 && eap->cmd[1] == ':')
Bram Moolenaare0890d62021-02-17 14:52:14 +01006833 || variable_exists(eap->cmd, len, cctx))
Bram Moolenaar17126b12021-01-07 22:03:02 +01006834 {
6835 *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx);
6836 if (*line == NULL || *line == eap->cmd)
6837 return FAIL;
6838 return OK;
6839 }
6840 }
6841 }
6842
6843 if (*eap->cmd == '[')
6844 {
6845 // [var, var] = expr
6846 *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx);
6847 if (*line == NULL)
6848 return FAIL;
6849 if (*line != eap->cmd)
6850 return OK;
6851 }
6852 return NOTDONE;
6853}
6854
6855/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006856 * Check if "name" can be "unlet".
6857 */
6858 int
6859check_vim9_unlet(char_u *name)
6860{
6861 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
6862 {
Bram Moolenaar84367732020-08-23 15:21:55 +02006863 // "unlet s:var" is allowed in legacy script.
6864 if (*name == 's' && !script_is_vim9())
6865 return OK;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006866 semsg(_(e_cannot_unlet_str), name);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006867 return FAIL;
6868 }
6869 return OK;
6870}
6871
6872/*
6873 * Callback passed to ex_unletlock().
6874 */
6875 static int
6876compile_unlet(
6877 lval_T *lvp,
6878 char_u *name_end,
6879 exarg_T *eap,
6880 int deep UNUSED,
6881 void *coookie)
6882{
Bram Moolenaar752fc692021-01-04 21:57:11 +01006883 cctx_T *cctx = coookie;
6884 char_u *p = lvp->ll_name;
6885 int cc = *name_end;
6886 int ret = OK;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006887
Bram Moolenaar752fc692021-01-04 21:57:11 +01006888 if (cctx->ctx_skip == SKIP_YES)
6889 return OK;
6890
6891 *name_end = NUL;
6892 if (*p == '$')
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006893 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006894 // :unlet $ENV_VAR
6895 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
6896 }
6897 else if (vim_strchr(p, '.') != NULL || vim_strchr(p, '[') != NULL)
6898 {
6899 lhs_T lhs;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006900
Bram Moolenaar752fc692021-01-04 21:57:11 +01006901 // This is similar to assigning: lookup the list/dict, compile the
6902 // idx/key. Then instead of storing the value unlet the item.
6903 // unlet {list}[idx]
6904 // unlet {dict}[key] dict.key
6905 //
6906 // Figure out the LHS type and other properties.
6907 //
6908 ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, 0, cctx);
6909
6910 // : unlet an indexed item
6911 if (!lhs.lhs_has_index)
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01006912 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006913 iemsg("called compile_lhs() without an index");
6914 ret = FAIL;
6915 }
6916 else
6917 {
6918 // Use the info in "lhs" to unlet the item at the index in the
6919 // list or dict.
6920 ret = compile_assign_unlet(p, &lhs, FALSE, &t_void, cctx);
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01006921 }
6922
Bram Moolenaar752fc692021-01-04 21:57:11 +01006923 vim_free(lhs.lhs_name);
6924 }
6925 else if (check_vim9_unlet(p) == FAIL)
6926 {
6927 ret = FAIL;
6928 }
6929 else
6930 {
6931 // Normal name. Only supports g:, w:, t: and b: namespaces.
6932 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006933 }
6934
Bram Moolenaar752fc692021-01-04 21:57:11 +01006935 *name_end = cc;
6936 return ret;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006937}
6938
6939/*
Bram Moolenaarb2cb6c82021-03-28 20:38:34 +02006940 * Callback passed to ex_unletlock().
6941 */
6942 static int
6943compile_lock_unlock(
6944 lval_T *lvp,
6945 char_u *name_end,
6946 exarg_T *eap,
6947 int deep UNUSED,
6948 void *coookie)
6949{
6950 cctx_T *cctx = coookie;
6951 int cc = *name_end;
6952 char_u *p = lvp->ll_name;
6953 int ret = OK;
6954 size_t len;
6955 char_u *buf;
6956
6957 if (cctx->ctx_skip == SKIP_YES)
6958 return OK;
6959
6960 // Cannot use :lockvar and :unlockvar on local variables.
6961 if (p[1] != ':')
6962 {
6963 char_u *end = skip_var_one(p, FALSE);
6964
6965 if (lookup_local(p, end - p, NULL, cctx) == OK)
6966 {
6967 emsg(_(e_cannot_lock_unlock_local_variable));
6968 return FAIL;
6969 }
6970 }
6971
6972 // Checking is done at runtime.
6973 *name_end = NUL;
6974 len = name_end - p + 20;
6975 buf = alloc(len);
6976 if (buf == NULL)
6977 ret = FAIL;
6978 else
6979 {
6980 vim_snprintf((char *)buf, len, "%s %s",
6981 eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
6982 p);
6983 ret = generate_EXEC(cctx, buf);
6984
6985 vim_free(buf);
6986 *name_end = cc;
6987 }
6988 return ret;
6989}
6990
6991/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006992 * compile "unlet var", "lock var" and "unlock var"
6993 * "arg" points to "var".
6994 */
6995 static char_u *
6996compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
6997{
Bram Moolenaarb2cb6c82021-03-28 20:38:34 +02006998 ex_unletlock(eap, arg, 0, GLV_NO_AUTOLOAD | GLV_COMPILING,
6999 eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
7000 cctx);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007001 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
7002}
7003
7004/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007005 * Compile an :import command.
7006 */
7007 static char_u *
7008compile_import(char_u *arg, cctx_T *cctx)
7009{
Bram Moolenaar1c991142020-07-04 13:15:31 +02007010 return handle_import(arg, &cctx->ctx_imports, 0, NULL, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007011}
7012
7013/*
7014 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
7015 */
7016 static int
7017compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
7018{
7019 garray_T *instr = &cctx->ctx_instr;
7020 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
7021
7022 if (endlabel == NULL)
7023 return FAIL;
7024 endlabel->el_next = *el;
7025 *el = endlabel;
7026 endlabel->el_end_label = instr->ga_len;
7027
7028 generate_JUMP(cctx, when, 0);
7029 return OK;
7030}
7031
7032 static void
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007033compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007034{
7035 garray_T *instr = &cctx->ctx_instr;
7036
7037 while (*el != NULL)
7038 {
7039 endlabel_T *cur = (*el);
7040 isn_T *isn;
7041
7042 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007043 isn->isn_arg.jump.jump_where = jump_where;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007044 *el = cur->el_next;
7045 vim_free(cur);
7046 }
7047}
7048
Bram Moolenaar3cca2992020-04-02 22:57:36 +02007049 static void
7050compile_free_jump_to_end(endlabel_T **el)
7051{
7052 while (*el != NULL)
7053 {
7054 endlabel_T *cur = (*el);
7055
7056 *el = cur->el_next;
7057 vim_free(cur);
7058 }
7059}
7060
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007061/*
7062 * Create a new scope and set up the generic items.
7063 */
7064 static scope_T *
7065new_scope(cctx_T *cctx, scopetype_T type)
7066{
7067 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
7068
7069 if (scope == NULL)
7070 return NULL;
7071 scope->se_outer = cctx->ctx_scope;
7072 cctx->ctx_scope = scope;
7073 scope->se_type = type;
7074 scope->se_local_count = cctx->ctx_locals.ga_len;
7075 return scope;
7076}
7077
7078/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007079 * Free the current scope and go back to the outer scope.
7080 */
7081 static void
7082drop_scope(cctx_T *cctx)
7083{
7084 scope_T *scope = cctx->ctx_scope;
7085
7086 if (scope == NULL)
7087 {
7088 iemsg("calling drop_scope() without a scope");
7089 return;
7090 }
7091 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02007092 switch (scope->se_type)
7093 {
7094 case IF_SCOPE:
7095 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
7096 case FOR_SCOPE:
7097 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
7098 case WHILE_SCOPE:
7099 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
7100 case TRY_SCOPE:
7101 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
7102 case NO_SCOPE:
7103 case BLOCK_SCOPE:
7104 break;
7105 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007106 vim_free(scope);
7107}
7108
7109/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007110 * compile "if expr"
7111 *
7112 * "if expr" Produces instructions:
7113 * EVAL expr Push result of "expr"
7114 * JUMP_IF_FALSE end
7115 * ... body ...
7116 * end:
7117 *
7118 * "if expr | else" Produces instructions:
7119 * EVAL expr Push result of "expr"
7120 * JUMP_IF_FALSE else
7121 * ... body ...
7122 * JUMP_ALWAYS end
7123 * else:
7124 * ... body ...
7125 * end:
7126 *
7127 * "if expr1 | elseif expr2 | else" Produces instructions:
7128 * EVAL expr Push result of "expr"
7129 * JUMP_IF_FALSE elseif
7130 * ... body ...
7131 * JUMP_ALWAYS end
7132 * elseif:
7133 * EVAL expr Push result of "expr"
7134 * JUMP_IF_FALSE else
7135 * ... body ...
7136 * JUMP_ALWAYS end
7137 * else:
7138 * ... body ...
7139 * end:
7140 */
7141 static char_u *
7142compile_if(char_u *arg, cctx_T *cctx)
7143{
7144 char_u *p = arg;
7145 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007146 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007147 scope_T *scope;
Bram Moolenaarefd88552020-06-18 20:50:10 +02007148 skip_T skip_save = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007149 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007150
Bram Moolenaara5565e42020-05-09 15:44:01 +02007151 CLEAR_FIELD(ppconst);
7152 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007153 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02007154 clear_ppconst(&ppconst);
7155 return NULL;
7156 }
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01007157 if (!ends_excmd2(arg, skipwhite(p)))
7158 {
7159 semsg(_(e_trailing_arg), p);
7160 return NULL;
7161 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02007162 if (cctx->ctx_skip == SKIP_YES)
7163 clear_ppconst(&ppconst);
7164 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaara5565e42020-05-09 15:44:01 +02007165 {
Bram Moolenaar13106602020-10-04 16:06:05 +02007166 int error = FALSE;
7167 int v;
7168
Bram Moolenaara5565e42020-05-09 15:44:01 +02007169 // The expression results in a constant.
Bram Moolenaar13106602020-10-04 16:06:05 +02007170 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
Bram Moolenaardda749c2020-10-04 17:24:29 +02007171 clear_ppconst(&ppconst);
Bram Moolenaar13106602020-10-04 16:06:05 +02007172 if (error)
7173 return NULL;
7174 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007175 }
7176 else
7177 {
7178 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007179 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007180 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007181 return NULL;
Bram Moolenaar13106602020-10-04 16:06:05 +02007182 if (bool_on_stack(cctx) == FAIL)
7183 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007184 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007185
Bram Moolenaara91a7132021-03-25 21:12:15 +01007186 // CMDMOD_REV must come before the jump
7187 generate_undo_cmdmods(cctx);
7188
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007189 scope = new_scope(cctx, IF_SCOPE);
7190 if (scope == NULL)
7191 return NULL;
Bram Moolenaarefd88552020-06-18 20:50:10 +02007192 scope->se_skip_save = skip_save;
7193 // "is_had_return" will be reset if any block does not end in :return
7194 scope->se_u.se_if.is_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007195
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007196 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007197 {
7198 // "where" is set when ":elseif", "else" or ":endif" is found
7199 scope->se_u.se_if.is_if_label = instr->ga_len;
7200 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
7201 }
7202 else
7203 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007204
Bram Moolenaarced68a02021-01-24 17:53:47 +01007205#ifdef FEAT_PROFILE
7206 if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES
7207 && skip_save != SKIP_YES)
7208 {
7209 // generated a profile start, need to generate a profile end, since it
7210 // won't be done after returning
7211 cctx->ctx_skip = SKIP_NOT;
7212 generate_instr(cctx, ISN_PROF_END);
7213 cctx->ctx_skip = SKIP_YES;
7214 }
7215#endif
7216
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007217 return p;
7218}
7219
7220 static char_u *
7221compile_elseif(char_u *arg, cctx_T *cctx)
7222{
7223 char_u *p = arg;
7224 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02007225 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007226 isn_T *isn;
7227 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02007228 ppconst_T ppconst;
Bram Moolenaar749639e2020-08-27 23:08:47 +02007229 skip_T save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007230
7231 if (scope == NULL || scope->se_type != IF_SCOPE)
7232 {
7233 emsg(_(e_elseif_without_if));
7234 return NULL;
7235 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01007236 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007237 if (!cctx->ctx_had_return)
7238 scope->se_u.se_if.is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007239
Bram Moolenaarced68a02021-01-24 17:53:47 +01007240 if (cctx->ctx_skip == SKIP_NOT)
7241 {
7242 // previous block was executed, this one and following will not
7243 cctx->ctx_skip = SKIP_YES;
7244 scope->se_u.se_if.is_seen_skip_not = TRUE;
7245 }
7246 if (scope->se_u.se_if.is_seen_skip_not)
7247 {
7248 // A previous block was executed, skip over expression and bail out.
Bram Moolenaara91a7132021-03-25 21:12:15 +01007249 // Do not count the "elseif" for profiling and cmdmod
7250 instr->ga_len = current_instr_idx(cctx);
7251
Bram Moolenaarced68a02021-01-24 17:53:47 +01007252 skip_expr_cctx(&p, cctx);
7253 return p;
7254 }
7255
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007256 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007257 {
Bram Moolenaara91a7132021-03-25 21:12:15 +01007258 int moved_cmdmod = FALSE;
7259
7260 // Move any CMDMOD instruction to after the jump
7261 if (((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD)
7262 {
7263 if (ga_grow(instr, 1) == FAIL)
7264 return NULL;
7265 ((isn_T *)instr->ga_data)[instr->ga_len] =
7266 ((isn_T *)instr->ga_data)[instr->ga_len - 1];
7267 --instr->ga_len;
7268 moved_cmdmod = TRUE;
7269 }
7270
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007271 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007272 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007273 return NULL;
7274 // previous "if" or "elseif" jumps here
7275 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
7276 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaara91a7132021-03-25 21:12:15 +01007277 if (moved_cmdmod)
7278 ++instr->ga_len;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007279 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007280
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007281 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02007282 CLEAR_FIELD(ppconst);
Bram Moolenaar749639e2020-08-27 23:08:47 +02007283 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarced68a02021-01-24 17:53:47 +01007284 {
Bram Moolenaar749639e2020-08-27 23:08:47 +02007285 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaarced68a02021-01-24 17:53:47 +01007286#ifdef FEAT_PROFILE
7287 if (cctx->ctx_profiling)
7288 {
7289 // the previous block was skipped, need to profile this line
7290 generate_instr(cctx, ISN_PROF_START);
7291 instr_count = instr->ga_len;
7292 }
7293#endif
7294 }
Bram Moolenaar7f141552020-05-09 17:35:53 +02007295 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007296 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02007297 clear_ppconst(&ppconst);
7298 return NULL;
7299 }
Bram Moolenaar749639e2020-08-27 23:08:47 +02007300 cctx->ctx_skip = save_skip;
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01007301 if (!ends_excmd2(arg, skipwhite(p)))
7302 {
7303 semsg(_(e_trailing_arg), p);
7304 return NULL;
7305 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02007306 if (scope->se_skip_save == SKIP_YES)
7307 clear_ppconst(&ppconst);
7308 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaar7f141552020-05-09 17:35:53 +02007309 {
Bram Moolenaar13106602020-10-04 16:06:05 +02007310 int error = FALSE;
7311 int v;
7312
Bram Moolenaar7f141552020-05-09 17:35:53 +02007313 // The expression results in a constant.
7314 // TODO: how about nesting?
Bram Moolenaar13106602020-10-04 16:06:05 +02007315 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
7316 if (error)
7317 return NULL;
7318 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
Bram Moolenaar7f141552020-05-09 17:35:53 +02007319 clear_ppconst(&ppconst);
7320 scope->se_u.se_if.is_if_label = -1;
7321 }
7322 else
7323 {
7324 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007325 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaar7f141552020-05-09 17:35:53 +02007326 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007327 return NULL;
Bram Moolenaar13106602020-10-04 16:06:05 +02007328 if (bool_on_stack(cctx) == FAIL)
7329 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007330
Bram Moolenaara91a7132021-03-25 21:12:15 +01007331 // CMDMOD_REV must come before the jump
7332 generate_undo_cmdmods(cctx);
7333
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007334 // "where" is set when ":elseif", "else" or ":endif" is found
7335 scope->se_u.se_if.is_if_label = instr->ga_len;
7336 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
7337 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007338
7339 return p;
7340}
7341
7342 static char_u *
7343compile_else(char_u *arg, cctx_T *cctx)
7344{
7345 char_u *p = arg;
7346 garray_T *instr = &cctx->ctx_instr;
7347 isn_T *isn;
7348 scope_T *scope = cctx->ctx_scope;
7349
7350 if (scope == NULL || scope->se_type != IF_SCOPE)
7351 {
7352 emsg(_(e_else_without_if));
7353 return NULL;
7354 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01007355 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007356 if (!cctx->ctx_had_return)
7357 scope->se_u.se_if.is_had_return = FALSE;
7358 scope->se_u.se_if.is_seen_else = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007359
Bram Moolenaarced68a02021-01-24 17:53:47 +01007360#ifdef FEAT_PROFILE
7361 if (cctx->ctx_profiling)
7362 {
7363 if (cctx->ctx_skip == SKIP_NOT
7364 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
7365 .isn_type == ISN_PROF_START)
7366 // the previous block was executed, do not count "else" for profiling
7367 --instr->ga_len;
7368 if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
7369 {
7370 // the previous block was not executed, this one will, do count the
7371 // "else" for profiling
7372 cctx->ctx_skip = SKIP_NOT;
7373 generate_instr(cctx, ISN_PROF_END);
7374 generate_instr(cctx, ISN_PROF_START);
7375 cctx->ctx_skip = SKIP_YES;
7376 }
7377 }
7378#endif
7379
7380 if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007381 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02007382 // jump from previous block to the end, unless the else block is empty
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007383 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007384 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02007385 if (!cctx->ctx_had_return
7386 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
7387 JUMP_ALWAYS, cctx) == FAIL)
7388 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007389 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007390
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007391 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02007392 {
7393 if (scope->se_u.se_if.is_if_label >= 0)
7394 {
7395 // previous "if" or "elseif" jumps here
7396 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
7397 isn->isn_arg.jump.jump_where = instr->ga_len;
7398 scope->se_u.se_if.is_if_label = -1;
7399 }
7400 }
7401
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007402 if (cctx->ctx_skip != SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02007403 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
7404 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007405
7406 return p;
7407}
7408
7409 static char_u *
7410compile_endif(char_u *arg, cctx_T *cctx)
7411{
7412 scope_T *scope = cctx->ctx_scope;
7413 ifscope_T *ifscope;
7414 garray_T *instr = &cctx->ctx_instr;
7415 isn_T *isn;
7416
Bram Moolenaarfa984412021-03-25 22:15:28 +01007417 if (misplaced_cmdmod(cctx))
7418 return NULL;
7419
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007420 if (scope == NULL || scope->se_type != IF_SCOPE)
7421 {
7422 emsg(_(e_endif_without_if));
7423 return NULL;
7424 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007425 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007426 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007427 if (!cctx->ctx_had_return)
7428 ifscope->is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007429
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007430 if (scope->se_u.se_if.is_if_label >= 0)
7431 {
7432 // previous "if" or "elseif" jumps here
7433 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
7434 isn->isn_arg.jump.jump_where = instr->ga_len;
7435 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007436 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007437 compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx);
Bram Moolenaarced68a02021-01-24 17:53:47 +01007438
7439#ifdef FEAT_PROFILE
7440 // even when skipping we count the endif as executed, unless the block it's
7441 // in is skipped
7442 if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES
7443 && scope->se_skip_save != SKIP_YES)
7444 {
7445 cctx->ctx_skip = SKIP_NOT;
7446 generate_instr(cctx, ISN_PROF_START);
7447 }
7448#endif
Bram Moolenaarefd88552020-06-18 20:50:10 +02007449 cctx->ctx_skip = scope->se_skip_save;
7450
7451 // If all the blocks end in :return and there is an :else then the
7452 // had_return flag is set.
7453 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007454
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007455 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007456 return arg;
7457}
7458
7459/*
Bram Moolenaar792f7862020-11-23 08:31:18 +01007460 * Compile "for var in expr":
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007461 *
7462 * Produces instructions:
7463 * PUSHNR -1
7464 * STORE loop-idx Set index to -1
Bram Moolenaar792f7862020-11-23 08:31:18 +01007465 * EVAL expr result of "expr" on top of stack
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007466 * top: FOR loop-idx, end Increment index, use list on bottom of stack
7467 * - if beyond end, jump to "end"
7468 * - otherwise get item from list and push it
7469 * STORE var Store item in "var"
7470 * ... body ...
7471 * JUMP top Jump back to repeat
7472 * end: DROP Drop the result of "expr"
7473 *
Bram Moolenaar792f7862020-11-23 08:31:18 +01007474 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
7475 * UNPACK 2 Split item in 2
7476 * STORE var1 Store item in "var1"
7477 * STORE var2 Store item in "var2"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007478 */
7479 static char_u *
Bram Moolenaar792f7862020-11-23 08:31:18 +01007480compile_for(char_u *arg_start, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007481{
Bram Moolenaar792f7862020-11-23 08:31:18 +01007482 char_u *arg;
7483 char_u *arg_end;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007484 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007485 char_u *p;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007486 char_u *wp;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007487 int var_count = 0;
7488 int semicolon = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007489 size_t varlen;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007490 garray_T *stack = &cctx->ctx_type_stack;
7491 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007492 lvar_T *loop_lvar; // loop iteration variable
7493 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007494 type_T *vartype;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007495 type_T *item_type = &t_any;
7496 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007497
Bram Moolenaar792f7862020-11-23 08:31:18 +01007498 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
Bram Moolenaar036d0712021-01-17 20:23:38 +01007499 if (p == NULL)
7500 return NULL;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007501 if (var_count == 0)
7502 var_count = 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007503
7504 // consume "in"
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007505 wp = p;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007506 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
7507 return NULL;
7508 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007509 {
7510 emsg(_(e_missing_in));
7511 return NULL;
7512 }
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007513 wp = p + 2;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007514 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
7515 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007516
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007517 scope = new_scope(cctx, FOR_SCOPE);
7518 if (scope == NULL)
7519 return NULL;
7520
Bram Moolenaar792f7862020-11-23 08:31:18 +01007521 // Reserve a variable to store the loop iteration counter and initialize it
7522 // to -1.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007523 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
7524 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007525 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007526 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007527 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007528 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007529 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007530 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007531
7532 // compile "expr", it remains on the stack until "endfor"
7533 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007534 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007535 {
7536 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007537 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007538 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007539 arg_end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007540
Bram Moolenaard551d6c2021-04-18 13:15:58 +02007541 // If we know the type of "var" and it is a not a supported type we can
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01007542 // give an error now.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007543 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01007544 if (vartype->tt_type != VAR_LIST && vartype->tt_type != VAR_STRING
Bram Moolenaard551d6c2021-04-18 13:15:58 +02007545 && vartype->tt_type != VAR_BLOB && vartype->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007546 {
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01007547 semsg(_(e_for_loop_on_str_not_supported),
7548 vartype_name(vartype->tt_type));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007549 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007550 return NULL;
7551 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007552
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007553 if (vartype->tt_type == VAR_STRING)
7554 item_type = &t_string;
Bram Moolenaard551d6c2021-04-18 13:15:58 +02007555 else if (vartype->tt_type == VAR_BLOB)
7556 item_type = &t_number;
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007557 else if (vartype->tt_type == VAR_LIST
7558 && vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar792f7862020-11-23 08:31:18 +01007559 {
7560 if (var_count == 1)
7561 item_type = vartype->tt_member;
7562 else if (vartype->tt_member->tt_type == VAR_LIST
7563 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
Bram Moolenaard551d6c2021-04-18 13:15:58 +02007564 // TODO: should get the type for each lhs
Bram Moolenaar792f7862020-11-23 08:31:18 +01007565 item_type = vartype->tt_member->tt_member;
7566 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007567
Bram Moolenaara91a7132021-03-25 21:12:15 +01007568 // CMDMOD_REV must come before the FOR instruction
7569 generate_undo_cmdmods(cctx);
7570
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007571 // "for_end" is set when ":endfor" is found
Bram Moolenaara91a7132021-03-25 21:12:15 +01007572 scope->se_u.se_for.fs_top_label = current_instr_idx(cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007573 generate_FOR(cctx, loop_lvar->lv_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007574
Bram Moolenaar792f7862020-11-23 08:31:18 +01007575 arg = arg_start;
7576 if (var_count > 1)
7577 {
7578 generate_UNPACK(cctx, var_count, semicolon);
7579 arg = skipwhite(arg + 1); // skip white after '['
7580
7581 // the list item is replaced by a number of items
7582 if (ga_grow(stack, var_count - 1) == FAIL)
7583 {
7584 drop_scope(cctx);
7585 return NULL;
7586 }
7587 --stack->ga_len;
7588 for (idx = 0; idx < var_count; ++idx)
7589 {
7590 ((type_T **)stack->ga_data)[stack->ga_len] =
7591 (semicolon && idx == 0) ? vartype : item_type;
7592 ++stack->ga_len;
7593 }
7594 }
7595
7596 for (idx = 0; idx < var_count; ++idx)
7597 {
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007598 assign_dest_T dest = dest_local;
7599 int opt_flags = 0;
7600 int vimvaridx = -1;
7601 type_T *type = &t_any;
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007602 type_T *lhs_type = &t_any;
7603 where_T where;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007604
7605 p = skip_var_one(arg, FALSE);
Bram Moolenaar792f7862020-11-23 08:31:18 +01007606 varlen = p - arg;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007607 name = vim_strnsave(arg, varlen);
7608 if (name == NULL)
7609 goto failed;
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007610 if (*p == ':')
7611 {
7612 p = skipwhite(p + 1);
7613 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
7614 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007615
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007616 // TODO: script var not supported?
7617 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
7618 &vimvaridx, &type, cctx) == FAIL)
7619 goto failed;
7620 if (dest != dest_local)
Bram Moolenaar792f7862020-11-23 08:31:18 +01007621 {
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007622 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
7623 0, 0, type, name) == FAIL)
7624 goto failed;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007625 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007626 else
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007627 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01007628 if (lookup_local(arg, varlen, NULL, cctx) == OK)
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007629 {
7630 semsg(_(e_variable_already_declared), arg);
7631 goto failed;
7632 }
7633
Bram Moolenaarea870692020-12-02 14:24:30 +01007634 if (STRNCMP(name, "s:", 2) == 0)
7635 {
7636 semsg(_(e_cannot_declare_script_variable_in_function), name);
7637 goto failed;
7638 }
7639
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007640 // Reserve a variable to store "var".
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007641 where.wt_index = var_count > 1 ? idx + 1 : 0;
7642 where.wt_variable = TRUE;
7643 if (lhs_type == &t_any)
7644 lhs_type = item_type;
7645 else if (item_type != &t_unknown
7646 && !(var_count > 1 && item_type == &t_any)
7647 && check_type(lhs_type, item_type, TRUE, where) == FAIL)
7648 goto failed;
7649 var_lvar = reserve_local(cctx, arg, varlen, TRUE, lhs_type);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007650 if (var_lvar == NULL)
7651 // out of memory or used as an argument
7652 goto failed;
7653
7654 if (semicolon && idx == var_count - 1)
7655 var_lvar->lv_type = vartype;
7656 else
7657 var_lvar->lv_type = item_type;
7658 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
7659 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007660
7661 if (*p == ',' || *p == ';')
7662 ++p;
7663 arg = skipwhite(p);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007664 vim_free(name);
Bram Moolenaar792f7862020-11-23 08:31:18 +01007665 }
7666
7667 return arg_end;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007668
7669failed:
7670 vim_free(name);
7671 drop_scope(cctx);
7672 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007673}
7674
7675/*
7676 * compile "endfor"
7677 */
7678 static char_u *
7679compile_endfor(char_u *arg, cctx_T *cctx)
7680{
7681 garray_T *instr = &cctx->ctx_instr;
7682 scope_T *scope = cctx->ctx_scope;
7683 forscope_T *forscope;
7684 isn_T *isn;
7685
Bram Moolenaarfa984412021-03-25 22:15:28 +01007686 if (misplaced_cmdmod(cctx))
7687 return NULL;
Bram Moolenaara91a7132021-03-25 21:12:15 +01007688
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007689 if (scope == NULL || scope->se_type != FOR_SCOPE)
7690 {
7691 emsg(_(e_for));
7692 return NULL;
7693 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007694 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007695 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007696 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007697
7698 // At end of ":for" scope jump back to the FOR instruction.
7699 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
7700
7701 // Fill in the "end" label in the FOR statement so it can jump here
7702 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
7703 isn->isn_arg.forloop.for_end = instr->ga_len;
7704
7705 // Fill in the "end" label any BREAK statements
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007706 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007707
7708 // Below the ":for" scope drop the "expr" list from the stack.
7709 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
7710 return NULL;
7711
7712 vim_free(scope);
7713
7714 return arg;
7715}
7716
7717/*
7718 * compile "while expr"
7719 *
7720 * Produces instructions:
7721 * top: EVAL expr Push result of "expr"
7722 * JUMP_IF_FALSE end jump if false
7723 * ... body ...
7724 * JUMP top Jump back to repeat
7725 * end:
7726 *
7727 */
7728 static char_u *
7729compile_while(char_u *arg, cctx_T *cctx)
7730{
7731 char_u *p = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007732 scope_T *scope;
7733
7734 scope = new_scope(cctx, WHILE_SCOPE);
7735 if (scope == NULL)
7736 return NULL;
7737
Bram Moolenaara91a7132021-03-25 21:12:15 +01007738 // "endwhile" jumps back here, one before when profiling or using cmdmods
7739 scope->se_u.se_while.ws_top_label = current_instr_idx(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007740
7741 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02007742 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007743 return NULL;
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01007744 if (!ends_excmd2(arg, skipwhite(p)))
7745 {
7746 semsg(_(e_trailing_arg), p);
7747 return NULL;
7748 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007749
Bram Moolenaar13106602020-10-04 16:06:05 +02007750 if (bool_on_stack(cctx) == FAIL)
7751 return FAIL;
7752
Bram Moolenaara91a7132021-03-25 21:12:15 +01007753 // CMDMOD_REV must come before the jump
7754 generate_undo_cmdmods(cctx);
7755
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007756 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007757 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007758 JUMP_IF_FALSE, cctx) == FAIL)
7759 return FAIL;
7760
7761 return p;
7762}
7763
7764/*
7765 * compile "endwhile"
7766 */
7767 static char_u *
7768compile_endwhile(char_u *arg, cctx_T *cctx)
7769{
7770 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007771 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007772
Bram Moolenaarfa984412021-03-25 22:15:28 +01007773 if (misplaced_cmdmod(cctx))
7774 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007775 if (scope == NULL || scope->se_type != WHILE_SCOPE)
7776 {
7777 emsg(_(e_while));
7778 return NULL;
7779 }
7780 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007781 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007782
Bram Moolenaarf002a412021-01-24 13:34:18 +01007783#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01007784 // count the endwhile before jumping
7785 may_generate_prof_end(cctx, cctx->ctx_lnum);
Bram Moolenaarf002a412021-01-24 13:34:18 +01007786#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01007787
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007788 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007789 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007790
7791 // Fill in the "end" label in the WHILE statement so it can jump here.
7792 // And in any jumps for ":break"
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007793 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
7794 instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007795
7796 vim_free(scope);
7797
7798 return arg;
7799}
7800
7801/*
7802 * compile "continue"
7803 */
7804 static char_u *
7805compile_continue(char_u *arg, cctx_T *cctx)
7806{
7807 scope_T *scope = cctx->ctx_scope;
Bram Moolenaarc150c092021-02-13 15:02:46 +01007808 int try_scopes = 0;
7809 int loop_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007810
7811 for (;;)
7812 {
7813 if (scope == NULL)
7814 {
7815 emsg(_(e_continue));
7816 return NULL;
7817 }
Bram Moolenaarc150c092021-02-13 15:02:46 +01007818 if (scope->se_type == FOR_SCOPE)
7819 {
7820 loop_label = scope->se_u.se_for.fs_top_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007821 break;
Bram Moolenaarc150c092021-02-13 15:02:46 +01007822 }
7823 if (scope->se_type == WHILE_SCOPE)
7824 {
7825 loop_label = scope->se_u.se_while.ws_top_label;
7826 break;
7827 }
7828 if (scope->se_type == TRY_SCOPE)
7829 ++try_scopes;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007830 scope = scope->se_outer;
7831 }
7832
Bram Moolenaarc150c092021-02-13 15:02:46 +01007833 if (try_scopes > 0)
7834 // Inside one or more try/catch blocks we first need to jump to the
7835 // "finally" or "endtry" to cleanup.
7836 generate_TRYCONT(cctx, try_scopes, loop_label);
7837 else
7838 // Jump back to the FOR or WHILE instruction.
7839 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
7840
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007841 return arg;
7842}
7843
7844/*
7845 * compile "break"
7846 */
7847 static char_u *
7848compile_break(char_u *arg, cctx_T *cctx)
7849{
7850 scope_T *scope = cctx->ctx_scope;
7851 endlabel_T **el;
7852
7853 for (;;)
7854 {
7855 if (scope == NULL)
7856 {
7857 emsg(_(e_break));
7858 return NULL;
7859 }
7860 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
7861 break;
7862 scope = scope->se_outer;
7863 }
7864
7865 // Jump to the end of the FOR or WHILE loop.
7866 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007867 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007868 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007869 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007870 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
7871 return FAIL;
7872
7873 return arg;
7874}
7875
7876/*
7877 * compile "{" start of block
7878 */
7879 static char_u *
7880compile_block(char_u *arg, cctx_T *cctx)
7881{
7882 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
7883 return NULL;
7884 return skipwhite(arg + 1);
7885}
7886
7887/*
7888 * compile end of block: drop one scope
7889 */
7890 static void
7891compile_endblock(cctx_T *cctx)
7892{
7893 scope_T *scope = cctx->ctx_scope;
7894
7895 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007896 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007897 vim_free(scope);
7898}
7899
7900/*
7901 * compile "try"
7902 * Creates a new scope for the try-endtry, pointing to the first catch and
7903 * finally.
7904 * Creates another scope for the "try" block itself.
7905 * TRY instruction sets up exception handling at runtime.
7906 *
7907 * "try"
7908 * TRY -> catch1, -> finally push trystack entry
7909 * ... try block
7910 * "throw {exception}"
7911 * EVAL {exception}
7912 * THROW create exception
7913 * ... try block
7914 * " catch {expr}"
7915 * JUMP -> finally
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01007916 * catch1: PUSH exception
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007917 * EVAL {expr}
7918 * MATCH
7919 * JUMP nomatch -> catch2
7920 * CATCH remove exception
7921 * ... catch block
7922 * " catch"
7923 * JUMP -> finally
7924 * catch2: CATCH remove exception
7925 * ... catch block
7926 * " finally"
7927 * finally:
7928 * ... finally block
7929 * " endtry"
7930 * ENDTRY pop trystack entry, may rethrow
7931 */
7932 static char_u *
7933compile_try(char_u *arg, cctx_T *cctx)
7934{
7935 garray_T *instr = &cctx->ctx_instr;
7936 scope_T *try_scope;
7937 scope_T *scope;
7938
Bram Moolenaarfa984412021-03-25 22:15:28 +01007939 if (misplaced_cmdmod(cctx))
7940 return NULL;
7941
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007942 // scope that holds the jumps that go to catch/finally/endtry
7943 try_scope = new_scope(cctx, TRY_SCOPE);
7944 if (try_scope == NULL)
7945 return NULL;
7946
Bram Moolenaar69f70502021-01-01 16:10:46 +01007947 if (cctx->ctx_skip != SKIP_YES)
7948 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007949 isn_T *isn;
7950
7951 // "try_catch" is set when the first ":catch" is found or when no catch
7952 // is found and ":finally" is found.
7953 // "try_finally" is set when ":finally" is found
7954 // "try_endtry" is set when ":endtry" is found
Bram Moolenaar69f70502021-01-01 16:10:46 +01007955 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007956 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
7957 return NULL;
7958 isn->isn_arg.try.try_ref = ALLOC_CLEAR_ONE(tryref_T);
7959 if (isn->isn_arg.try.try_ref == NULL)
Bram Moolenaar69f70502021-01-01 16:10:46 +01007960 return NULL;
7961 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007962
7963 // scope for the try block itself
7964 scope = new_scope(cctx, BLOCK_SCOPE);
7965 if (scope == NULL)
7966 return NULL;
7967
7968 return arg;
7969}
7970
7971/*
7972 * compile "catch {expr}"
7973 */
7974 static char_u *
7975compile_catch(char_u *arg, cctx_T *cctx UNUSED)
7976{
7977 scope_T *scope = cctx->ctx_scope;
7978 garray_T *instr = &cctx->ctx_instr;
7979 char_u *p;
7980 isn_T *isn;
7981
Bram Moolenaarfa984412021-03-25 22:15:28 +01007982 if (misplaced_cmdmod(cctx))
7983 return NULL;
7984
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007985 // end block scope from :try or :catch
7986 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
7987 compile_endblock(cctx);
7988 scope = cctx->ctx_scope;
7989
7990 // Error if not in a :try scope
7991 if (scope == NULL || scope->se_type != TRY_SCOPE)
7992 {
7993 emsg(_(e_catch));
7994 return NULL;
7995 }
7996
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007997 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007998 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02007999 emsg(_(e_catch_unreachable_after_catch_all));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008000 return NULL;
8001 }
8002
Bram Moolenaar69f70502021-01-01 16:10:46 +01008003 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008004 {
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008005#ifdef FEAT_PROFILE
8006 // the profile-start should be after the jump
8007 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
8008 .isn_type == ISN_PROF_START)
8009 --instr->ga_len;
8010#endif
Bram Moolenaar69f70502021-01-01 16:10:46 +01008011 // Jump from end of previous block to :finally or :endtry
8012 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
8013 JUMP_ALWAYS, cctx) == FAIL)
8014 return NULL;
8015
8016 // End :try or :catch scope: set value in ISN_TRY instruction
8017 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008018 if (isn->isn_arg.try.try_ref->try_catch == 0)
8019 isn->isn_arg.try.try_ref->try_catch = instr->ga_len;
Bram Moolenaar69f70502021-01-01 16:10:46 +01008020 if (scope->se_u.se_try.ts_catch_label != 0)
8021 {
8022 // Previous catch without match jumps here
8023 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
8024 isn->isn_arg.jump.jump_where = instr->ga_len;
8025 }
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008026#ifdef FEAT_PROFILE
8027 if (cctx->ctx_profiling)
8028 {
8029 // a "throw" that jumps here needs to be counted
8030 generate_instr(cctx, ISN_PROF_END);
8031 // the "catch" is also counted
8032 generate_instr(cctx, ISN_PROF_START);
8033 }
8034#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008035 }
8036
8037 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02008038 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008039 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008040 scope->se_u.se_try.ts_caught_all = TRUE;
8041 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008042 }
8043 else
8044 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008045 char_u *end;
8046 char_u *pat;
8047 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02008048 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01008049 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008050
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008051 // Push v:exception, push {expr} and MATCH
8052 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
8053
Bram Moolenaard93a7fc2021-01-04 12:42:13 +01008054 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008055 if (*end != *p)
8056 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02008057 semsg(_(e_separator_mismatch_str), p);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008058 vim_free(tofree);
8059 return FAIL;
8060 }
8061 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01008062 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008063 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02008064 len = (int)(end - tofree);
8065 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008066 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02008067 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008068 if (pat == NULL)
8069 return FAIL;
8070 if (generate_PUSHS(cctx, pat) == FAIL)
8071 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008072
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008073 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
8074 return NULL;
8075
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008076 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008077 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
8078 return NULL;
8079 }
8080
Bram Moolenaar69f70502021-01-01 16:10:46 +01008081 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008082 return NULL;
8083
8084 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
8085 return NULL;
8086 return p;
8087}
8088
8089 static char_u *
8090compile_finally(char_u *arg, cctx_T *cctx)
8091{
8092 scope_T *scope = cctx->ctx_scope;
8093 garray_T *instr = &cctx->ctx_instr;
8094 isn_T *isn;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008095 int this_instr;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008096
Bram Moolenaarfa984412021-03-25 22:15:28 +01008097 if (misplaced_cmdmod(cctx))
8098 return NULL;
8099
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008100 // end block scope from :try or :catch
8101 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
8102 compile_endblock(cctx);
8103 scope = cctx->ctx_scope;
8104
8105 // Error if not in a :try scope
8106 if (scope == NULL || scope->se_type != TRY_SCOPE)
8107 {
8108 emsg(_(e_finally));
8109 return NULL;
8110 }
8111
8112 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008113 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008114 if (isn->isn_arg.try.try_ref->try_finally != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008115 {
8116 emsg(_(e_finally_dup));
8117 return NULL;
8118 }
8119
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008120 this_instr = instr->ga_len;
8121#ifdef FEAT_PROFILE
8122 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
8123 .isn_type == ISN_PROF_START)
8124 // jump to the profile start of the "finally"
8125 --this_instr;
8126#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008127
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008128 // Fill in the "end" label in jumps at the end of the blocks.
8129 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
8130 this_instr, cctx);
8131
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008132 // If there is no :catch then an exception jumps to :finally.
8133 if (isn->isn_arg.try.try_ref->try_catch == 0)
8134 isn->isn_arg.try.try_ref->try_catch = this_instr;
8135 isn->isn_arg.try.try_ref->try_finally = this_instr;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008136 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008137 {
8138 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008139 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008140 isn->isn_arg.jump.jump_where = this_instr;
Bram Moolenaare8593122020-07-18 15:17:02 +02008141 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008142 }
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008143 if (generate_instr(cctx, ISN_FINALLY) == NULL)
8144 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008145
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008146 // TODO: set index in ts_finally_label jumps
8147
8148 return arg;
8149}
8150
8151 static char_u *
8152compile_endtry(char_u *arg, cctx_T *cctx)
8153{
8154 scope_T *scope = cctx->ctx_scope;
8155 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaarc150c092021-02-13 15:02:46 +01008156 isn_T *try_isn;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008157
Bram Moolenaarfa984412021-03-25 22:15:28 +01008158 if (misplaced_cmdmod(cctx))
8159 return NULL;
8160
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008161 // end block scope from :catch or :finally
8162 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
8163 compile_endblock(cctx);
8164 scope = cctx->ctx_scope;
8165
8166 // Error if not in a :try scope
8167 if (scope == NULL || scope->se_type != TRY_SCOPE)
8168 {
8169 if (scope == NULL)
8170 emsg(_(e_no_endtry));
8171 else if (scope->se_type == WHILE_SCOPE)
8172 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01008173 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008174 emsg(_(e_endfor));
8175 else
8176 emsg(_(e_endif));
8177 return NULL;
8178 }
8179
Bram Moolenaarc150c092021-02-13 15:02:46 +01008180 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar69f70502021-01-01 16:10:46 +01008181 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008182 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008183 if (try_isn->isn_arg.try.try_ref->try_catch == 0
8184 && try_isn->isn_arg.try.try_ref->try_finally == 0)
Bram Moolenaar69f70502021-01-01 16:10:46 +01008185 {
8186 emsg(_(e_missing_catch_or_finally));
8187 return NULL;
8188 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008189
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008190#ifdef FEAT_PROFILE
8191 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
8192 .isn_type == ISN_PROF_START)
8193 // move the profile start after "endtry" so that it's not counted when
8194 // the exception is rethrown.
8195 --instr->ga_len;
8196#endif
8197
Bram Moolenaar69f70502021-01-01 16:10:46 +01008198 // Fill in the "end" label in jumps at the end of the blocks, if not
8199 // done by ":finally".
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008200 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
8201 instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008202
Bram Moolenaar69f70502021-01-01 16:10:46 +01008203 if (scope->se_u.se_try.ts_catch_label != 0)
8204 {
8205 // Last catch without match jumps here
Bram Moolenaarc150c092021-02-13 15:02:46 +01008206 isn_T *isn = ((isn_T *)instr->ga_data)
8207 + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar69f70502021-01-01 16:10:46 +01008208 isn->isn_arg.jump.jump_where = instr->ga_len;
8209 }
Bram Moolenaare8593122020-07-18 15:17:02 +02008210 }
8211
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008212 compile_endblock(cctx);
8213
Bram Moolenaar4afa7742021-02-14 16:34:59 +01008214 if (cctx->ctx_skip != SKIP_YES)
8215 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008216 // End :catch or :finally scope: set instruction index in ISN_TRY
8217 // instruction
8218 try_isn->isn_arg.try.try_ref->try_endtry = instr->ga_len;
Bram Moolenaar4afa7742021-02-14 16:34:59 +01008219 if (cctx->ctx_skip != SKIP_YES
8220 && generate_instr(cctx, ISN_ENDTRY) == NULL)
8221 return NULL;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008222#ifdef FEAT_PROFILE
8223 if (cctx->ctx_profiling)
8224 generate_instr(cctx, ISN_PROF_START);
8225#endif
Bram Moolenaar4afa7742021-02-14 16:34:59 +01008226 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008227 return arg;
8228}
8229
8230/*
8231 * compile "throw {expr}"
8232 */
8233 static char_u *
8234compile_throw(char_u *arg, cctx_T *cctx UNUSED)
8235{
8236 char_u *p = skipwhite(arg);
8237
Bram Moolenaara5565e42020-05-09 15:44:01 +02008238 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008239 return NULL;
Bram Moolenaar9e1d9e32021-01-11 20:17:34 +01008240 if (cctx->ctx_skip == SKIP_YES)
8241 return p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008242 if (may_generate_2STRING(-1, cctx) == FAIL)
8243 return NULL;
8244 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
8245 return NULL;
8246
8247 return p;
8248}
8249
8250/*
8251 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02008252 * compile "echomsg expr"
8253 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01008254 * compile "execute expr"
8255 */
8256 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02008257compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01008258{
8259 char_u *p = arg;
Bram Moolenaare4984292020-12-13 14:19:25 +01008260 char_u *prev = arg;
Bram Moolenaarad39c092020-02-26 18:23:43 +01008261 int count = 0;
Bram Moolenaarc70fe462021-04-17 17:59:19 +02008262 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaarad39c092020-02-26 18:23:43 +01008263
8264 for (;;)
8265 {
Bram Moolenaare4984292020-12-13 14:19:25 +01008266 if (ends_excmd2(prev, p))
8267 break;
Bram Moolenaara5565e42020-05-09 15:44:01 +02008268 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01008269 return NULL;
8270 ++count;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02008271 prev = p;
Bram Moolenaarad39c092020-02-26 18:23:43 +01008272 p = skipwhite(p);
Bram Moolenaarad39c092020-02-26 18:23:43 +01008273 }
8274
Bram Moolenaare4984292020-12-13 14:19:25 +01008275 if (count > 0)
8276 {
Bram Moolenaarc70fe462021-04-17 17:59:19 +02008277 long save_lnum = cctx->ctx_lnum;
8278
8279 // Use the line number where the command started.
8280 cctx->ctx_lnum = start_ctx_lnum;
8281
Bram Moolenaare4984292020-12-13 14:19:25 +01008282 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
8283 generate_ECHO(cctx, cmdidx == CMD_echo, count);
8284 else if (cmdidx == CMD_execute)
8285 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
8286 else if (cmdidx == CMD_echomsg)
8287 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
8288 else
8289 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaarc70fe462021-04-17 17:59:19 +02008290
8291 cctx->ctx_lnum = save_lnum;
Bram Moolenaare4984292020-12-13 14:19:25 +01008292 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008293 return p;
8294}
8295
8296/*
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01008297 * If "eap" has a range that is not a constant generate an ISN_RANGE
Bram Moolenaar08597872020-12-10 19:43:40 +01008298 * instruction to compute it and return OK.
8299 * Otherwise return FAIL, the caller must deal with any range.
8300 */
8301 static int
8302compile_variable_range(exarg_T *eap, cctx_T *cctx)
8303{
8304 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
8305 char_u *p = skipdigits(eap->cmd);
8306
8307 if (p == range_end)
8308 return FAIL;
8309 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
8310}
8311
8312/*
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008313 * :put r
8314 * :put ={expr}
8315 */
8316 static char_u *
8317compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
8318{
8319 char_u *line = arg;
8320 linenr_T lnum;
8321 char *errormsg;
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02008322 int above = eap->forceit;
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008323
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008324 eap->regname = *line;
8325
8326 if (eap->regname == '=')
8327 {
8328 char_u *p = line + 1;
8329
8330 if (compile_expr0(&p, cctx) == FAIL)
8331 return NULL;
8332 line = p;
8333 }
8334 else if (eap->regname != NUL)
8335 ++line;
8336
Bram Moolenaar08597872020-12-10 19:43:40 +01008337 if (compile_variable_range(eap, cctx) == OK)
8338 {
8339 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
8340 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008341 else
Bram Moolenaar08597872020-12-10 19:43:40 +01008342 {
8343 // Either no range or a number.
8344 // "errormsg" will not be set because the range is ADDR_LINES.
8345 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
Bram Moolenaar399ea812020-12-15 21:28:57 +01008346 // cannot happen
Bram Moolenaar08597872020-12-10 19:43:40 +01008347 return NULL;
8348 if (eap->addr_count == 0)
8349 lnum = -1;
8350 else
8351 lnum = eap->line2;
8352 if (above)
8353 --lnum;
8354 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008355
8356 generate_PUT(cctx, eap->regname, lnum);
8357 return line;
8358}
8359
8360/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008361 * A command that is not compiled, execute with legacy code.
8362 */
8363 static char_u *
8364compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
8365{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02008366 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02008367 int has_expr = FALSE;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008368 char_u *nextcmd = (char_u *)"";
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008369
Bram Moolenaar9b68c822020-06-18 19:31:08 +02008370 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008371 goto theend;
8372
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02008373 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008374 {
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02008375 long argt = eap->argt;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008376 int usefilter = FALSE;
8377
8378 has_expr = argt & (EX_XFILE | EX_EXPAND);
8379
8380 // If the command can be followed by a bar, find the bar and truncate
8381 // it, so that the following command can be compiled.
8382 // The '|' is overwritten with a NUL, it is put back below.
8383 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
8384 && *eap->arg == '!')
8385 // :w !filter or :r !filter or :r! filter
8386 usefilter = TRUE;
8387 if ((argt & EX_TRLBAR) && !usefilter)
8388 {
Bram Moolenaarb8a92962020-08-20 18:02:47 +02008389 eap->argt = argt;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008390 separate_nextcmd(eap);
8391 if (eap->nextcmd != NULL)
8392 nextcmd = eap->nextcmd;
8393 }
Bram Moolenaara11919f2021-01-02 19:44:56 +01008394 else if (eap->cmdidx == CMD_wincmd)
8395 {
8396 p = eap->arg;
8397 if (*p != NUL)
8398 ++p;
8399 if (*p == 'g' || *p == Ctrl_G)
8400 ++p;
8401 p = skipwhite(p);
8402 if (*p == '|')
8403 {
8404 *p = NUL;
8405 nextcmd = p + 1;
8406 }
8407 }
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008408 }
8409
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02008410 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
8411 {
8412 // expand filename in "syntax include [@group] filename"
8413 has_expr = TRUE;
8414 eap->arg = skipwhite(eap->arg + 7);
8415 if (*eap->arg == '@')
8416 eap->arg = skiptowhite(eap->arg);
8417 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008418
Bram Moolenaar56ce9ea2020-12-25 18:35:29 +01008419 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
8420 && STRLEN(eap->arg) > 4)
8421 {
8422 int delim = *eap->arg;
8423
Bram Moolenaard93a7fc2021-01-04 12:42:13 +01008424 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
Bram Moolenaar56ce9ea2020-12-25 18:35:29 +01008425 if (*p == delim)
8426 {
8427 eap->arg = p + 1;
8428 has_expr = TRUE;
8429 }
8430 }
8431
Bram Moolenaarecac5912021-01-05 19:23:28 +01008432 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
8433 {
8434 // TODO: should only expand when appropriate for the command
8435 eap->arg = skiptowhite(eap->arg);
8436 has_expr = TRUE;
8437 }
8438
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02008439 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008440 {
8441 int count = 0;
8442 char_u *start = skipwhite(line);
8443
8444 // :cmd xxx`=expr1`yyy`=expr2`zzz
8445 // PUSHS ":cmd xxx"
8446 // eval expr1
8447 // PUSHS "yyy"
8448 // eval expr2
8449 // PUSHS "zzz"
8450 // EXECCONCAT 5
8451 for (;;)
8452 {
8453 if (p > start)
8454 {
Bram Moolenaar71ccd032020-06-12 22:59:11 +02008455 generate_PUSHS(cctx, vim_strnsave(start, p - start));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008456 ++count;
8457 }
8458 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02008459 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008460 return NULL;
8461 may_generate_2STRING(-1, cctx);
8462 ++count;
8463 p = skipwhite(p);
8464 if (*p != '`')
8465 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008466 emsg(_(e_missing_backtick));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008467 return NULL;
8468 }
8469 start = p + 1;
8470
8471 p = (char_u *)strstr((char *)start, "`=");
8472 if (p == NULL)
8473 {
8474 if (*skipwhite(start) != NUL)
8475 {
8476 generate_PUSHS(cctx, vim_strsave(start));
8477 ++count;
8478 }
8479 break;
8480 }
8481 }
8482 generate_EXECCONCAT(cctx, count);
8483 }
8484 else
8485 generate_EXEC(cctx, line);
8486
8487theend:
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008488 if (*nextcmd != NUL)
8489 {
8490 // the parser expects a pointer to the bar, put it back
8491 --nextcmd;
8492 *nextcmd = '|';
8493 }
8494
8495 return nextcmd;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008496}
8497
Bram Moolenaar8238f082021-04-20 21:10:48 +02008498
8499 static void
8500clear_instr_ga(garray_T *gap)
8501{
8502 int idx;
8503
8504 for (idx = 0; idx < gap->ga_len; ++idx)
8505 delete_instr(((isn_T *)gap->ga_data) + idx);
8506 ga_clear(gap);
8507}
8508
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008509/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02008510 * :s/pat/repl/
8511 */
8512 static char_u *
8513compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
8514{
8515 char_u *cmd = eap->arg;
8516 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
8517
8518 if (expr != NULL)
8519 {
8520 int delimiter = *cmd++;
8521
8522 // There is a \=expr, find it in the substitute part.
Bram Moolenaar8238f082021-04-20 21:10:48 +02008523 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
Bram Moolenaar4c137212021-04-19 16:48:48 +02008524 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
8525 {
Bram Moolenaar8238f082021-04-20 21:10:48 +02008526 garray_T save_ga = cctx->ctx_instr;
8527 char_u *end;
8528 int trailing_error;
8529 int instr_count;
8530 isn_T *instr = NULL;
8531 isn_T *isn;
Bram Moolenaar4c137212021-04-19 16:48:48 +02008532
8533 cmd += 3;
8534 end = skip_substitute(cmd, delimiter);
8535
Bram Moolenaar8238f082021-04-20 21:10:48 +02008536 // Temporarily reset the list of instructions so that the jumps
8537 // labels are correct.
8538 cctx->ctx_instr.ga_len = 0;
8539 cctx->ctx_instr.ga_maxlen = 0;
8540 cctx->ctx_instr.ga_data = NULL;
Bram Moolenaar4c137212021-04-19 16:48:48 +02008541 compile_expr0(&cmd, cctx);
8542 if (end[-1] == NUL)
8543 end[-1] = delimiter;
8544 cmd = skipwhite(cmd);
Bram Moolenaar8238f082021-04-20 21:10:48 +02008545 trailing_error = *cmd != delimiter && *cmd != NUL;
8546
8547 instr_count = cctx->ctx_instr.ga_len;
8548 instr = ALLOC_MULT(isn_T, instr_count + 1);
8549 if (trailing_error || instr == NULL)
Bram Moolenaar4c137212021-04-19 16:48:48 +02008550 {
Bram Moolenaar8238f082021-04-20 21:10:48 +02008551 if (trailing_error)
8552 semsg(_(e_trailing_arg), cmd);
8553 clear_instr_ga(&cctx->ctx_instr);
8554 cctx->ctx_instr = save_ga;
8555 vim_free(instr);
Bram Moolenaar4c137212021-04-19 16:48:48 +02008556 return NULL;
8557 }
8558
Bram Moolenaar8238f082021-04-20 21:10:48 +02008559 // Move the generated instructions into the ISN_SUBSTITUTE
8560 // instructions, then restore the list of instructions before
8561 // adding the ISN_SUBSTITUTE instruction.
8562 mch_memmove(instr, cctx->ctx_instr.ga_data,
8563 instr_count * sizeof(isn_T));
8564 instr[instr_count].isn_type = ISN_FINISH;
8565
8566 cctx->ctx_instr = save_ga;
8567 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
8568 {
8569 int idx;
8570
8571 for (idx = 0; idx < instr_count; ++idx)
8572 delete_instr(instr + idx);
8573 vim_free(instr);
Bram Moolenaar4c137212021-04-19 16:48:48 +02008574 return NULL;
Bram Moolenaar8238f082021-04-20 21:10:48 +02008575 }
8576 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
8577 isn->isn_arg.subs.subs_instr = instr;
Bram Moolenaar4c137212021-04-19 16:48:48 +02008578
8579 // skip over flags
8580 if (*end == '&')
8581 ++end;
8582 while (ASCII_ISALPHA(*end) || *end == '#')
8583 ++end;
8584 return end;
8585 }
8586 }
8587
8588 return compile_exec(arg, eap, cctx);
8589}
8590
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02008591 static char_u *
8592compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
8593{
8594 char_u *arg = eap->arg;
8595
8596 if (cctx->ctx_redir_lhs.lhs_name != NULL)
8597 {
8598 if (STRNCMP(arg, "END", 3) == 0)
8599 {
8600 if (cctx->ctx_redir_lhs.lhs_append)
8601 {
8602 if (compile_load_lhs(&cctx->ctx_redir_lhs,
8603 cctx->ctx_redir_lhs.lhs_name, NULL, cctx) == FAIL)
8604 return NULL;
8605 if (cctx->ctx_redir_lhs.lhs_has_index)
8606 emsg("redir with index not implemented yet");
8607 }
8608
8609 // Gets the redirected text and put it on the stack, then store it
8610 // in the variable.
8611 generate_instr_type(cctx, ISN_REDIREND, &t_string);
8612
8613 if (cctx->ctx_redir_lhs.lhs_append)
8614 generate_instr_drop(cctx, ISN_CONCAT, 1);
8615
8616 if (generate_store_lhs(cctx, &cctx->ctx_redir_lhs, -1) == FAIL)
8617 return NULL;
8618
8619 VIM_CLEAR(cctx->ctx_redir_lhs.lhs_name);
8620 return arg + 3;
8621 }
8622 emsg(_(e_cannot_nest_redir));
8623 return NULL;
8624 }
8625
8626 if (arg[0] == '=' && arg[1] == '>')
8627 {
8628 int append = FALSE;
8629
8630 // redirect to a variable is compiled
8631 arg += 2;
8632 if (*arg == '>')
8633 {
8634 ++arg;
8635 append = TRUE;
8636 }
8637 arg = skipwhite(arg);
8638
8639 if (compile_assign_lhs(arg, &cctx->ctx_redir_lhs, CMD_redir,
8640 FALSE, FALSE, 1, cctx) == FAIL)
8641 return NULL;
8642 generate_instr(cctx, ISN_REDIRSTART);
8643 cctx->ctx_redir_lhs.lhs_append = append;
8644
8645 return arg + cctx->ctx_redir_lhs.lhs_varlen;
8646 }
8647
8648 // other redirects are handled like at script level
8649 return compile_exec(line, eap, cctx);
8650}
8651
Bram Moolenaar4c137212021-04-19 16:48:48 +02008652/*
Bram Moolenaar09689a02020-05-09 22:50:08 +02008653 * Add a function to the list of :def functions.
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008654 * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet.
Bram Moolenaar09689a02020-05-09 22:50:08 +02008655 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02008656 static int
Bram Moolenaar09689a02020-05-09 22:50:08 +02008657add_def_function(ufunc_T *ufunc)
8658{
8659 dfunc_T *dfunc;
8660
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008661 if (def_functions.ga_len == 0)
8662 {
8663 // The first position is not used, so that a zero uf_dfunc_idx means it
8664 // wasn't set.
8665 if (ga_grow(&def_functions, 1) == FAIL)
8666 return FAIL;
8667 ++def_functions.ga_len;
8668 }
8669
Bram Moolenaar09689a02020-05-09 22:50:08 +02008670 // Add the function to "def_functions".
8671 if (ga_grow(&def_functions, 1) == FAIL)
8672 return FAIL;
8673 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
8674 CLEAR_POINTER(dfunc);
8675 dfunc->df_idx = def_functions.ga_len;
8676 ufunc->uf_dfunc_idx = dfunc->df_idx;
8677 dfunc->df_ufunc = ufunc;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01008678 dfunc->df_name = vim_strsave(ufunc->uf_name);
8679 ++dfunc->df_refcount;
Bram Moolenaar09689a02020-05-09 22:50:08 +02008680 ++def_functions.ga_len;
8681 return OK;
8682}
8683
8684/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008685 * After ex_function() has collected all the function lines: parse and compile
8686 * the lines into instructions.
8687 * Adds the function to "def_functions".
Bram Moolenaar9e68c322020-12-25 12:38:04 +01008688 * When "check_return_type" is set then set ufunc->uf_ret_type to the type of
8689 * the return statement (used for lambda). When uf_ret_type is already set
8690 * then check that it matches.
Bram Moolenaarb2049902021-01-24 12:53:53 +01008691 * When "profiling" is true add ISN_PROF_START instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02008692 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02008693 * This can be used recursively through compile_lambda(), which may reallocate
8694 * "def_functions".
Bram Moolenaar822ba242020-05-24 23:00:18 +02008695 * Returns OK or FAIL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008696 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02008697 int
Bram Moolenaarb2049902021-01-24 12:53:53 +01008698compile_def_function(
8699 ufunc_T *ufunc,
8700 int check_return_type,
Bram Moolenaarf002a412021-01-24 13:34:18 +01008701 int profiling UNUSED,
Bram Moolenaarb2049902021-01-24 12:53:53 +01008702 cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008703{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008704 char_u *line = NULL;
Bram Moolenaarf62d7392021-04-14 12:40:00 +02008705 char_u *line_to_free = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008706 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008707 char *errormsg = NULL; // error message
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008708 cctx_T cctx;
8709 garray_T *instr;
Bram Moolenaard66960b2020-10-30 20:46:26 +01008710 int did_emsg_before = did_emsg;
Bram Moolenaar599410c2021-04-10 14:03:43 +02008711 int did_emsg_silent_before = did_emsg_silent;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008712 int ret = FAIL;
8713 sctx_T save_current_sctx = current_sctx;
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02008714 int save_estack_compiling = estack_compiling;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008715 int do_estack_push;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008716 int new_def_function = FALSE;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008717#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01008718 int prof_lnum = -1;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008719#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008720
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008721 // When using a function that was compiled before: Free old instructions.
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01008722 // The index is reused. Otherwise add a new entry in "def_functions".
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008723 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008724 {
Bram Moolenaar09689a02020-05-09 22:50:08 +02008725 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8726 + ufunc->uf_dfunc_idx;
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01008727 delete_def_function_contents(dfunc, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008728 }
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008729 else
8730 {
8731 if (add_def_function(ufunc) == FAIL)
8732 return FAIL;
8733 new_def_function = TRUE;
8734 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008735
Bram Moolenaar985116a2020-07-12 17:31:09 +02008736 ufunc->uf_def_status = UF_COMPILING;
8737
Bram Moolenaara80faa82020-04-12 19:37:17 +02008738 CLEAR_FIELD(cctx);
Bram Moolenaarb2049902021-01-24 12:53:53 +01008739
Bram Moolenaarf002a412021-01-24 13:34:18 +01008740#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01008741 cctx.ctx_profiling = profiling;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008742#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008743 cctx.ctx_ufunc = ufunc;
8744 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02008745 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008746 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
8747 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
8748 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
8749 cctx.ctx_type_list = &ufunc->uf_type_list;
8750 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
8751 instr = &cctx.ctx_instr;
8752
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008753 // Set the context to the function, it may be compiled when called from
8754 // another script. Set the script version to the most modern one.
8755 // The line number will be set in next_line_from_context().
8756 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008757 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
8758
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008759 // Make sure error messages are OK.
8760 do_estack_push = !estack_top_is_ufunc(ufunc, 1);
8761 if (do_estack_push)
8762 estack_push_ufunc(ufunc, 1);
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02008763 estack_compiling = TRUE;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008764
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008765 if (ufunc->uf_def_args.ga_len > 0)
8766 {
8767 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008768 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar12bce952021-03-11 20:04:04 +01008769 int uf_args_len = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008770 int i;
8771 char_u *arg;
8772 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008773 int did_set_arg_type = FALSE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008774
8775 // Produce instructions for the default values of optional arguments.
Bram Moolenaar12bce952021-03-11 20:04:04 +01008776 SOURCING_LNUM = 0; // line number unknown
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008777 for (i = 0; i < count; ++i)
8778 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008779 garray_T *stack = &cctx.ctx_type_stack;
8780 type_T *val_type;
8781 int arg_idx = first_def_arg + i;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008782 where_T where;
Bram Moolenaar12bce952021-03-11 20:04:04 +01008783 int r;
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02008784 int jump_instr_idx = instr->ga_len;
8785 isn_T *isn;
8786
8787 // Use a JUMP_IF_ARG_SET instruction to skip if the value was given.
8788 if (generate_JUMP_IF_ARG_SET(&cctx, i - count - off) == FAIL)
8789 goto erret;
Bram Moolenaar12bce952021-03-11 20:04:04 +01008790
8791 // Make sure later arguments are not found.
8792 ufunc->uf_args.ga_len = i;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008793
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008794 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar12bce952021-03-11 20:04:04 +01008795 r = compile_expr0(&arg, &cctx);
8796
8797 ufunc->uf_args.ga_len = uf_args_len;
8798 if (r == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008799 goto erret;
8800
8801 // If no type specified use the type of the default value.
8802 // Otherwise check that the default value type matches the
8803 // specified type.
8804 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008805 where.wt_index = arg_idx + 1;
8806 where.wt_variable = FALSE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008807 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008808 {
8809 did_set_arg_type = TRUE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008810 ufunc->uf_arg_types[arg_idx] = val_type;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008811 }
Bram Moolenaar8b565c22020-08-30 23:24:20 +02008812 else if (check_type(ufunc->uf_arg_types[arg_idx], val_type,
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008813 TRUE, where) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008814 goto erret;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008815
8816 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008817 goto erret;
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02008818
8819 // set instruction index in JUMP_IF_ARG_SET to here
8820 isn = ((isn_T *)instr->ga_data) + jump_instr_idx;
8821 isn->isn_arg.jumparg.jump_where = instr->ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008822 }
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008823
8824 if (did_set_arg_type)
8825 set_function_type(ufunc);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008826 }
8827
8828 /*
8829 * Loop over all the lines of the function and generate instructions.
8830 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008831 for (;;)
8832 {
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02008833 exarg_T ea;
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02008834 int starts_with_colon = FALSE;
8835 char_u *cmd;
Bram Moolenaar02194d22020-10-24 23:08:38 +02008836 cmdmod_T local_cmdmod;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01008837
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02008838 // Bail out on the first error to avoid a flood of errors and report
8839 // the right line number when inside try/catch.
Bram Moolenaard66960b2020-10-30 20:46:26 +01008840 if (did_emsg_before != did_emsg)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02008841 goto erret;
8842
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008843 if (line != NULL && *line == '|')
8844 // the line continues after a '|'
8845 ++line;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02008846 else if (line != NULL && *skipwhite(line) != NUL
Bram Moolenaar7a092242020-04-16 22:10:49 +02008847 && !(*line == '#' && (line == cctx.ctx_line_start
8848 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008849 {
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02008850 semsg(_(e_trailing_arg), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008851 goto erret;
8852 }
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01008853 else if (line != NULL && vim9_bad_comment(skipwhite(line)))
8854 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008855 else
8856 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02008857 line = next_line_from_context(&cctx, FALSE);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02008858 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarb2049902021-01-24 12:53:53 +01008859 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008860 // beyond the last line
Bram Moolenaarf002a412021-01-24 13:34:18 +01008861#ifdef FEAT_PROFILE
Bram Moolenaarced68a02021-01-24 17:53:47 +01008862 if (cctx.ctx_skip != SKIP_YES)
8863 may_generate_prof_end(&cctx, prof_lnum);
Bram Moolenaarf002a412021-01-24 13:34:18 +01008864#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008865 break;
Bram Moolenaarb2049902021-01-24 12:53:53 +01008866 }
Bram Moolenaarf62d7392021-04-14 12:40:00 +02008867 // Make a copy, splitting off nextcmd and removing trailing spaces
8868 // may change it.
8869 if (line != NULL)
8870 {
8871 line = vim_strsave(line);
8872 vim_free(line_to_free);
8873 line_to_free = line;
8874 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008875 }
8876
Bram Moolenaara80faa82020-04-12 19:37:17 +02008877 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008878 ea.cmdlinep = &line;
8879 ea.cmd = skipwhite(line);
8880
Bram Moolenaarb2049902021-01-24 12:53:53 +01008881 if (*ea.cmd == '#')
8882 {
8883 // "#" starts a comment
8884 line = (char_u *)"";
8885 continue;
8886 }
8887
Bram Moolenaarf002a412021-01-24 13:34:18 +01008888#ifdef FEAT_PROFILE
Bram Moolenaarced68a02021-01-24 17:53:47 +01008889 if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum &&
8890 cctx.ctx_skip != SKIP_YES)
Bram Moolenaarb2049902021-01-24 12:53:53 +01008891 {
8892 may_generate_prof_end(&cctx, prof_lnum);
8893
8894 prof_lnum = cctx.ctx_lnum;
8895 generate_instr(&cctx, ISN_PROF_START);
8896 }
Bram Moolenaarf002a412021-01-24 13:34:18 +01008897#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01008898
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008899 // Some things can be recognized by the first character.
8900 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008901 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008902 case '}':
8903 {
8904 // "}" ends a block scope
8905 scopetype_T stype = cctx.ctx_scope == NULL
8906 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008907
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008908 if (stype == BLOCK_SCOPE)
8909 {
8910 compile_endblock(&cctx);
8911 line = ea.cmd;
8912 }
8913 else
8914 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008915 emsg(_(e_using_rcurly_outside_if_block_scope));
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008916 goto erret;
8917 }
8918 if (line != NULL)
8919 line = skipwhite(ea.cmd + 1);
8920 continue;
8921 }
8922
8923 case '{':
8924 // "{" starts a block scope
8925 // "{'a': 1}->func() is something else
8926 if (ends_excmd(*skipwhite(ea.cmd + 1)))
8927 {
8928 line = compile_block(ea.cmd, &cctx);
8929 continue;
8930 }
8931 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008932 }
8933
8934 /*
8935 * COMMAND MODIFIERS
8936 */
Bram Moolenaar02194d22020-10-24 23:08:38 +02008937 cctx.ctx_has_cmdmod = FALSE;
Bram Moolenaare1004402020-10-24 20:49:43 +02008938 if (parse_command_modifiers(&ea, &errormsg, &local_cmdmod, FALSE)
8939 == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008940 {
8941 if (errormsg != NULL)
8942 goto erret;
8943 // empty line or comment
8944 line = (char_u *)"";
8945 continue;
8946 }
Bram Moolenaare1004402020-10-24 20:49:43 +02008947 generate_cmdmods(&cctx, &local_cmdmod);
8948 undo_cmdmod(&local_cmdmod);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008949
Bram Moolenaare88c8e82020-11-01 17:03:37 +01008950 // Check if there was a colon after the last command modifier or before
8951 // the current position.
8952 for (p = ea.cmd; p >= line; --p)
8953 {
8954 if (*p == ':')
8955 starts_with_colon = TRUE;
8956 if (p < ea.cmd && !VIM_ISWHITE(*p))
8957 break;
8958 }
8959
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008960 // Skip ":call" to get to the function name.
Bram Moolenaar575f24b2020-08-12 14:21:11 +02008961 p = ea.cmd;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008962 if (checkforcmd(&ea.cmd, "call", 3))
Bram Moolenaar575f24b2020-08-12 14:21:11 +02008963 {
8964 if (*ea.cmd == '(')
8965 // not for "call()"
8966 ea.cmd = p;
8967 else
8968 ea.cmd = skipwhite(ea.cmd);
8969 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008970
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02008971 if (!starts_with_colon)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008972 {
Bram Moolenaar17126b12021-01-07 22:03:02 +01008973 int assign;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02008974
Bram Moolenaar17126b12021-01-07 22:03:02 +01008975 // Check for assignment after command modifiers.
8976 assign = may_compile_assignment(&ea, &line, &cctx);
8977 if (assign == OK)
8978 goto nextline;
8979 if (assign == FAIL)
8980 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008981 }
8982
8983 /*
8984 * COMMAND after range
Bram Moolenaar3d48e252020-07-15 14:15:52 +02008985 * 'text'->func() should not be confused with 'a mark
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008986 */
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008987 cmd = ea.cmd;
Bram Moolenaar7c5ad342020-08-12 15:48:55 +02008988 if (*cmd != '\'' || starts_with_colon)
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008989 {
Bram Moolenaar3bd8de42020-09-14 16:37:34 +02008990 ea.cmd = skip_range(ea.cmd, TRUE, NULL);
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008991 if (ea.cmd > cmd)
Bram Moolenaar3d48e252020-07-15 14:15:52 +02008992 {
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008993 if (!starts_with_colon)
8994 {
Bram Moolenaar6e2c2c52020-12-25 19:25:45 +01008995 semsg(_(e_colon_required_before_range_str), cmd);
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008996 goto erret;
8997 }
Bram Moolenaarada1d872021-02-20 08:16:51 +01008998 ea.addr_count = 1;
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008999 if (ends_excmd2(line, ea.cmd))
9000 {
9001 // A range without a command: jump to the line.
9002 // TODO: compile to a more efficient command, possibly
9003 // calling parse_cmd_address().
9004 ea.cmdidx = CMD_SIZE;
9005 line = compile_exec(line, &ea, &cctx);
9006 goto nextline;
9007 }
Bram Moolenaar3d48e252020-07-15 14:15:52 +02009008 }
Bram Moolenaardf069ee2020-06-22 23:02:51 +02009009 }
Bram Moolenaar77b10ff2021-03-14 13:21:35 +01009010 p = find_ex_command(&ea, NULL, starts_with_colon
9011 ? NULL : item_exists, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009012
Bram Moolenaard1510ee2021-01-04 16:15:58 +01009013 if (p == NULL)
9014 {
9015 if (cctx.ctx_skip != SKIP_YES)
9016 emsg(_(e_ambiguous_use_of_user_defined_command));
9017 goto erret;
9018 }
9019
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009020 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
9021 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02009022 if (cctx.ctx_skip == SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01009023 {
9024 line += STRLEN(line);
Bram Moolenaarf665e972020-12-05 19:17:16 +01009025 goto nextline;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01009026 }
9027
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009028 // Expression or function call.
Bram Moolenaar007f9d62020-07-06 23:04:49 +02009029 if (ea.cmdidx != CMD_eval)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009030 {
Bram Moolenaar52c124d2020-12-20 21:43:35 +01009031 // CMD_var cannot happen, compile_assignment() above would be
9032 // used. Most likely an assignment to a non-existing variable.
9033 semsg(_(e_command_not_recognized_str), ea.cmd);
Bram Moolenaar007f9d62020-07-06 23:04:49 +02009034 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009035 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009036 }
9037
Bram Moolenaar3988f642020-08-27 22:43:03 +02009038 if (cctx.ctx_had_return
Bram Moolenaara259d8d2020-01-31 20:10:50 +01009039 && ea.cmdidx != CMD_elseif
9040 && ea.cmdidx != CMD_else
Bram Moolenaarefd88552020-06-18 20:50:10 +02009041 && ea.cmdidx != CMD_endif
9042 && ea.cmdidx != CMD_endfor
9043 && ea.cmdidx != CMD_endwhile
9044 && ea.cmdidx != CMD_catch
9045 && ea.cmdidx != CMD_finally
9046 && ea.cmdidx != CMD_endtry)
9047 {
Bram Moolenaar3988f642020-08-27 22:43:03 +02009048 emsg(_(e_unreachable_code_after_return));
9049 goto erret;
Bram Moolenaarefd88552020-06-18 20:50:10 +02009050 }
9051
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02009052 p = skipwhite(p);
9053 if (ea.cmdidx != CMD_SIZE
9054 && ea.cmdidx != CMD_write && ea.cmdidx != CMD_read)
9055 {
Bram Moolenaar9b123d82020-09-14 22:39:11 +02009056 if (ea.cmdidx >= 0)
9057 ea.argt = excmd_get_argt(ea.cmdidx);
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02009058 if ((ea.argt & EX_BANG) && *p == '!')
9059 {
9060 ea.forceit = TRUE;
9061 p = skipwhite(p + 1);
9062 }
9063 }
9064
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009065 switch (ea.cmdidx)
9066 {
9067 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02009068 ea.arg = p;
9069 line = compile_nested_function(&ea, &cctx);
9070 break;
9071
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009072 case CMD_function:
Bram Moolenaar451c2e32020-08-15 16:33:28 +02009073 // TODO: should we allow this, e.g. to declare a global
9074 // function?
9075 emsg(_(e_cannot_use_function_inside_def));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009076 goto erret;
9077
9078 case CMD_return:
Bram Moolenaar9e68c322020-12-25 12:38:04 +01009079 line = compile_return(p, check_return_type, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009080 cctx.ctx_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009081 break;
9082
9083 case CMD_let:
Bram Moolenaarc58f5452020-10-21 20:58:52 +02009084 emsg(_(e_cannot_use_let_in_vim9_script));
9085 break;
Bram Moolenaar30fd8202020-09-26 15:09:30 +02009086 case CMD_var:
9087 case CMD_final:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009088 case CMD_const:
9089 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02009090 if (line == p)
9091 line = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009092 break;
9093
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02009094 case CMD_unlet:
9095 case CMD_unlockvar:
9096 case CMD_lockvar:
9097 line = compile_unletlock(p, &ea, &cctx);
9098 break;
9099
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009100 case CMD_import:
9101 line = compile_import(p, &cctx);
9102 break;
9103
9104 case CMD_if:
9105 line = compile_if(p, &cctx);
9106 break;
9107 case CMD_elseif:
9108 line = compile_elseif(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009109 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009110 break;
9111 case CMD_else:
9112 line = compile_else(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009113 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009114 break;
9115 case CMD_endif:
9116 line = compile_endif(p, &cctx);
9117 break;
9118
9119 case CMD_while:
9120 line = compile_while(p, &cctx);
9121 break;
9122 case CMD_endwhile:
9123 line = compile_endwhile(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009124 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009125 break;
9126
9127 case CMD_for:
9128 line = compile_for(p, &cctx);
9129 break;
9130 case CMD_endfor:
9131 line = compile_endfor(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009132 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009133 break;
9134 case CMD_continue:
9135 line = compile_continue(p, &cctx);
9136 break;
9137 case CMD_break:
9138 line = compile_break(p, &cctx);
9139 break;
9140
9141 case CMD_try:
9142 line = compile_try(p, &cctx);
9143 break;
9144 case CMD_catch:
9145 line = compile_catch(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009146 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009147 break;
9148 case CMD_finally:
9149 line = compile_finally(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009150 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009151 break;
9152 case CMD_endtry:
9153 line = compile_endtry(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009154 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009155 break;
9156 case CMD_throw:
9157 line = compile_throw(p, &cctx);
9158 break;
9159
Bram Moolenaar007f9d62020-07-06 23:04:49 +02009160 case CMD_eval:
9161 if (compile_expr0(&p, &cctx) == FAIL)
9162 goto erret;
9163
Bram Moolenaar3988f642020-08-27 22:43:03 +02009164 // drop the result
Bram Moolenaar007f9d62020-07-06 23:04:49 +02009165 generate_instr_drop(&cctx, ISN_DROP, 1);
9166
9167 line = skipwhite(p);
9168 break;
9169
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009170 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009171 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01009172 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02009173 case CMD_echomsg:
9174 case CMD_echoerr:
9175 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01009176 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009177
Bram Moolenaarc3516f72020-09-08 22:45:35 +02009178 case CMD_put:
9179 ea.cmd = cmd;
9180 line = compile_put(p, &ea, &cctx);
9181 break;
9182
Bram Moolenaar4c137212021-04-19 16:48:48 +02009183 case CMD_substitute:
9184 if (cctx.ctx_skip == SKIP_YES)
9185 line = (char_u *)"";
9186 else
9187 {
9188 ea.arg = p;
9189 line = compile_substitute(line, &ea, &cctx);
9190 }
9191 break;
9192
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009193 case CMD_redir:
9194 ea.arg = p;
9195 line = compile_redir(line, &ea, &cctx);
9196 break;
9197
Bram Moolenaar3988f642020-08-27 22:43:03 +02009198 // TODO: any other commands with an expression argument?
Bram Moolenaardf069ee2020-06-22 23:02:51 +02009199
Bram Moolenaarae616492020-07-28 20:07:27 +02009200 case CMD_append:
9201 case CMD_change:
9202 case CMD_insert:
Bram Moolenaar10b94212021-02-19 21:42:57 +01009203 case CMD_k:
Bram Moolenaarf5a48012020-08-01 17:00:03 +02009204 case CMD_t:
Bram Moolenaarae616492020-07-28 20:07:27 +02009205 case CMD_xit:
9206 not_in_vim9(&ea);
9207 goto erret;
9208
Bram Moolenaar002262f2020-07-08 17:47:57 +02009209 case CMD_SIZE:
Bram Moolenaar3988f642020-08-27 22:43:03 +02009210 if (cctx.ctx_skip != SKIP_YES)
9211 {
9212 semsg(_(e_invalid_command_str), ea.cmd);
9213 goto erret;
9214 }
9215 // We don't check for a next command here.
9216 line = (char_u *)"";
9217 break;
Bram Moolenaar002262f2020-07-08 17:47:57 +02009218
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009219 default:
Bram Moolenaar5163fcc2020-08-27 23:37:09 +02009220 if (cctx.ctx_skip == SKIP_YES)
9221 {
9222 // We don't check for a next command here.
9223 line = (char_u *)"";
9224 }
9225 else
9226 {
9227 // Not recognized, execute with do_cmdline_cmd().
9228 ea.arg = p;
9229 line = compile_exec(line, &ea, &cctx);
9230 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009231 break;
9232 }
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02009233nextline:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009234 if (line == NULL)
9235 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02009236 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009237
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02009238 // Undo any command modifiers.
Bram Moolenaar02194d22020-10-24 23:08:38 +02009239 generate_undo_cmdmods(&cctx);
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02009240
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009241 if (cctx.ctx_type_stack.ga_len < 0)
9242 {
9243 iemsg("Type stack underflow");
9244 goto erret;
9245 }
9246 }
9247
9248 if (cctx.ctx_scope != NULL)
9249 {
9250 if (cctx.ctx_scope->se_type == IF_SCOPE)
9251 emsg(_(e_endif));
9252 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
9253 emsg(_(e_endwhile));
9254 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
9255 emsg(_(e_endfor));
9256 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02009257 emsg(_(e_missing_rcurly));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009258 goto erret;
9259 }
9260
Bram Moolenaarefd88552020-06-18 20:50:10 +02009261 if (!cctx.ctx_had_return)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009262 {
9263 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
9264 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02009265 emsg(_(e_missing_return_statement));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009266 goto erret;
9267 }
9268
9269 // Return zero if there is no return at the end.
Bram Moolenaar299f3032021-01-08 20:53:09 +01009270 generate_instr(&cctx, ISN_RETURN_ZERO);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009271 }
9272
Bram Moolenaar599410c2021-04-10 14:03:43 +02009273 // When compiled with ":silent!" and there was an error don't consider the
9274 // function compiled.
9275 if (emsg_silent == 0 || did_emsg_silent == did_emsg_silent_before)
Bram Moolenaar05afcee2020-03-31 23:32:31 +02009276 {
9277 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9278 + ufunc->uf_dfunc_idx;
9279 dfunc->df_deleted = FALSE;
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01009280 dfunc->df_script_seq = current_sctx.sc_seq;
Bram Moolenaarf002a412021-01-24 13:34:18 +01009281#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01009282 if (cctx.ctx_profiling)
9283 {
9284 dfunc->df_instr_prof = instr->ga_data;
9285 dfunc->df_instr_prof_count = instr->ga_len;
9286 }
9287 else
Bram Moolenaarf002a412021-01-24 13:34:18 +01009288#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01009289 {
9290 dfunc->df_instr = instr->ga_data;
9291 dfunc->df_instr_count = instr->ga_len;
9292 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02009293 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02009294 dfunc->df_has_closure = cctx.ctx_has_closure;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02009295 if (cctx.ctx_outer_used)
9296 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009297 ufunc->uf_def_status = UF_COMPILED;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02009298 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009299
9300 ret = OK;
9301
9302erret:
Bram Moolenaar599410c2021-04-10 14:03:43 +02009303 if (ufunc->uf_def_status == UF_COMPILING)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009304 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02009305 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9306 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009307
Bram Moolenaar8238f082021-04-20 21:10:48 +02009308 clear_instr_ga(instr);
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009309 VIM_CLEAR(dfunc->df_name);
Bram Moolenaar20431c92020-03-20 18:39:46 +01009310
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02009311 // If using the last entry in the table and it was added above, we
9312 // might as well remove it.
9313 if (!dfunc->df_deleted && new_def_function
Bram Moolenaar45a15082020-05-25 00:28:33 +02009314 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02009315 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01009316 --def_functions.ga_len;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02009317 ufunc->uf_dfunc_idx = 0;
9318 }
Bram Moolenaar701cc6c2021-04-10 13:33:48 +02009319 ufunc->uf_def_status = UF_COMPILE_ERROR;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009320
Bram Moolenaar3cca2992020-04-02 22:57:36 +02009321 while (cctx.ctx_scope != NULL)
9322 drop_scope(&cctx);
9323
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009324 if (errormsg != NULL)
9325 emsg(errormsg);
Bram Moolenaard66960b2020-10-30 20:46:26 +01009326 else if (did_emsg == did_emsg_before)
Bram Moolenaare13bdec2020-10-16 23:16:47 +02009327 emsg(_(e_compiling_def_function_failed));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009328 }
9329
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009330 if (cctx.ctx_redir_lhs.lhs_name != NULL)
9331 {
9332 if (ret == OK)
9333 {
9334 emsg(_(e_missing_redir_end));
9335 ret = FAIL;
9336 }
9337 vim_free(cctx.ctx_redir_lhs.lhs_name);
9338 }
9339
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009340 current_sctx = save_current_sctx;
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02009341 estack_compiling = save_estack_compiling;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02009342 if (do_estack_push)
9343 estack_pop();
9344
Bram Moolenaarf62d7392021-04-14 12:40:00 +02009345 vim_free(line_to_free);
Bram Moolenaar20431c92020-03-20 18:39:46 +01009346 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02009347 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009348 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar822ba242020-05-24 23:00:18 +02009349 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009350}
9351
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02009352 void
9353set_function_type(ufunc_T *ufunc)
9354{
9355 int varargs = ufunc->uf_va_name != NULL;
9356 int argcount = ufunc->uf_args.ga_len;
9357
9358 // Create a type for the function, with the return type and any
9359 // argument types.
9360 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
9361 // The type is included in "tt_args".
9362 if (argcount > 0 || varargs)
9363 {
Bram Moolenaar18062fc2021-03-05 21:35:47 +01009364 if (ufunc->uf_type_list.ga_itemsize == 0)
9365 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02009366 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
9367 argcount, &ufunc->uf_type_list);
9368 // Add argument types to the function type.
9369 if (func_type_add_arg_types(ufunc->uf_func_type,
9370 argcount + varargs,
9371 &ufunc->uf_type_list) == FAIL)
9372 return;
9373 ufunc->uf_func_type->tt_argcount = argcount + varargs;
9374 ufunc->uf_func_type->tt_min_argcount =
9375 argcount - ufunc->uf_def_args.ga_len;
9376 if (ufunc->uf_arg_types == NULL)
9377 {
9378 int i;
9379
9380 // lambda does not have argument types.
9381 for (i = 0; i < argcount; ++i)
9382 ufunc->uf_func_type->tt_args[i] = &t_any;
9383 }
9384 else
9385 mch_memmove(ufunc->uf_func_type->tt_args,
9386 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
9387 if (varargs)
9388 {
9389 ufunc->uf_func_type->tt_args[argcount] =
Bram Moolenaar2a389082021-04-09 20:24:31 +02009390 ufunc->uf_va_type == NULL ? &t_list_any : ufunc->uf_va_type;
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02009391 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
9392 }
9393 }
9394 else
9395 // No arguments, can use a predefined type.
9396 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
9397 argcount, &ufunc->uf_type_list);
9398}
9399
9400
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009401/*
9402 * Delete an instruction, free what it contains.
9403 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01009404 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009405delete_instr(isn_T *isn)
9406{
9407 switch (isn->isn_type)
9408 {
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009409 case ISN_DEF:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009410 case ISN_EXEC:
Bram Moolenaar03290b82020-12-19 16:30:44 +01009411 case ISN_LOADAUTO:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009412 case ISN_LOADB:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009413 case ISN_LOADENV:
9414 case ISN_LOADG:
9415 case ISN_LOADOPT:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009416 case ISN_LOADT:
9417 case ISN_LOADW:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009418 case ISN_PUSHEXC:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009419 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009420 case ISN_PUSHS:
Bram Moolenaar08597872020-12-10 19:43:40 +01009421 case ISN_RANGE:
Bram Moolenaar03290b82020-12-19 16:30:44 +01009422 case ISN_STOREAUTO:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009423 case ISN_STOREB:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01009424 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009425 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02009426 case ISN_STORET:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009427 case ISN_STOREW:
9428 case ISN_STRINGMEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009429 vim_free(isn->isn_arg.string);
9430 break;
9431
Bram Moolenaar4c137212021-04-19 16:48:48 +02009432 case ISN_SUBSTITUTE:
Bram Moolenaar4f2df372021-04-19 21:06:31 +02009433 {
9434 int idx;
9435 isn_T *list = isn->isn_arg.subs.subs_instr;
9436
9437 vim_free(isn->isn_arg.subs.subs_cmd);
9438 for (idx = 0; list[idx].isn_type != ISN_FINISH; ++idx)
9439 delete_instr(list + idx);
9440 vim_free(list);
9441 }
Bram Moolenaar4c137212021-04-19 16:48:48 +02009442 break;
9443
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009444 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01009445 case ISN_STORES:
9446 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009447 break;
9448
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02009449 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02009450 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02009451 vim_free(isn->isn_arg.unlet.ul_name);
9452 break;
9453
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009454 case ISN_STOREOPT:
9455 vim_free(isn->isn_arg.storeopt.so_name);
9456 break;
9457
9458 case ISN_PUSHBLOB: // push blob isn_arg.blob
9459 blob_unref(isn->isn_arg.blob);
9460 break;
9461
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009462 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01009463#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009464 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01009465#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009466 break;
9467
9468 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01009469#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009470 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01009471#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009472 break;
9473
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009474 case ISN_UCALL:
9475 vim_free(isn->isn_arg.ufunc.cuf_name);
9476 break;
9477
Bram Moolenaar221fcc72020-05-05 19:46:20 +02009478 case ISN_FUNCREF:
9479 {
9480 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9481 + isn->isn_arg.funcref.fr_func;
Bram Moolenaar077a4232020-12-22 18:33:27 +01009482 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaara05e5242020-09-19 18:19:19 +02009483
Bram Moolenaar077a4232020-12-22 18:33:27 +01009484 if (ufunc != NULL && func_name_refcount(ufunc->uf_name))
9485 func_ptr_unref(ufunc);
Bram Moolenaara05e5242020-09-19 18:19:19 +02009486 }
9487 break;
9488
9489 case ISN_DCALL:
9490 {
9491 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9492 + isn->isn_arg.dfunc.cdf_idx;
9493
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02009494 if (dfunc->df_ufunc != NULL
9495 && func_name_refcount(dfunc->df_ufunc->uf_name))
Bram Moolenaara05e5242020-09-19 18:19:19 +02009496 func_ptr_unref(dfunc->df_ufunc);
Bram Moolenaar221fcc72020-05-05 19:46:20 +02009497 }
9498 break;
9499
Bram Moolenaar38ddf332020-07-31 22:05:04 +02009500 case ISN_NEWFUNC:
Bram Moolenaarce658352020-07-31 23:47:12 +02009501 {
9502 char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
9503 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
9504
9505 if (ufunc != NULL)
9506 {
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009507 unlink_def_function(ufunc);
Bram Moolenaarce658352020-07-31 23:47:12 +02009508 func_ptr_unref(ufunc);
9509 }
9510
9511 vim_free(lambda);
9512 vim_free(isn->isn_arg.newfunc.nf_global);
9513 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02009514 break;
9515
Bram Moolenaar5e654232020-09-16 15:22:00 +02009516 case ISN_CHECKTYPE:
Bram Moolenaaraa210a32021-01-02 15:41:03 +01009517 case ISN_SETTYPE:
Bram Moolenaar5e654232020-09-16 15:22:00 +02009518 free_type(isn->isn_arg.type.ct_type);
9519 break;
9520
Bram Moolenaar02194d22020-10-24 23:08:38 +02009521 case ISN_CMDMOD:
9522 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
9523 ->cmod_filter_regmatch.regprog);
9524 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
9525 break;
9526
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01009527 case ISN_LOADSCRIPT:
9528 case ISN_STORESCRIPT:
9529 vim_free(isn->isn_arg.script.scriptref);
9530 break;
9531
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01009532 case ISN_TRY:
9533 vim_free(isn->isn_arg.try.try_ref);
9534 break;
9535
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009536 case ISN_2BOOL:
9537 case ISN_2STRING:
Bram Moolenaar418f1df2020-08-12 21:34:49 +02009538 case ISN_2STRING_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009539 case ISN_ADDBLOB:
9540 case ISN_ADDLIST:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009541 case ISN_ANYINDEX:
9542 case ISN_ANYSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009543 case ISN_BCALL:
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02009544 case ISN_BLOBAPPEND:
Bram Moolenaarcfc30232021-04-11 20:26:34 +02009545 case ISN_BLOBINDEX:
9546 case ISN_BLOBSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009547 case ISN_CATCH:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009548 case ISN_CHECKLEN:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009549 case ISN_CHECKNR:
Bram Moolenaar02194d22020-10-24 23:08:38 +02009550 case ISN_CMDMOD_REV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009551 case ISN_COMPAREANY:
9552 case ISN_COMPAREBLOB:
9553 case ISN_COMPAREBOOL:
9554 case ISN_COMPAREDICT:
9555 case ISN_COMPAREFLOAT:
9556 case ISN_COMPAREFUNC:
9557 case ISN_COMPARELIST:
9558 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009559 case ISN_COMPARESPECIAL:
9560 case ISN_COMPARESTRING:
9561 case ISN_CONCAT:
Bram Moolenaar2bb26582020-10-03 22:52:39 +02009562 case ISN_COND2BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009563 case ISN_DROP:
9564 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02009565 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02009566 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009567 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02009568 case ISN_EXECCONCAT:
9569 case ISN_EXECUTE:
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01009570 case ISN_FINALLY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009571 case ISN_FOR:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009572 case ISN_GETITEM:
9573 case ISN_JUMP:
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02009574 case ISN_JUMP_IF_ARG_SET:
Bram Moolenaar1dcae592020-10-19 19:02:42 +02009575 case ISN_LISTAPPEND:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02009576 case ISN_LISTINDEX:
Bram Moolenaared591872020-08-15 22:14:53 +02009577 case ISN_LISTSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009578 case ISN_LOAD:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02009579 case ISN_LOADBDICT:
9580 case ISN_LOADGDICT:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02009581 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009582 case ISN_LOADREG:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02009583 case ISN_LOADTDICT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009584 case ISN_LOADV:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02009585 case ISN_LOADWDICT:
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02009586 case ISN_LOCKCONST:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009587 case ISN_MEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009588 case ISN_NEGATENR:
9589 case ISN_NEWDICT:
9590 case ISN_NEWLIST:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009591 case ISN_OPANY:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009592 case ISN_OPFLOAT:
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009593 case ISN_FINISH:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009594 case ISN_OPNR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009595 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02009596 case ISN_PCALL_END:
Bram Moolenaarb2049902021-01-24 12:53:53 +01009597 case ISN_PROF_END:
9598 case ISN_PROF_START:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009599 case ISN_PUSHBOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009600 case ISN_PUSHF:
9601 case ISN_PUSHNR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009602 case ISN_PUSHSPEC:
Bram Moolenaarc3516f72020-09-08 22:45:35 +02009603 case ISN_PUT:
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009604 case ISN_REDIREND:
9605 case ISN_REDIRSTART:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009606 case ISN_RETURN:
Bram Moolenaar299f3032021-01-08 20:53:09 +01009607 case ISN_RETURN_ZERO:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009608 case ISN_SHUFFLE:
9609 case ISN_SLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009610 case ISN_STORE:
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01009611 case ISN_STOREINDEX:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009612 case ISN_STORENR:
9613 case ISN_STOREOUTER:
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009614 case ISN_STORERANGE:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009615 case ISN_STOREREG:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009616 case ISN_STOREV:
9617 case ISN_STRINDEX:
9618 case ISN_STRSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009619 case ISN_THROW:
Bram Moolenaarc150c092021-02-13 15:02:46 +01009620 case ISN_TRYCONT:
Bram Moolenaar752fc692021-01-04 21:57:11 +01009621 case ISN_UNLETINDEX:
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01009622 case ISN_UNLETRANGE:
Bram Moolenaar792f7862020-11-23 08:31:18 +01009623 case ISN_UNPACK:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009624 // nothing allocated
9625 break;
9626 }
9627}
9628
9629/*
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009630 * Free all instructions for "dfunc" except df_name.
Bram Moolenaar20431c92020-03-20 18:39:46 +01009631 */
9632 static void
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009633delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
Bram Moolenaar20431c92020-03-20 18:39:46 +01009634{
9635 int idx;
9636
9637 ga_clear(&dfunc->df_def_args_isn);
9638
9639 if (dfunc->df_instr != NULL)
9640 {
9641 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
9642 delete_instr(dfunc->df_instr + idx);
9643 VIM_CLEAR(dfunc->df_instr);
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009644 dfunc->df_instr = NULL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009645 }
Bram Moolenaarc05fe072021-01-24 21:30:48 +01009646#ifdef FEAT_PROFILE
9647 if (dfunc->df_instr_prof != NULL)
9648 {
9649 for (idx = 0; idx < dfunc->df_instr_prof_count; ++idx)
9650 delete_instr(dfunc->df_instr_prof + idx);
9651 VIM_CLEAR(dfunc->df_instr_prof);
9652 dfunc->df_instr_prof = NULL;
9653 }
9654#endif
Bram Moolenaar20431c92020-03-20 18:39:46 +01009655
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009656 if (mark_deleted)
9657 dfunc->df_deleted = TRUE;
9658 if (dfunc->df_ufunc != NULL)
9659 dfunc->df_ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009660}
9661
9662/*
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009663 * When a user function is deleted, clear the contents of any associated def
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009664 * function, unless another user function still uses it.
9665 * The position in def_functions can be re-used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009666 */
9667 void
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009668unlink_def_function(ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009669{
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009670 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009671 {
9672 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9673 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009674
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009675 if (--dfunc->df_refcount <= 0)
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009676 delete_def_function_contents(dfunc, TRUE);
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009677 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009678 ufunc->uf_dfunc_idx = 0;
9679 if (dfunc->df_ufunc == ufunc)
9680 dfunc->df_ufunc = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009681 }
9682}
9683
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009684/*
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009685 * Used when a user function refers to an existing dfunc.
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009686 */
9687 void
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009688link_def_function(ufunc_T *ufunc)
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009689{
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009690 if (ufunc->uf_dfunc_idx > 0)
9691 {
9692 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9693 + ufunc->uf_dfunc_idx;
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009694
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009695 ++dfunc->df_refcount;
9696 }
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009697}
9698
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009699#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01009700/*
9701 * Free all functions defined with ":def".
9702 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009703 void
9704free_def_functions(void)
9705{
Bram Moolenaar20431c92020-03-20 18:39:46 +01009706 int idx;
9707
9708 for (idx = 0; idx < def_functions.ga_len; ++idx)
9709 {
9710 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
9711
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009712 delete_def_function_contents(dfunc, TRUE);
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009713 vim_free(dfunc->df_name);
Bram Moolenaar20431c92020-03-20 18:39:46 +01009714 }
9715
9716 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009717}
9718#endif
9719
9720
9721#endif // FEAT_EVAL