blob: 027f79d95cf775efcfcf61fc750db770f05b7256 [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 Moolenaar4c137212021-04-19 16:48:48 +02002182 static int
2183generate_substitute(char_u *cmd, int instr_start, cctx_T *cctx)
2184{
2185 isn_T *isn;
2186 isn_T *instr;
2187 int instr_count = cctx->ctx_instr.ga_len - instr_start;
2188
2189 instr = ALLOC_MULT(isn_T, instr_count + 1);
2190 if (instr == NULL)
2191 return FAIL;
2192 // Move the generated instructions into the ISN_SUBSTITUTE instructions,
2193 // then truncate the list of instructions, so they are used only once.
2194 mch_memmove(instr, ((isn_T *)cctx->ctx_instr.ga_data) + instr_start,
2195 instr_count * sizeof(isn_T));
2196 instr[instr_count].isn_type = ISN_FINISH;
2197 cctx->ctx_instr.ga_len = instr_start;
2198
2199 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2200 {
2201 vim_free(instr);
2202 return FAIL;
2203 }
2204 isn->isn_arg.subs.subs_cmd = vim_strsave(cmd);
2205 isn->isn_arg.subs.subs_instr = instr;
2206 return OK;
2207}
2208
Bram Moolenaar08597872020-12-10 19:43:40 +01002209/*
2210 * Generate ISN_RANGE. Consumes "range". Return OK/FAIL.
2211 */
2212 static int
2213generate_RANGE(cctx_T *cctx, char_u *range)
2214{
2215 isn_T *isn;
2216 garray_T *stack = &cctx->ctx_type_stack;
2217
2218 if ((isn = generate_instr(cctx, ISN_RANGE)) == NULL)
2219 return FAIL;
2220 isn->isn_arg.string = range;
2221
2222 if (ga_grow(stack, 1) == FAIL)
2223 return FAIL;
2224 ((type_T **)stack->ga_data)[stack->ga_len] = &t_number;
2225 ++stack->ga_len;
2226 return OK;
2227}
2228
Bram Moolenaar792f7862020-11-23 08:31:18 +01002229 static int
2230generate_UNPACK(cctx_T *cctx, int var_count, int semicolon)
2231{
2232 isn_T *isn;
2233
2234 RETURN_OK_IF_SKIP(cctx);
2235 if ((isn = generate_instr(cctx, ISN_UNPACK)) == NULL)
2236 return FAIL;
2237 isn->isn_arg.unpack.unp_count = var_count;
2238 isn->isn_arg.unpack.unp_semicolon = semicolon;
2239 return OK;
2240}
2241
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002242/*
Bram Moolenaar02194d22020-10-24 23:08:38 +02002243 * Generate an instruction for any command modifiers.
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002244 */
2245 static int
Bram Moolenaare1004402020-10-24 20:49:43 +02002246generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002247{
2248 isn_T *isn;
2249
Bram Moolenaarfa984412021-03-25 22:15:28 +01002250 if (has_cmdmod(cmod))
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002251 {
Bram Moolenaar02194d22020-10-24 23:08:38 +02002252 cctx->ctx_has_cmdmod = TRUE;
2253
2254 if ((isn = generate_instr(cctx, ISN_CMDMOD)) == NULL)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002255 return FAIL;
Bram Moolenaar02194d22020-10-24 23:08:38 +02002256 isn->isn_arg.cmdmod.cf_cmdmod = ALLOC_ONE(cmdmod_T);
2257 if (isn->isn_arg.cmdmod.cf_cmdmod == NULL)
2258 return FAIL;
2259 mch_memmove(isn->isn_arg.cmdmod.cf_cmdmod, cmod, sizeof(cmdmod_T));
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01002260 // filter program now belongs to the instruction
Bram Moolenaar02194d22020-10-24 23:08:38 +02002261 cmod->cmod_filter_regmatch.regprog = NULL;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002262 }
Bram Moolenaar02194d22020-10-24 23:08:38 +02002263
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002264 return OK;
2265}
2266
2267 static int
Bram Moolenaar02194d22020-10-24 23:08:38 +02002268generate_undo_cmdmods(cctx_T *cctx)
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002269{
Bram Moolenaarf665e972020-12-05 19:17:16 +01002270 if (cctx->ctx_has_cmdmod && generate_instr(cctx, ISN_CMDMOD_REV) == NULL)
2271 return FAIL;
Bram Moolenaar7cd24222021-01-12 18:58:39 +01002272 cctx->ctx_has_cmdmod = FALSE;
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002273 return OK;
2274}
2275
Bram Moolenaarfa984412021-03-25 22:15:28 +01002276 static int
2277misplaced_cmdmod(cctx_T *cctx)
Bram Moolenaara91a7132021-03-25 21:12:15 +01002278{
2279 garray_T *instr = &cctx->ctx_instr;
2280
Bram Moolenaara91a7132021-03-25 21:12:15 +01002281 if (cctx->ctx_has_cmdmod
2282 && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
2283 == ISN_CMDMOD)
2284 {
Bram Moolenaarfa984412021-03-25 22:15:28 +01002285 emsg(_(e_misplaced_command_modifier));
2286 return TRUE;
Bram Moolenaara91a7132021-03-25 21:12:15 +01002287 }
Bram Moolenaarfa984412021-03-25 22:15:28 +01002288 return FALSE;
Bram Moolenaara91a7132021-03-25 21:12:15 +01002289}
2290
2291/*
2292 * Get the index of the current instruction.
2293 * This compenstates for a preceding ISN_CMDMOD and ISN_PROF_START.
2294 */
2295 static int
2296current_instr_idx(cctx_T *cctx)
2297{
2298 garray_T *instr = &cctx->ctx_instr;
2299 int idx = instr->ga_len;
2300
2301 if (cctx->ctx_has_cmdmod && ((isn_T *)instr->ga_data)[idx - 1]
2302 .isn_type == ISN_CMDMOD)
2303 --idx;
2304#ifdef FEAT_PROFILE
2305 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[idx - 1]
2306 .isn_type == ISN_PROF_START)
2307 --idx;
2308#endif
2309 return idx;
2310}
2311
Bram Moolenaarf002a412021-01-24 13:34:18 +01002312#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01002313 static void
2314may_generate_prof_end(cctx_T *cctx, int prof_lnum)
2315{
2316 if (cctx->ctx_profiling && prof_lnum >= 0)
Bram Moolenaarb2049902021-01-24 12:53:53 +01002317 generate_instr(cctx, ISN_PROF_END);
Bram Moolenaarb2049902021-01-24 12:53:53 +01002318}
Bram Moolenaarf002a412021-01-24 13:34:18 +01002319#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01002320
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02002321/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002322 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002323 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002324 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002325 static lvar_T *
Bram Moolenaare8211a32020-10-09 22:04:29 +02002326reserve_local(
2327 cctx_T *cctx,
2328 char_u *name,
2329 size_t len,
2330 int isConst,
2331 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002332{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002333 lvar_T *lvar;
2334
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002335 if (arg_exists(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002336 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002337 emsg_namelen(_(e_str_is_used_as_argument), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002338 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002339 }
2340
2341 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002342 return NULL;
2343 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaare8211a32020-10-09 22:04:29 +02002344 CLEAR_POINTER(lvar);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002345
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002346 // Every local variable uses the next entry on the stack. We could re-use
2347 // the last ones when leaving a scope, but then variables used in a closure
2348 // might get overwritten. To keep things simple do not re-use stack
2349 // entries. This is less efficient, but memory is cheap these days.
2350 lvar->lv_idx = cctx->ctx_locals_count++;
2351
Bram Moolenaar71ccd032020-06-12 22:59:11 +02002352 lvar->lv_name = vim_strnsave(name, len == 0 ? STRLEN(name) : len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002353 lvar->lv_const = isConst;
2354 lvar->lv_type = type;
2355
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002356 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002357}
2358
2359/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002360 * Remove local variables above "new_top".
2361 */
2362 static void
2363unwind_locals(cctx_T *cctx, int new_top)
2364{
2365 if (cctx->ctx_locals.ga_len > new_top)
2366 {
2367 int idx;
2368 lvar_T *lvar;
2369
2370 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
2371 {
2372 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
2373 vim_free(lvar->lv_name);
2374 }
2375 }
2376 cctx->ctx_locals.ga_len = new_top;
2377}
2378
2379/*
2380 * Free all local variables.
2381 */
2382 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002383free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01002384{
2385 unwind_locals(cctx, 0);
2386 ga_clear(&cctx->ctx_locals);
2387}
2388
2389/*
Bram Moolenaar08251752021-01-11 21:20:18 +01002390 * If "check_writable" is ASSIGN_CONST give an error if the variable was
2391 * defined with :final or :const, if "check_writable" is ASSIGN_FINAL give an
2392 * error if the variable was defined with :const.
2393 */
2394 static int
2395check_item_writable(svar_T *sv, int check_writable, char_u *name)
2396{
2397 if ((check_writable == ASSIGN_CONST && sv->sv_const != 0)
2398 || (check_writable == ASSIGN_FINAL
2399 && sv->sv_const == ASSIGN_CONST))
2400 {
2401 semsg(_(e_readonlyvar), name);
2402 return FAIL;
2403 }
2404 return OK;
2405}
2406
2407/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002408 * Find "name" in script-local items of script "sid".
Bram Moolenaar08251752021-01-11 21:20:18 +01002409 * Pass "check_writable" to check_item_writable().
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002410 * Returns the index in "sn_var_vals" if found.
2411 * If found but not in "sn_var_vals" returns -1.
Bram Moolenaar08251752021-01-11 21:20:18 +01002412 * If not found or the variable is not writable returns -2.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002413 */
2414 int
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002415get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002416{
2417 hashtab_T *ht;
2418 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002419 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002420 svar_T *sv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002421 int idx;
2422
Bram Moolenaare3d46852020-08-29 13:39:17 +02002423 if (!SCRIPT_ID_VALID(sid))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002424 return -1;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002425 if (sid == current_sctx.sc_sid)
2426 {
Bram Moolenaar209f0202020-10-15 13:57:56 +02002427 sallvar_T *sav = find_script_var(name, 0, cctx);
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002428
2429 if (sav == NULL)
2430 return -2;
2431 idx = sav->sav_var_vals_idx;
2432 sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
Bram Moolenaar08251752021-01-11 21:20:18 +01002433 if (check_item_writable(sv, check_writable, name) == FAIL)
2434 return -2;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002435 return idx;
2436 }
2437
2438 // First look the name up in the hashtable.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002439 ht = &SCRIPT_VARS(sid);
2440 di = find_var_in_ht(ht, 0, name, TRUE);
2441 if (di == NULL)
2442 return -2;
2443
2444 // Now find the svar_T index in sn_var_vals.
2445 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2446 {
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02002447 sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002448 if (sv->sv_tv == &di->di_tv)
2449 {
Bram Moolenaar08251752021-01-11 21:20:18 +01002450 if (check_item_writable(sv, check_writable, name) == FAIL)
2451 return -2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002452 return idx;
2453 }
2454 }
2455 return -1;
2456}
2457
2458/*
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02002459 * Find "name" in imported items of the current script or in "cctx" if not
2460 * NULL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002461 */
2462 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002463find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002464{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002465 int idx;
2466
Bram Moolenaare3d46852020-08-29 13:39:17 +02002467 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02002468 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002469 if (cctx != NULL)
2470 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2471 {
2472 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2473 + idx;
2474
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002475 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2476 : STRLEN(import->imp_name) == len
2477 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002478 return import;
2479 }
2480
Bram Moolenaarefa94442020-08-08 22:16:00 +02002481 return find_imported_in_script(name, len, current_sctx.sc_sid);
2482}
2483
2484 imported_T *
2485find_imported_in_script(char_u *name, size_t len, int sid)
2486{
Bram Moolenaare3d46852020-08-29 13:39:17 +02002487 scriptitem_T *si;
Bram Moolenaarefa94442020-08-08 22:16:00 +02002488 int idx;
2489
Bram Moolenaare3d46852020-08-29 13:39:17 +02002490 if (!SCRIPT_ID_VALID(sid))
2491 return NULL;
2492 si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002493 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2494 {
2495 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2496
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002497 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2498 : STRLEN(import->imp_name) == len
2499 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002500 return import;
2501 }
2502 return NULL;
2503}
2504
2505/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002506 * Free all imported variables.
2507 */
2508 static void
2509free_imported(cctx_T *cctx)
2510{
2511 int idx;
2512
2513 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2514 {
2515 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2516
2517 vim_free(import->imp_name);
2518 }
2519 ga_clear(&cctx->ctx_imports);
2520}
2521
2522/*
Bram Moolenaar23c55272020-06-21 16:58:13 +02002523 * Return a pointer to the next line that isn't empty or only contains a
2524 * comment. Skips over white space.
2525 * Returns NULL if there is none.
2526 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002527 char_u *
2528peek_next_line_from_context(cctx_T *cctx)
Bram Moolenaar23c55272020-06-21 16:58:13 +02002529{
2530 int lnum = cctx->ctx_lnum;
2531
2532 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
2533 {
2534 char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002535 char_u *p;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002536
Bram Moolenaarba60cc42020-08-12 19:15:33 +02002537 // ignore NULLs inserted for continuation lines
2538 if (line != NULL)
2539 {
2540 p = skipwhite(line);
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01002541 if (vim9_bad_comment(p))
2542 return NULL;
Bram Moolenaarba60cc42020-08-12 19:15:33 +02002543 if (*p != NUL && !vim9_comment_start(p))
2544 return p;
2545 }
Bram Moolenaar23c55272020-06-21 16:58:13 +02002546 }
2547 return NULL;
2548}
2549
2550/*
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002551 * Called when checking for a following operator at "arg". When the rest of
2552 * the line is empty or only a comment, peek the next line. If there is a next
2553 * line return a pointer to it and set "nextp".
2554 * Otherwise skip over white space.
2555 */
2556 static char_u *
2557may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp)
2558{
2559 char_u *p = skipwhite(arg);
2560
2561 *nextp = NULL;
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002562 if (*p == NUL || (VIM_ISWHITE(*arg) && vim9_comment_start(p)))
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002563 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002564 *nextp = peek_next_line_from_context(cctx);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002565 if (*nextp != NULL)
2566 return *nextp;
2567 }
2568 return p;
2569}
2570
2571/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002572 * Get the next line of the function from "cctx".
Bram Moolenaar23c55272020-06-21 16:58:13 +02002573 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
Bram Moolenaare6085c52020-04-12 20:19:16 +02002574 * Returns NULL when at the end.
2575 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002576 char_u *
Bram Moolenaar23c55272020-06-21 16:58:13 +02002577next_line_from_context(cctx_T *cctx, int skip_comment)
Bram Moolenaare6085c52020-04-12 20:19:16 +02002578{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002579 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002580
2581 do
2582 {
2583 ++cctx->ctx_lnum;
2584 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002585 {
2586 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002587 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002588 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002589 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002590 cctx->ctx_line_start = line;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02002591 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002592 } while (line == NULL || *skipwhite(line) == NUL
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02002593 || (skip_comment && vim9_comment_start(skipwhite(line))));
Bram Moolenaare6085c52020-04-12 20:19:16 +02002594 return line;
2595}
2596
2597/*
Bram Moolenaar5afd0812021-01-03 18:33:13 +01002598 * Skip over white space at "whitep" and assign to "*arg".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002599 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002600 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002601 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2602 */
2603 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002604may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002605{
Bram Moolenaar5afd0812021-01-03 18:33:13 +01002606 *arg = skipwhite(whitep);
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01002607 if (vim9_bad_comment(*arg))
2608 return FAIL;
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002609 if (**arg == NUL || (VIM_ISWHITE(*whitep) && vim9_comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002610 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002611 char_u *next = next_line_from_context(cctx, TRUE);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002612
2613 if (next == NULL)
2614 return FAIL;
2615 *arg = skipwhite(next);
2616 }
2617 return OK;
2618}
2619
Bram Moolenaara7eedf32020-07-10 21:50:41 +02002620/*
2621 * Idem, and give an error when failed.
2622 */
2623 static int
2624may_get_next_line_error(char_u *whitep, char_u **arg, cctx_T *cctx)
2625{
2626 if (may_get_next_line(whitep, arg, cctx) == FAIL)
2627 {
Bram Moolenaar8ff16e02020-12-07 21:49:52 +01002628 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002629 emsg(_(e_line_incomplete));
Bram Moolenaara7eedf32020-07-10 21:50:41 +02002630 return FAIL;
2631 }
2632 return OK;
2633}
2634
2635
Bram Moolenaara5565e42020-05-09 15:44:01 +02002636// Structure passed between the compile_expr* functions to keep track of
2637// constants that have been parsed but for which no code was produced yet. If
2638// possible expressions on these constants are applied at compile time. If
2639// that is not possible, the code to push the constants needs to be generated
2640// before other instructions.
Bram Moolenaar1c747212020-05-09 18:28:34 +02002641// Using 50 should be more than enough of 5 levels of ().
2642#define PPSIZE 50
Bram Moolenaara5565e42020-05-09 15:44:01 +02002643typedef struct {
Bram Moolenaar1c747212020-05-09 18:28:34 +02002644 typval_T pp_tv[PPSIZE]; // stack of ppconst constants
Bram Moolenaara5565e42020-05-09 15:44:01 +02002645 int pp_used; // active entries in pp_tv[]
Bram Moolenaar334a8b42020-10-19 16:07:42 +02002646 int pp_is_const; // all generated code was constants, used for a
2647 // list or dict with constant members
Bram Moolenaara5565e42020-05-09 15:44:01 +02002648} ppconst_T;
2649
Bram Moolenaar334a8b42020-10-19 16:07:42 +02002650static int compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const);
Bram Moolenaar1c747212020-05-09 18:28:34 +02002651static int compile_expr0(char_u **arg, cctx_T *cctx);
2652static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2653
Bram Moolenaara5565e42020-05-09 15:44:01 +02002654/*
2655 * Generate a PUSH instruction for "tv".
2656 * "tv" will be consumed or cleared.
2657 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
2658 */
2659 static int
2660generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
2661{
2662 if (tv != NULL)
2663 {
2664 switch (tv->v_type)
2665 {
2666 case VAR_UNKNOWN:
2667 break;
2668 case VAR_BOOL:
2669 generate_PUSHBOOL(cctx, tv->vval.v_number);
2670 break;
2671 case VAR_SPECIAL:
2672 generate_PUSHSPEC(cctx, tv->vval.v_number);
2673 break;
2674 case VAR_NUMBER:
2675 generate_PUSHNR(cctx, tv->vval.v_number);
2676 break;
2677#ifdef FEAT_FLOAT
2678 case VAR_FLOAT:
2679 generate_PUSHF(cctx, tv->vval.v_float);
2680 break;
2681#endif
2682 case VAR_BLOB:
2683 generate_PUSHBLOB(cctx, tv->vval.v_blob);
2684 tv->vval.v_blob = NULL;
2685 break;
2686 case VAR_STRING:
2687 generate_PUSHS(cctx, tv->vval.v_string);
2688 tv->vval.v_string = NULL;
2689 break;
2690 default:
2691 iemsg("constant type not supported");
2692 clear_tv(tv);
2693 return FAIL;
2694 }
2695 tv->v_type = VAR_UNKNOWN;
2696 }
2697 return OK;
2698}
2699
2700/*
2701 * Generate code for any ppconst entries.
2702 */
2703 static int
2704generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
2705{
2706 int i;
2707 int ret = OK;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002708 int save_skip = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002709
Bram Moolenaar9b68c822020-06-18 19:31:08 +02002710 cctx->ctx_skip = SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002711 for (i = 0; i < ppconst->pp_used; ++i)
2712 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
2713 ret = FAIL;
2714 ppconst->pp_used = 0;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002715 cctx->ctx_skip = save_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002716 return ret;
2717}
2718
2719/*
2720 * Clear ppconst constants. Used when failing.
2721 */
2722 static void
2723clear_ppconst(ppconst_T *ppconst)
2724{
2725 int i;
2726
2727 for (i = 0; i < ppconst->pp_used; ++i)
2728 clear_tv(&ppconst->pp_tv[i]);
2729 ppconst->pp_used = 0;
2730}
2731
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002732/*
Bram Moolenaare42939a2021-04-05 17:11:17 +02002733 * Compile getting a member from a list/dict/string/blob. Stack has the
2734 * indexable value and the index.
2735 */
2736 static int
2737compile_member(int is_slice, cctx_T *cctx)
2738{
2739 type_T **typep;
2740 garray_T *stack = &cctx->ctx_type_stack;
2741 vartype_T vtype;
2742 type_T *valtype;
2743
2744 // We can index a list and a dict. If we don't know the type
2745 // we can use the index value type.
2746 // TODO: If we don't know use an instruction to figure it out at
2747 // runtime.
2748 typep = ((type_T **)stack->ga_data) + stack->ga_len
2749 - (is_slice ? 3 : 2);
2750 vtype = (*typep)->tt_type;
2751 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2752 // If the index is a string, the variable must be a Dict.
2753 if (*typep == &t_any && valtype == &t_string)
2754 vtype = VAR_DICT;
2755 if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB)
2756 {
2757 if (need_type(valtype, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
2758 return FAIL;
2759 if (is_slice)
2760 {
2761 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2];
2762 if (need_type(valtype, &t_number, -2, 0, cctx,
2763 FALSE, FALSE) == FAIL)
2764 return FAIL;
2765 }
2766 }
2767
2768 if (vtype == VAR_DICT)
2769 {
2770 if (is_slice)
2771 {
2772 emsg(_(e_cannot_slice_dictionary));
2773 return FAIL;
2774 }
2775 if ((*typep)->tt_type == VAR_DICT)
2776 {
2777 *typep = (*typep)->tt_member;
2778 if (*typep == &t_unknown)
2779 // empty dict was used
2780 *typep = &t_any;
2781 }
2782 else
2783 {
2784 if (need_type(*typep, &t_dict_any, -2, 0, cctx,
2785 FALSE, FALSE) == FAIL)
2786 return FAIL;
2787 *typep = &t_any;
2788 }
2789 if (may_generate_2STRING(-1, cctx) == FAIL)
2790 return FAIL;
2791 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
2792 return FAIL;
2793 }
2794 else if (vtype == VAR_STRING)
2795 {
2796 *typep = &t_string;
2797 if ((is_slice
2798 ? generate_instr_drop(cctx, ISN_STRSLICE, 2)
2799 : generate_instr_drop(cctx, ISN_STRINDEX, 1)) == FAIL)
2800 return FAIL;
2801 }
2802 else if (vtype == VAR_BLOB)
2803 {
Bram Moolenaarcfc30232021-04-11 20:26:34 +02002804 if (is_slice)
2805 {
2806 *typep = &t_blob;
2807 if (generate_instr_drop(cctx, ISN_BLOBSLICE, 2) == FAIL)
2808 return FAIL;
2809 }
2810 else
2811 {
2812 *typep = &t_number;
2813 if (generate_instr_drop(cctx, ISN_BLOBINDEX, 1) == FAIL)
2814 return FAIL;
2815 }
Bram Moolenaare42939a2021-04-05 17:11:17 +02002816 }
2817 else if (vtype == VAR_LIST || *typep == &t_any)
2818 {
2819 if (is_slice)
2820 {
2821 if (generate_instr_drop(cctx,
2822 vtype == VAR_LIST ? ISN_LISTSLICE : ISN_ANYSLICE,
2823 2) == FAIL)
2824 return FAIL;
2825 }
2826 else
2827 {
2828 if ((*typep)->tt_type == VAR_LIST)
2829 {
2830 *typep = (*typep)->tt_member;
2831 if (*typep == &t_unknown)
2832 // empty list was used
2833 *typep = &t_any;
2834 }
2835 if (generate_instr_drop(cctx,
2836 vtype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX, 1) == FAIL)
2837 return FAIL;
2838 }
2839 }
2840 else
2841 {
2842 emsg(_(e_string_list_dict_or_blob_required));
2843 return FAIL;
2844 }
2845 return OK;
2846}
2847
2848/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002849 * Generate an instruction to load script-local variable "name", without the
2850 * leading "s:".
2851 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002852 */
2853 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002854compile_load_scriptvar(
2855 cctx_T *cctx,
2856 char_u *name, // variable NUL terminated
2857 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002858 char_u **end, // end of variable
2859 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002860{
Bram Moolenaare3d46852020-08-29 13:39:17 +02002861 scriptitem_T *si;
2862 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002863 imported_T *import;
2864
Bram Moolenaare3d46852020-08-29 13:39:17 +02002865 if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
2866 return FAIL;
2867 si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar08251752021-01-11 21:20:18 +01002868 idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx);
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002869 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002870 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002871 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002872 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2873 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002874 }
2875 if (idx >= 0)
2876 {
2877 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2878
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002879 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002880 current_sctx.sc_sid, idx, sv->sv_type);
2881 return OK;
2882 }
2883
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002884 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002885 if (import != NULL)
2886 {
Bram Moolenaara6294952020-12-27 13:39:50 +01002887 if (import->imp_flags & IMP_FLAGS_STAR)
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002888 {
2889 char_u *p = skipwhite(*end);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002890 char_u *exp_name;
2891 int cc;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002892 ufunc_T *ufunc;
2893 type_T *type;
2894
2895 // Used "import * as Name", need to lookup the member.
2896 if (*p != '.')
2897 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002898 semsg(_(e_expected_dot_after_name_str), start);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002899 return FAIL;
2900 }
2901 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002902 if (VIM_ISWHITE(*p))
2903 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002904 emsg(_(e_no_white_space_allowed_after_dot));
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002905 return FAIL;
2906 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002907
Bram Moolenaar1c991142020-07-04 13:15:31 +02002908 // isolate one name
2909 exp_name = p;
2910 while (eval_isnamec(*p))
2911 ++p;
2912 cc = *p;
2913 *p = NUL;
2914
Bram Moolenaaredba7072021-03-13 21:14:18 +01002915 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
2916 cctx, TRUE);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002917 *p = cc;
2918 p = skipwhite(p);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002919 *end = p;
2920
Bram Moolenaar529fb5a2021-04-01 12:57:57 +02002921 if (idx < 0)
2922 {
2923 if (*p == '(' && ufunc != NULL)
2924 {
2925 generate_PUSHFUNC(cctx, ufunc->uf_name, import->imp_type);
2926 return OK;
2927 }
2928 return FAIL;
2929 }
2930
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002931 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2932 import->imp_sid,
2933 idx,
2934 type);
2935 }
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002936 else if (import->imp_funcname != NULL)
2937 generate_PUSHFUNC(cctx, import->imp_funcname, import->imp_type);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002938 else
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002939 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2940 import->imp_sid,
2941 import->imp_var_vals_idx,
2942 import->imp_type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002943 return OK;
2944 }
2945
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002946 if (error)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02002947 semsg(_(e_item_not_found_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002948 return FAIL;
2949}
2950
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002951 static int
2952generate_funcref(cctx_T *cctx, char_u *name)
2953{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002954 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002955
2956 if (ufunc == NULL)
2957 return FAIL;
2958
Bram Moolenaarb8070e32020-07-23 20:56:04 +02002959 // Need to compile any default values to get the argument types.
Bram Moolenaare5ea3462021-01-25 21:01:48 +01002960 if (func_needs_compiling(ufunc, PROFILING(ufunc))
2961 && compile_def_function(ufunc, TRUE, PROFILING(ufunc), NULL)
Bram Moolenaarb2049902021-01-24 12:53:53 +01002962 == FAIL)
2963 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002964 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002965}
2966
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002967/*
2968 * Compile a variable name into a load instruction.
2969 * "end" points to just after the name.
Bram Moolenaar0f769812020-09-12 18:32:34 +02002970 * "is_expr" is TRUE when evaluating an expression, might be a funcref.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002971 * When "error" is FALSE do not give an error when not found.
2972 */
2973 static int
Bram Moolenaar0f769812020-09-12 18:32:34 +02002974compile_load(
2975 char_u **arg,
2976 char_u *end_arg,
2977 cctx_T *cctx,
2978 int is_expr,
2979 int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002980{
2981 type_T *type;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002982 char_u *name = NULL;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002983 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002984 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002985 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002986
2987 if (*(*arg + 1) == ':')
2988 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002989 if (end <= *arg + 2)
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002990 {
2991 isntype_T isn_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002992
Bram Moolenaarfa596382021-04-07 21:58:16 +02002993 // load dictionary of namespace
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002994 switch (**arg)
2995 {
2996 case 'g': isn_type = ISN_LOADGDICT; break;
2997 case 'w': isn_type = ISN_LOADWDICT; break;
2998 case 't': isn_type = ISN_LOADTDICT; break;
2999 case 'b': isn_type = ISN_LOADBDICT; break;
3000 default:
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003001 semsg(_(e_namespace_not_supported_str), *arg);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003002 goto theend;
3003 }
3004 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
3005 goto theend;
3006 res = OK;
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01003007 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003008 else
3009 {
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003010 isntype_T isn_type = ISN_DROP;
3011
Bram Moolenaarfa596382021-04-07 21:58:16 +02003012 // load namespaced variable
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003013 name = vim_strnsave(*arg + 2, end - (*arg + 2));
3014 if (name == NULL)
3015 return FAIL;
3016
3017 switch (**arg)
3018 {
3019 case 'v': res = generate_LOADV(cctx, name, error);
3020 break;
Bram Moolenaarfa596382021-04-07 21:58:16 +02003021 case 's': if (is_expr && ASCII_ISUPPER(*name)
3022 && find_func(name, FALSE, cctx) != NULL)
3023 res = generate_funcref(cctx, name);
3024 else
3025 res = compile_load_scriptvar(cctx, name,
Bram Moolenaarca51cc02021-04-01 21:38:53 +02003026 NULL, &end, error);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003027 break;
Bram Moolenaar03290b82020-12-19 16:30:44 +01003028 case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
Bram Moolenaarfa596382021-04-07 21:58:16 +02003029 {
3030 if (is_expr && ASCII_ISUPPER(*name)
3031 && find_func(name, FALSE, cctx) != NULL)
3032 res = generate_funcref(cctx, name);
3033 else
3034 isn_type = ISN_LOADG;
3035 }
Bram Moolenaar03290b82020-12-19 16:30:44 +01003036 else
3037 {
3038 isn_type = ISN_LOADAUTO;
3039 vim_free(name);
3040 name = vim_strnsave(*arg, end - *arg);
3041 if (name == NULL)
3042 return FAIL;
3043 }
3044 break;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003045 case 'w': isn_type = ISN_LOADW; break;
3046 case 't': isn_type = ISN_LOADT; break;
3047 case 'b': isn_type = ISN_LOADB; break;
Bram Moolenaar918a4242020-12-06 14:37:08 +01003048 default: // cannot happen, just in case
3049 semsg(_(e_namespace_not_supported_str), *arg);
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003050 goto theend;
3051 }
3052 if (isn_type != ISN_DROP)
3053 {
3054 // Global, Buffer-local, Window-local and Tabpage-local
3055 // variables can be defined later, thus we don't check if it
Bram Moolenaarfa596382021-04-07 21:58:16 +02003056 // exists, give an error at runtime.
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02003057 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
3058 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003059 }
3060 }
3061 else
3062 {
3063 size_t len = end - *arg;
3064 int idx;
3065 int gen_load = FALSE;
Bram Moolenaarab360522021-01-10 14:02:28 +01003066 int gen_load_outer = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003067
3068 name = vim_strnsave(*arg, end - *arg);
3069 if (name == NULL)
3070 return FAIL;
3071
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02003072 if (arg_exists(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003073 {
Bram Moolenaarab360522021-01-10 14:02:28 +01003074 if (gen_load_outer == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02003075 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003076 }
3077 else
3078 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01003079 lvar_T lvar;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02003080
Bram Moolenaar709664c2020-12-12 14:33:41 +01003081 if (lookup_local(*arg, len, &lvar, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003082 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01003083 type = lvar.lv_type;
3084 idx = lvar.lv_idx;
Bram Moolenaarab360522021-01-10 14:02:28 +01003085 if (lvar.lv_from_outer != 0)
3086 gen_load_outer = lvar.lv_from_outer;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003087 else
3088 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003089 }
3090 else
3091 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003092 // "var" can be script-local even without using "s:" if it
Bram Moolenaar53900992020-08-22 19:02:02 +02003093 // already exists in a Vim9 script or when it's imported.
Bram Moolenaar15e5e532021-04-07 21:21:13 +02003094 if (script_var_exists(*arg, len, cctx) == OK
Bram Moolenaar53900992020-08-22 19:02:02 +02003095 || find_imported(name, 0, cctx) != NULL)
3096 res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003097
Bram Moolenaar0f769812020-09-12 18:32:34 +02003098 // When evaluating an expression and the name starts with an
Bram Moolenaarfa596382021-04-07 21:58:16 +02003099 // uppercase letter it can be a user defined function.
3100 // generate_funcref() will fail if the function can't be found.
3101 if (res == FAIL && is_expr && ASCII_ISUPPER(*name))
Bram Moolenaara5565e42020-05-09 15:44:01 +02003102 res = generate_funcref(cctx, name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003103 }
3104 }
3105 if (gen_load)
3106 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarab360522021-01-10 14:02:28 +01003107 if (gen_load_outer > 0)
Bram Moolenaarfd777482020-08-12 19:42:01 +02003108 {
Bram Moolenaarab360522021-01-10 14:02:28 +01003109 res = generate_LOADOUTER(cctx, idx, gen_load_outer, type);
Bram Moolenaarfd777482020-08-12 19:42:01 +02003110 cctx->ctx_outer_used = TRUE;
3111 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003112 }
3113
3114 *arg = end;
3115
3116theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01003117 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003118 semsg(_(e_variable_not_found_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003119 vim_free(name);
3120 return res;
3121}
3122
3123/*
3124 * Compile the argument expressions.
3125 * "arg" points to just after the "(" and is advanced to after the ")"
3126 */
3127 static int
3128compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
3129{
Bram Moolenaar2c330432020-04-13 14:41:35 +02003130 char_u *p = *arg;
3131 char_u *whitep = *arg;
Bram Moolenaar10e4f122020-09-20 22:43:52 +02003132 int must_end = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003133
Bram Moolenaare6085c52020-04-12 20:19:16 +02003134 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003135 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003136 if (may_get_next_line(whitep, &p, cctx) == FAIL)
3137 goto failret;
Bram Moolenaare6085c52020-04-12 20:19:16 +02003138 if (*p == ')')
3139 {
3140 *arg = p + 1;
3141 return OK;
3142 }
Bram Moolenaar10e4f122020-09-20 22:43:52 +02003143 if (must_end)
3144 {
3145 semsg(_(e_missing_comma_before_argument_str), p);
3146 return FAIL;
3147 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02003148
Bram Moolenaara5565e42020-05-09 15:44:01 +02003149 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003150 return FAIL;
3151 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003152
3153 if (*p != ',' && *skipwhite(p) == ',')
3154 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003155 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003156 p = skipwhite(p);
3157 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003158 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003159 {
3160 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02003161 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003162 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003163 }
Bram Moolenaar10e4f122020-09-20 22:43:52 +02003164 else
3165 must_end = TRUE;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003166 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003167 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003168 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003169failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02003170 emsg(_(e_missing_close));
3171 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003172}
3173
3174/*
3175 * Compile a function call: name(arg1, arg2)
3176 * "arg" points to "name", "arg + varlen" to the "(".
3177 * "argcount_init" is 1 for "value->method()"
3178 * Instructions:
3179 * EVAL arg1
3180 * EVAL arg2
3181 * BCALL / DCALL / UCALL
3182 */
3183 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003184compile_call(
3185 char_u **arg,
3186 size_t varlen,
3187 cctx_T *cctx,
3188 ppconst_T *ppconst,
3189 int argcount_init)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003190{
3191 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01003192 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003193 int argcount = argcount_init;
3194 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003195 char_u fname_buf[FLEN_FIXED + 1];
3196 char_u *tofree = NULL;
3197 int error = FCERR_NONE;
Bram Moolenaarb3a01942020-11-17 19:56:09 +01003198 ufunc_T *ufunc = NULL;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003199 int res = FAIL;
Bram Moolenaara1773442020-08-12 15:21:22 +02003200 int is_autoload;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003201
Bram Moolenaara5565e42020-05-09 15:44:01 +02003202 // we can evaluate "has('name')" at compile time
3203 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
3204 {
3205 char_u *s = skipwhite(*arg + varlen + 1);
3206 typval_T argvars[2];
3207
3208 argvars[0].v_type = VAR_UNKNOWN;
3209 if (*s == '"')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003210 (void)eval_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003211 else if (*s == '\'')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003212 (void)eval_lit_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003213 s = skipwhite(s);
Bram Moolenaar8cebd432020-11-08 12:49:47 +01003214 if (*s == ')' && argvars[0].v_type == VAR_STRING
3215 && !dynamic_feature(argvars[0].vval.v_string))
Bram Moolenaara5565e42020-05-09 15:44:01 +02003216 {
3217 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
3218
3219 *arg = s + 1;
3220 argvars[1].v_type = VAR_UNKNOWN;
3221 tv->v_type = VAR_NUMBER;
3222 tv->vval.v_number = 0;
3223 f_has(argvars, tv);
3224 clear_tv(&argvars[0]);
3225 ++ppconst->pp_used;
3226 return OK;
3227 }
Bram Moolenaar497f76b2020-05-09 16:44:22 +02003228 clear_tv(&argvars[0]);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003229 }
3230
3231 if (generate_ppconst(cctx, ppconst) == FAIL)
3232 return FAIL;
3233
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003234 if (varlen >= sizeof(namebuf))
3235 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003236 semsg(_(e_name_too_long_str), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003237 return FAIL;
3238 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003239 vim_strncpy(namebuf, *arg, varlen);
3240 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003241
3242 *arg = skipwhite(*arg + varlen + 1);
3243 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003244 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003245
Bram Moolenaar03290b82020-12-19 16:30:44 +01003246 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
Bram Moolenaara1773442020-08-12 15:21:22 +02003247 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003248 {
3249 int idx;
3250
3251 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003252 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003253 if (idx >= 0)
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003254 {
Bram Moolenaar3b690062021-02-01 20:14:51 +01003255 if (STRCMP(name, "flatten") == 0)
3256 {
3257 emsg(_(e_cannot_use_flatten_in_vim9_script));
3258 goto theend;
3259 }
3260
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003261 if (STRCMP(name, "add") == 0 && argcount == 2)
3262 {
3263 garray_T *stack = &cctx->ctx_type_stack;
3264 type_T *type = ((type_T **)stack->ga_data)[
3265 stack->ga_len - 2];
3266
Bram Moolenaare88c8e82020-11-01 17:03:37 +01003267 // add() can be compiled to instructions if we know the type
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003268 if (type->tt_type == VAR_LIST)
3269 {
3270 // inline "add(list, item)" so that the type can be checked
3271 res = generate_LISTAPPEND(cctx);
3272 idx = -1;
3273 }
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02003274 else if (type->tt_type == VAR_BLOB)
3275 {
3276 // inline "add(blob, nr)" so that the type can be checked
3277 res = generate_BLOBAPPEND(cctx);
3278 idx = -1;
3279 }
Bram Moolenaar1dcae592020-10-19 19:02:42 +02003280 }
3281
3282 if (idx >= 0)
3283 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
3284 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003285 else
3286 semsg(_(e_unknownfunc), namebuf);
3287 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003288 }
3289
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01003290 // An argument or local variable can be a function reference, this
3291 // overrules a function name.
Bram Moolenaar709664c2020-12-12 14:33:41 +01003292 if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01003293 && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003294 {
Bram Moolenaar52bf81c2020-11-17 18:50:44 +01003295 // If we can find the function by name generate the right call.
3296 // Skip global functions here, a local funcref takes precedence.
3297 ufunc = find_func(name, FALSE, cctx);
3298 if (ufunc != NULL && !func_is_global(ufunc))
3299 {
3300 res = generate_CALL(cctx, ufunc, argcount);
3301 goto theend;
3302 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003303 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003304
3305 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02003306 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaara1773442020-08-12 15:21:22 +02003307 // Not for eome#Func(), it will be loaded later.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003308 p = namebuf;
Bram Moolenaara1773442020-08-12 15:21:22 +02003309 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload
Bram Moolenaar0f769812020-09-12 18:32:34 +02003310 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003311 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003312 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003313 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003314
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003315 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003316 goto theend;
3317 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003318
Bram Moolenaar0f769812020-09-12 18:32:34 +02003319 // If we can find a global function by name generate the right call.
3320 if (ufunc != NULL)
3321 {
3322 res = generate_CALL(cctx, ufunc, argcount);
3323 goto theend;
3324 }
3325
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003326 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003327 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaara1773442020-08-12 15:21:22 +02003328 if (STRNCMP(namebuf, "g:", 2) == 0 || is_autoload)
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003329 res = generate_UCALL(cctx, name, argcount);
3330 else
3331 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003332
3333theend:
3334 vim_free(tofree);
3335 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003336}
3337
3338// like NAMESPACE_CHAR but with 'a' and 'l'.
3339#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
3340
3341/*
3342 * Find the end of a variable or function name. Unlike find_name_end() this
3343 * does not recognize magic braces.
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003344 * When "use_namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003345 * Return a pointer to just after the name. Equal to "arg" if there is no
3346 * valid name.
3347 */
Bram Moolenaar2bede172020-11-19 18:53:18 +01003348 char_u *
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003349to_name_end(char_u *arg, int use_namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003350{
3351 char_u *p;
3352
3353 // Quick check for valid starting character.
3354 if (!eval_isnamec1(*arg))
3355 return arg;
3356
3357 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
3358 // Include a namespace such as "s:var" and "v:var". But "n:" is not
3359 // and can be used in slice "[n:]".
3360 if (*p == ':' && (p != arg + 1
Bram Moolenaarbebaa0d2020-11-20 18:59:19 +01003361 || !use_namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003362 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
3363 break;
3364 return p;
3365}
3366
3367/*
3368 * Like to_name_end() but also skip over a list or dict constant.
Bram Moolenaar1c991142020-07-04 13:15:31 +02003369 * This intentionally does not handle line continuation.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003370 */
3371 char_u *
3372to_name_const_end(char_u *arg)
3373{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003374 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003375 typval_T rettv;
3376
3377 if (p == arg && *arg == '[')
3378 {
3379
3380 // Can be "[1, 2, 3]->Func()".
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003381 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003382 p = arg;
3383 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003384 return p;
3385}
3386
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003387/*
3388 * parse a list: [expr, expr]
3389 * "*arg" points to the '['.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003390 * ppconst->pp_is_const is set if all items are a constant.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003391 */
3392 static int
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003393compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003394{
3395 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003396 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003397 int count = 0;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003398 int is_const;
3399 int is_all_const = TRUE; // reset when non-const encountered
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003400
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003401 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003402 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003403 if (may_get_next_line(whitep, &p, cctx) == FAIL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01003404 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003405 semsg(_(e_list_end), *arg);
3406 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003407 }
Bram Moolenaardb199212020-08-12 18:01:53 +02003408 if (*p == ',')
3409 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003410 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
Bram Moolenaardb199212020-08-12 18:01:53 +02003411 return FAIL;
3412 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003413 if (*p == ']')
3414 {
3415 ++p;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003416 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01003417 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003418 if (compile_expr0_ext(&p, cctx, &is_const) == FAIL)
Bram Moolenaarc1f00662020-10-03 13:41:53 +02003419 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003420 if (!is_const)
3421 is_all_const = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003422 ++count;
3423 if (*p == ',')
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003424 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003425 ++p;
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003426 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
3427 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003428 semsg(_(e_white_space_required_after_str_str), ",", p - 1);
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003429 return FAIL;
3430 }
3431 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003432 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003433 p = skipwhite(p);
3434 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003435 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003436
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003437 ppconst->pp_is_const = is_all_const;
3438 return generate_NEWLIST(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003439}
3440
3441/*
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01003442 * Parse a lambda: "(arg, arg) => expr"
Bram Moolenaar7a6eaa02021-03-21 20:53:29 +01003443 * "*arg" points to the '('.
Bram Moolenaare462f522020-12-27 14:43:30 +01003444 * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003445 */
3446 static int
3447compile_lambda(char_u **arg, cctx_T *cctx)
3448{
Bram Moolenaare462f522020-12-27 14:43:30 +01003449 int r;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003450 typval_T rettv;
3451 ufunc_T *ufunc;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003452 evalarg_T evalarg;
3453
3454 CLEAR_FIELD(evalarg);
3455 evalarg.eval_flags = EVAL_EVALUATE;
3456 evalarg.eval_cctx = cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003457
3458 // Get the funcref in "rettv".
Bram Moolenaare462f522020-12-27 14:43:30 +01003459 r = get_lambda_tv(arg, &rettv, TRUE, &evalarg);
3460 if (r != OK)
Bram Moolenaar2ea79ad2020-10-18 23:32:13 +02003461 {
3462 clear_evalarg(&evalarg, NULL);
Bram Moolenaare462f522020-12-27 14:43:30 +01003463 return r;
Bram Moolenaar2ea79ad2020-10-18 23:32:13 +02003464 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01003465
Bram Moolenaar65c44152020-12-24 15:14:01 +01003466 // "rettv" will now be a partial referencing the function.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003467 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003468 ++ufunc->uf_refcount;
3469 clear_tv(&rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003470
Bram Moolenaar65c44152020-12-24 15:14:01 +01003471 // Compile the function into instructions.
Bram Moolenaare5ea3462021-01-25 21:01:48 +01003472 compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003473
Bram Moolenaar67da21a2021-03-21 22:12:34 +01003474 // evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
3475 // points into it. Point to the original line to avoid a dangling pointer.
3476 if (evalarg.eval_tofree_cmdline != NULL)
3477 {
3478 size_t off = *arg - evalarg.eval_tofree_cmdline;
3479
3480 *arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
3481 + off;
3482 }
3483
Bram Moolenaar8e2730a2020-07-08 22:01:49 +02003484 clear_evalarg(&evalarg, NULL);
3485
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02003486 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar5a849da2020-08-08 16:47:30 +02003487 {
3488 // The return type will now be known.
3489 set_function_type(ufunc);
3490
Bram Moolenaarfdeab652020-09-19 15:16:50 +02003491 // The function reference count will be 1. When the ISN_FUNCREF
3492 // instruction is deleted the reference count is decremented and the
3493 // function is freed.
Bram Moolenaar5a849da2020-08-08 16:47:30 +02003494 return generate_FUNCREF(cctx, ufunc);
3495 }
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003496
3497 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003498 return FAIL;
3499}
3500
3501/*
Bram Moolenaare0de1712020-12-02 17:36:54 +01003502 * parse a dict: {key: val, [key]: val}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003503 * "*arg" points to the '{'.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003504 * ppconst->pp_is_const is set if all item values are a constant.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003505 */
3506 static int
Bram Moolenaare0de1712020-12-02 17:36:54 +01003507compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003508{
3509 garray_T *instr = &cctx->ctx_instr;
3510 int count = 0;
3511 dict_T *d = dict_alloc();
3512 dictitem_T *item;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003513 char_u *whitep = *arg + 1;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003514 char_u *p;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003515 int is_const;
3516 int is_all_const = TRUE; // reset when non-const encountered
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003517
3518 if (d == NULL)
3519 return FAIL;
Bram Moolenaard62d87d2021-01-04 17:40:12 +01003520 if (generate_ppconst(cctx, ppconst) == FAIL)
3521 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003522 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003523 {
Bram Moolenaar2bede172020-11-19 18:53:18 +01003524 char_u *key = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003525
Bram Moolenaar23c55272020-06-21 16:58:13 +02003526 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003527 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003528 *arg = NULL;
3529 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003530 }
3531
3532 if (**arg == '}')
3533 break;
3534
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003535 if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003536 {
Bram Moolenaar2bede172020-11-19 18:53:18 +01003537 isn_T *isn;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003538
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003539 // {[expr]: value} uses an evaluated key.
Bram Moolenaare0de1712020-12-02 17:36:54 +01003540 *arg = skipwhite(*arg + 1);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003541 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003542 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003543 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01003544 if (isn->isn_type == ISN_PUSHNR)
3545 {
3546 char buf[NUMBUFLEN];
3547
3548 // Convert to string at compile time.
3549 vim_snprintf(buf, NUMBUFLEN, "%lld", isn->isn_arg.number);
3550 isn->isn_type = ISN_PUSHS;
3551 isn->isn_arg.string = vim_strsave((char_u *)buf);
3552 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003553 if (isn->isn_type == ISN_PUSHS)
3554 key = isn->isn_arg.string;
Bram Moolenaar2e5910b2021-02-03 17:41:24 +01003555 else if (may_generate_2STRING(-1, cctx) == FAIL)
3556 return FAIL;
Bram Moolenaare0de1712020-12-02 17:36:54 +01003557 *arg = skipwhite(*arg);
3558 if (**arg != ']')
Bram Moolenaar2bede172020-11-19 18:53:18 +01003559 {
Bram Moolenaare0de1712020-12-02 17:36:54 +01003560 emsg(_(e_missing_matching_bracket_after_dict_key));
3561 return FAIL;
Bram Moolenaar2bede172020-11-19 18:53:18 +01003562 }
Bram Moolenaare0de1712020-12-02 17:36:54 +01003563 ++*arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003564 }
Bram Moolenaarc5e6a712020-12-04 19:12:14 +01003565 else
3566 {
3567 // {"name": value},
3568 // {'name': value},
3569 // {name: value} use "name" as a literal key
3570 key = get_literal_key(arg);
3571 if (key == NULL)
3572 return FAIL;
3573 if (generate_PUSHS(cctx, key) == FAIL)
3574 return FAIL;
3575 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003576
3577 // Check for duplicate keys, if using string keys.
3578 if (key != NULL)
3579 {
3580 item = dict_find(d, key, -1);
3581 if (item != NULL)
3582 {
3583 semsg(_(e_duplicate_key), key);
3584 goto failret;
3585 }
3586 item = dictitem_alloc(key);
3587 if (item != NULL)
3588 {
3589 item->di_tv.v_type = VAR_UNKNOWN;
3590 item->di_tv.v_lock = 0;
3591 if (dict_add(d, item) == FAIL)
3592 dictitem_free(item);
3593 }
3594 }
3595
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003596 if (**arg != ':')
3597 {
Bram Moolenaar17a836c2020-08-12 17:35:58 +02003598 if (*skipwhite(*arg) == ':')
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003599 semsg(_(e_no_white_space_allowed_before_str_str), ":", *arg);
Bram Moolenaar17a836c2020-08-12 17:35:58 +02003600 else
3601 semsg(_(e_missing_dict_colon), *arg);
3602 return FAIL;
3603 }
3604 whitep = *arg + 1;
3605 if (!IS_WHITE_OR_NUL(*whitep))
3606 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003607 semsg(_(e_white_space_required_after_str_str), ":", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003608 return FAIL;
3609 }
3610
Bram Moolenaar23c55272020-06-21 16:58:13 +02003611 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003612 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003613 *arg = NULL;
3614 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003615 }
3616
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003617 if (compile_expr0_ext(arg, cctx, &is_const) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003618 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003619 if (!is_const)
3620 is_all_const = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003621 ++count;
3622
Bram Moolenaar2c330432020-04-13 14:41:35 +02003623 whitep = *arg;
Bram Moolenaar23c55272020-06-21 16:58:13 +02003624 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003625 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003626 *arg = NULL;
3627 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003628 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003629 if (**arg == '}')
3630 break;
3631 if (**arg != ',')
3632 {
3633 semsg(_(e_missing_dict_comma), *arg);
3634 goto failret;
3635 }
Bram Moolenaarc3d6e8a2020-08-12 18:34:28 +02003636 if (IS_WHITE_OR_NUL(*whitep))
3637 {
Bram Moolenaarba98fb52021-02-07 18:06:29 +01003638 semsg(_(e_no_white_space_allowed_before_str_str), ",", whitep);
Bram Moolenaarc3d6e8a2020-08-12 18:34:28 +02003639 return FAIL;
3640 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003641 whitep = *arg + 1;
Bram Moolenaar9a13e182020-10-19 21:45:07 +02003642 if (!IS_WHITE_OR_NUL(*whitep))
3643 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003644 semsg(_(e_white_space_required_after_str_str), ",", *arg);
Bram Moolenaar9a13e182020-10-19 21:45:07 +02003645 return FAIL;
3646 }
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01003647 *arg = skipwhite(whitep);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003648 }
3649
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003650 *arg = *arg + 1;
3651
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003652 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02003653 p = skipwhite(*arg);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003654 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003655 *arg += STRLEN(*arg);
3656
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003657 dict_unref(d);
Bram Moolenaar334a8b42020-10-19 16:07:42 +02003658 ppconst->pp_is_const = is_all_const;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003659 return generate_NEWDICT(cctx, count);
3660
3661failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003662 if (*arg == NULL)
Bram Moolenaar44aefff2020-10-05 19:23:59 +02003663 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003664 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar44aefff2020-10-05 19:23:59 +02003665 *arg = (char_u *)"";
3666 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003667 dict_unref(d);
3668 return FAIL;
3669}
3670
3671/*
3672 * Compile "&option".
3673 */
3674 static int
3675compile_get_option(char_u **arg, cctx_T *cctx)
3676{
3677 typval_T rettv;
3678 char_u *start = *arg;
3679 int ret;
3680
3681 // parse the option and get the current value to get the type.
3682 rettv.v_type = VAR_UNKNOWN;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003683 ret = eval_option(arg, &rettv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003684 if (ret == OK)
3685 {
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003686 // include the '&' in the name, eval_option() expects it.
Bram Moolenaard5ea8f02021-01-01 14:49:15 +01003687 char_u *name = vim_strnsave(start, *arg - start);
3688 type_T *type = rettv.v_type == VAR_BOOL ? &t_bool
3689 : rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003690
3691 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
3692 vim_free(name);
3693 }
3694 clear_tv(&rettv);
3695
3696 return ret;
3697}
3698
3699/*
3700 * Compile "$VAR".
3701 */
3702 static int
3703compile_get_env(char_u **arg, cctx_T *cctx)
3704{
3705 char_u *start = *arg;
3706 int len;
3707 int ret;
3708 char_u *name;
3709
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003710 ++*arg;
3711 len = get_env_len(arg);
3712 if (len == 0)
3713 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003714 semsg(_(e_syntax_error_at_str), start - 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003715 return FAIL;
3716 }
3717
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003718 // include the '$' in the name, eval_env_var() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003719 name = vim_strnsave(start, len + 1);
3720 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
3721 vim_free(name);
3722 return ret;
3723}
3724
3725/*
3726 * Compile "@r".
3727 */
3728 static int
3729compile_get_register(char_u **arg, cctx_T *cctx)
3730{
3731 int ret;
3732
3733 ++*arg;
3734 if (**arg == NUL)
3735 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02003736 semsg(_(e_syntax_error_at_str), *arg - 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003737 return FAIL;
3738 }
Bram Moolenaar7226e5b2020-08-02 17:33:26 +02003739 if (!valid_yank_reg(**arg, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003740 {
3741 emsg_invreg(**arg);
3742 return FAIL;
3743 }
3744 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3745 ++*arg;
3746 return ret;
3747}
3748
3749/*
3750 * Apply leading '!', '-' and '+' to constant "rettv".
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003751 * When "numeric_only" is TRUE do not apply '!'.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003752 */
3753 static int
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003754apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003755{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003756 char_u *p = *end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003757
3758 // this works from end to start
3759 while (p > start)
3760 {
3761 --p;
3762 if (*p == '-' || *p == '+')
3763 {
3764 // only '-' has an effect, for '+' we only check the type
3765#ifdef FEAT_FLOAT
3766 if (rettv->v_type == VAR_FLOAT)
3767 {
3768 if (*p == '-')
3769 rettv->vval.v_float = -rettv->vval.v_float;
3770 }
3771 else
3772#endif
3773 {
3774 varnumber_T val;
3775 int error = FALSE;
3776
3777 // tv_get_number_chk() accepts a string, but we don't want that
3778 // here
3779 if (check_not_string(rettv) == FAIL)
3780 return FAIL;
3781 val = tv_get_number_chk(rettv, &error);
3782 clear_tv(rettv);
3783 if (error)
3784 return FAIL;
3785 if (*p == '-')
3786 val = -val;
3787 rettv->v_type = VAR_NUMBER;
3788 rettv->vval.v_number = val;
3789 }
3790 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003791 else if (numeric_only)
3792 {
3793 ++p;
3794 break;
3795 }
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003796 else if (*p == '!')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003797 {
3798 int v = tv2bool(rettv);
3799
3800 // '!' is permissive in the type.
3801 clear_tv(rettv);
3802 rettv->v_type = VAR_BOOL;
3803 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3804 }
3805 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003806 *end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003807 return OK;
3808}
3809
3810/*
3811 * Recognize v: variables that are constants and set "rettv".
3812 */
3813 static void
3814get_vim_constant(char_u **arg, typval_T *rettv)
3815{
3816 if (STRNCMP(*arg, "v:true", 6) == 0)
3817 {
3818 rettv->v_type = VAR_BOOL;
3819 rettv->vval.v_number = VVAL_TRUE;
3820 *arg += 6;
3821 }
3822 else if (STRNCMP(*arg, "v:false", 7) == 0)
3823 {
3824 rettv->v_type = VAR_BOOL;
3825 rettv->vval.v_number = VVAL_FALSE;
3826 *arg += 7;
3827 }
3828 else if (STRNCMP(*arg, "v:null", 6) == 0)
3829 {
3830 rettv->v_type = VAR_SPECIAL;
3831 rettv->vval.v_number = VVAL_NULL;
3832 *arg += 6;
3833 }
3834 else if (STRNCMP(*arg, "v:none", 6) == 0)
3835 {
3836 rettv->v_type = VAR_SPECIAL;
3837 rettv->vval.v_number = VVAL_NONE;
3838 *arg += 6;
3839 }
3840}
3841
Bram Moolenaar657137c2021-01-09 15:45:23 +01003842 exprtype_T
Bram Moolenaar61a89812020-05-07 16:58:17 +02003843get_compare_type(char_u *p, int *len, int *type_is)
3844{
Bram Moolenaar657137c2021-01-09 15:45:23 +01003845 exprtype_T type = EXPR_UNKNOWN;
Bram Moolenaar61a89812020-05-07 16:58:17 +02003846 int i;
3847
3848 switch (p[0])
3849 {
3850 case '=': if (p[1] == '=')
3851 type = EXPR_EQUAL;
3852 else if (p[1] == '~')
3853 type = EXPR_MATCH;
3854 break;
3855 case '!': if (p[1] == '=')
3856 type = EXPR_NEQUAL;
3857 else if (p[1] == '~')
3858 type = EXPR_NOMATCH;
3859 break;
3860 case '>': if (p[1] != '=')
3861 {
3862 type = EXPR_GREATER;
3863 *len = 1;
3864 }
3865 else
3866 type = EXPR_GEQUAL;
3867 break;
3868 case '<': if (p[1] != '=')
3869 {
3870 type = EXPR_SMALLER;
3871 *len = 1;
3872 }
3873 else
3874 type = EXPR_SEQUAL;
3875 break;
3876 case 'i': if (p[1] == 's')
3877 {
3878 // "is" and "isnot"; but not a prefix of a name
3879 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3880 *len = 5;
3881 i = p[*len];
3882 if (!isalnum(i) && i != '_')
3883 {
3884 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3885 *type_is = TRUE;
3886 }
3887 }
3888 break;
3889 }
3890 return type;
3891}
3892
3893/*
Bram Moolenaar7e368202020-12-25 21:56:57 +01003894 * Skip over an expression, ignoring most errors.
3895 */
3896 static void
3897skip_expr_cctx(char_u **arg, cctx_T *cctx)
3898{
3899 evalarg_T evalarg;
3900
3901 CLEAR_FIELD(evalarg);
3902 evalarg.eval_cctx = cctx;
3903 skip_expr(arg, &evalarg);
3904}
3905
3906/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003907 * Compile code to apply '-', '+' and '!'.
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003908 * When "numeric_only" is TRUE do not apply '!'.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003909 */
3910 static int
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003911compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003912{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003913 char_u *p = *end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003914
3915 // this works from end to start
3916 while (p > start)
3917 {
3918 --p;
Bram Moolenaar79cdf802020-11-18 17:39:05 +01003919 while (VIM_ISWHITE(*p))
3920 --p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003921 if (*p == '-' || *p == '+')
3922 {
3923 int negate = *p == '-';
3924 isn_T *isn;
3925
3926 // TODO: check type
3927 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3928 {
3929 --p;
3930 if (*p == '-')
3931 negate = !negate;
3932 }
3933 // only '-' has an effect, for '+' we only check the type
3934 if (negate)
3935 isn = generate_instr(cctx, ISN_NEGATENR);
3936 else
3937 isn = generate_instr(cctx, ISN_CHECKNR);
3938 if (isn == NULL)
3939 return FAIL;
3940 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003941 else if (numeric_only)
3942 {
3943 ++p;
3944 break;
3945 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003946 else
3947 {
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003948 int invert = *p == '!';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003949
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003950 while (p > start && (p[-1] == '!' || VIM_ISWHITE(p[-1])))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003951 {
Bram Moolenaar27491cd2020-10-15 21:54:56 +02003952 if (p[-1] == '!')
3953 invert = !invert;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003954 --p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003955 }
3956 if (generate_2BOOL(cctx, invert) == FAIL)
3957 return FAIL;
3958 }
3959 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02003960 *end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003961 return OK;
3962}
3963
3964/*
Bram Moolenaar7e368202020-12-25 21:56:57 +01003965 * Compile "(expression)": recursive!
3966 * Return FAIL/OK.
3967 */
3968 static int
3969compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
3970{
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003971 int ret;
Bram Moolenaar24156692021-01-14 20:35:49 +01003972 char_u *p = *arg + 1;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003973
Bram Moolenaar24156692021-01-14 20:35:49 +01003974 if (may_get_next_line_error(p, arg, cctx) == FAIL)
3975 return FAIL;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003976 if (ppconst->pp_used <= PPSIZE - 10)
3977 {
3978 ret = compile_expr1(arg, cctx, ppconst);
3979 }
3980 else
3981 {
3982 // Not enough space in ppconst, flush constants.
3983 if (generate_ppconst(cctx, ppconst) == FAIL)
3984 return FAIL;
3985 ret = compile_expr0(arg, cctx);
3986 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01003987 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
3988 return FAIL;
Bram Moolenaar7e368202020-12-25 21:56:57 +01003989 if (**arg == ')')
3990 ++*arg;
3991 else if (ret == OK)
3992 {
3993 emsg(_(e_missing_close));
3994 ret = FAIL;
3995 }
3996 return ret;
3997}
3998
3999/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004000 * Compile whatever comes after "name" or "name()".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004001 * Advances "*arg" only when something was recognized.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004002 */
4003 static int
4004compile_subscript(
4005 char_u **arg,
4006 cctx_T *cctx,
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004007 char_u *start_leader,
4008 char_u **end_leader,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004009 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004010{
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004011 char_u *name_start = *end_leader;
4012
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004013 for (;;)
4014 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02004015 char_u *p = skipwhite(*arg);
4016
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02004017 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
Bram Moolenaar23c55272020-06-21 16:58:13 +02004018 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004019 char_u *next = peek_next_line_from_context(cctx);
Bram Moolenaar23c55272020-06-21 16:58:13 +02004020
4021 // If a following line starts with "->{" or "->X" advance to that
4022 // line, so that a line break before "->" is allowed.
Bram Moolenaara7eedf32020-07-10 21:50:41 +02004023 // Also if a following line starts with ".x".
4024 if (next != NULL &&
4025 ((next[0] == '-' && next[1] == '>'
4026 && (next[2] == '{' || ASCII_ISALPHA(next[2])))
Bram Moolenaarb13ab992020-07-27 21:43:28 +02004027 || (next[0] == '.' && eval_isdictc(next[1]))))
Bram Moolenaar23c55272020-06-21 16:58:13 +02004028 {
4029 next = next_line_from_context(cctx, TRUE);
4030 if (next == NULL)
4031 return FAIL;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004032 *arg = next;
4033 p = skipwhite(*arg);
Bram Moolenaar23c55272020-06-21 16:58:13 +02004034 }
4035 }
4036
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01004037 // Do not skip over white space to find the "(", "execute 'x' ()" is
Bram Moolenaar2d6b20d2020-07-25 19:30:59 +02004038 // not a function call.
4039 if (**arg == '(')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004040 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02004041 garray_T *stack = &cctx->ctx_type_stack;
4042 type_T *type;
4043 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004044
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004045 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004046 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004047 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004048
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004049 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02004050 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4051
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004052 *arg = skipwhite(p + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004053 if (compile_arguments(arg, cctx, &argcount) == FAIL)
4054 return FAIL;
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004055 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004056 return FAIL;
4057 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004058 else if (*p == '-' && p[1] == '>')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004059 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02004060 char_u *pstart = p;
4061
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004062 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004063 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004064 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004065
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004066 // something->method()
4067 // Apply the '!', '-' and '+' first:
4068 // -1.0->func() works like (-1.0)->func()
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004069 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004070 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004071
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004072 p += 2;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004073 *arg = skipwhite(p);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02004074 // No line break supported right after "->".
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01004075 if (**arg == '(')
Bram Moolenaar65c44152020-12-24 15:14:01 +01004076 {
Bram Moolenaar7e368202020-12-25 21:56:57 +01004077 int argcount = 1;
Bram Moolenaar2927c072021-04-05 19:41:21 +02004078 garray_T *stack = &cctx->ctx_type_stack;
4079 int type_idx_start = stack->ga_len;
Bram Moolenaar7e368202020-12-25 21:56:57 +01004080 type_T *type;
Bram Moolenaar2927c072021-04-05 19:41:21 +02004081 int expr_isn_start = cctx->ctx_instr.ga_len;
4082 int expr_isn_end;
4083 int arg_isn_count;
Bram Moolenaar7e368202020-12-25 21:56:57 +01004084
4085 // Funcref call: list->(Refs[2])(arg)
4086 // or lambda: list->((arg) => expr)(arg)
Bram Moolenaar2927c072021-04-05 19:41:21 +02004087 //
4088 // Fist compile the function expression.
4089 if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
Bram Moolenaar7e368202020-12-25 21:56:57 +01004090 return FAIL;
Bram Moolenaar2927c072021-04-05 19:41:21 +02004091
4092 // Remember the next instruction index, where the instructions
4093 // for arguments are being written.
4094 expr_isn_end = cctx->ctx_instr.ga_len;
4095
4096 // Compile the arguments.
Bram Moolenaar7e368202020-12-25 21:56:57 +01004097 if (**arg != '(')
4098 {
Bram Moolenaar2949cfd2020-12-31 21:28:47 +01004099 if (*skipwhite(*arg) == '(')
4100 emsg(_(e_nowhitespace));
4101 else
4102 semsg(_(e_missing_paren), *arg);
Bram Moolenaar7e368202020-12-25 21:56:57 +01004103 return FAIL;
4104 }
Bram Moolenaar7e368202020-12-25 21:56:57 +01004105 *arg = skipwhite(*arg + 1);
4106 if (compile_arguments(arg, cctx, &argcount) == FAIL)
4107 return FAIL;
4108
Bram Moolenaar2927c072021-04-05 19:41:21 +02004109 // Move the instructions for the arguments to before the
4110 // instructions of the expression and move the type of the
4111 // expression after the argument types. This is what ISN_PCALL
4112 // expects.
Bram Moolenaar7e368202020-12-25 21:56:57 +01004113 stack = &cctx->ctx_type_stack;
Bram Moolenaar2927c072021-04-05 19:41:21 +02004114 arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end;
4115 if (arg_isn_count > 0)
4116 {
4117 int expr_isn_count = expr_isn_end - expr_isn_start;
4118 isn_T *isn = ALLOC_MULT(isn_T, expr_isn_count);
4119
4120 if (isn == NULL)
4121 return FAIL;
4122 mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data)
4123 + expr_isn_start,
4124 sizeof(isn_T) * expr_isn_count);
4125 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
4126 + expr_isn_start,
4127 ((isn_T *)cctx->ctx_instr.ga_data) + expr_isn_end,
4128 sizeof(isn_T) * arg_isn_count);
4129 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
4130 + expr_isn_start + arg_isn_count,
4131 isn, sizeof(isn_T) * expr_isn_count);
4132 vim_free(isn);
4133
4134 type = ((type_T **)stack->ga_data)[type_idx_start];
4135 mch_memmove(((type_T **)stack->ga_data) + type_idx_start,
4136 ((type_T **)stack->ga_data) + type_idx_start + 1,
4137 sizeof(type_T *)
4138 * (stack->ga_len - type_idx_start - 1));
4139 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
4140 }
4141
Bram Moolenaar7e368202020-12-25 21:56:57 +01004142 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4143 if (generate_PCALL(cctx, argcount,
4144 (char_u *)"[expression]", type, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004145 return FAIL;
4146 }
4147 else
4148 {
4149 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02004150 p = *arg;
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02004151 if (!eval_isnamec1(*p))
4152 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02004153 semsg(_(e_trailing_arg), pstart);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02004154 return FAIL;
4155 }
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02004156 if (ASCII_ISALPHA(*p) && p[1] == ':')
4157 p += 2;
Bram Moolenaarc5da1fb2020-08-05 15:43:44 +02004158 for ( ; eval_isnamec(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004159 ;
4160 if (*p != '(')
4161 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02004162 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004163 return FAIL;
4164 }
4165 // TODO: base value may not be the first argument
Bram Moolenaara5565e42020-05-09 15:44:01 +02004166 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004167 return FAIL;
4168 }
4169 }
Bram Moolenaarbadd8482020-07-31 22:38:17 +02004170 else if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004171 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004172 int is_slice = FALSE;
Bram Moolenaarb13af502020-02-17 21:12:08 +01004173
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004174 // list index: list[123]
Bram Moolenaara6e67e42020-05-15 23:36:40 +02004175 // dict member: dict[key]
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02004176 // string index: text[123]
Bram Moolenaarcfc30232021-04-11 20:26:34 +02004177 // blob index: blob[123]
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004178 // TODO: more arguments
4179 // TODO: recognize list or dict at runtime
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004180 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004181 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004182 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004183
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004184 ++p;
Bram Moolenaara7eedf32020-07-10 21:50:41 +02004185 if (may_get_next_line_error(p, arg, cctx) == FAIL)
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004186 return FAIL;
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004187 if (**arg == ':')
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004188 {
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004189 // missing first index is equal to zero
4190 generate_PUSHNR(cctx, 0);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004191 }
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004192 else
4193 {
4194 if (compile_expr0(arg, cctx) == FAIL)
4195 return FAIL;
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004196 if (**arg == ':')
4197 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004198 semsg(_(e_white_space_required_before_and_after_str_at_str),
4199 ":", *arg);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004200 return FAIL;
4201 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004202 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004203 return FAIL;
4204 *arg = skipwhite(*arg);
4205 }
4206 if (**arg == ':')
4207 {
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004208 is_slice = TRUE;
4209 ++*arg;
4210 if (!IS_WHITE_OR_NUL(**arg) && **arg != ']')
4211 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004212 semsg(_(e_white_space_required_before_and_after_str_at_str),
4213 ":", *arg);
Bram Moolenaarde4f95b2020-12-30 20:39:21 +01004214 return FAIL;
4215 }
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004216 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004217 return FAIL;
4218 if (**arg == ']')
4219 // missing second index is equal to end of string
4220 generate_PUSHNR(cctx, -1);
4221 else
4222 {
4223 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar918a4242020-12-06 14:37:08 +01004224 return FAIL;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004225 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004226 return FAIL;
4227 *arg = skipwhite(*arg);
4228 }
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004229 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004230
4231 if (**arg != ']')
4232 {
4233 emsg(_(e_missbrac));
4234 return FAIL;
4235 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01004236 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004237
Bram Moolenaare42939a2021-04-05 17:11:17 +02004238 if (compile_member(is_slice, cctx) == FAIL)
Bram Moolenaar11107ba2020-08-15 21:10:16 +02004239 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004240 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004241 else if (*p == '.' && p[1] != '.')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004242 {
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004243 // dictionary member: dict.name
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004244 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004245 return FAIL;
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004246 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004247
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02004248 *arg = p + 1;
Bram Moolenaar90193e62021-04-04 20:49:50 +02004249 if (IS_WHITE_OR_NUL(**arg))
Bram Moolenaarc1f00662020-10-03 13:41:53 +02004250 {
4251 emsg(_(e_missing_name_after_dot));
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004252 return FAIL;
Bram Moolenaarc1f00662020-10-03 13:41:53 +02004253 }
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02004254 p = *arg;
Bram Moolenaarb13ab992020-07-27 21:43:28 +02004255 if (eval_isdictc(*p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004256 while (eval_isnamec(*p))
4257 MB_PTR_ADV(p);
4258 if (p == *arg)
4259 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004260 semsg(_(e_syntax_error_at_str), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004261 return FAIL;
4262 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004263 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004264 return FAIL;
4265 *arg = p;
4266 }
4267 else
4268 break;
4269 }
4270
4271 // TODO - see handle_subscript():
4272 // Turn "dict.Func" into a partial for "Func" bound to "dict".
4273 // Don't do this when "Func" is already a partial that was bound
4274 // explicitly (pt_auto is FALSE).
4275
4276 return OK;
4277}
4278
4279/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004280 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
4281 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004282 *
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004283 * If the value is a constant "ppconst->pp_used" will be non-zero.
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004284 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004285 *
4286 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004287 */
4288
4289/*
4290 * number number constant
4291 * 0zFFFFFFFF Blob constant
4292 * "string" string constant
4293 * 'string' literal string constant
4294 * &option-name option value
4295 * @r register contents
4296 * identifier variable value
4297 * function() function call
4298 * $VAR environment variable
4299 * (expression) nested expression
4300 * [expr, expr] List
Bram Moolenaare0de1712020-12-02 17:36:54 +01004301 * {key: val, [key]: val} Dictionary
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004302 *
4303 * Also handle:
4304 * ! in front logical NOT
4305 * - in front unary minus
4306 * + in front unary plus (ignored)
4307 * trailing (arg) funcref/partial call
4308 * trailing [] subscript in String or List
4309 * trailing .name entry in Dictionary
4310 * trailing ->name() method call
4311 */
4312 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004313compile_expr7(
4314 char_u **arg,
4315 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004316 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004317{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004318 char_u *start_leader, *end_leader;
4319 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004320 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02004321 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004322
Bram Moolenaar334a8b42020-10-19 16:07:42 +02004323 ppconst->pp_is_const = FALSE;
4324
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004325 /*
4326 * Skip '!', '-' and '+' characters. They are handled later.
4327 */
4328 start_leader = *arg;
Bram Moolenaarb23279d2021-01-05 22:08:20 +01004329 if (eval_leader(arg, TRUE) == FAIL)
4330 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004331 end_leader = *arg;
4332
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004333 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004334 switch (**arg)
4335 {
4336 /*
4337 * Number constant.
4338 */
4339 case '0': // also for blob starting with 0z
4340 case '1':
4341 case '2':
4342 case '3':
4343 case '4':
4344 case '5':
4345 case '6':
4346 case '7':
4347 case '8':
4348 case '9':
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004349 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004350 return FAIL;
Bram Moolenaar4301a722020-08-11 20:51:08 +02004351 // Apply "-" and "+" just before the number now, right to
4352 // left. Matters especially when "->" follows. Stops at
4353 // '!'.
4354 if (apply_leader(rettv, TRUE,
4355 start_leader, &end_leader) == FAIL)
4356 {
4357 clear_tv(rettv);
4358 return FAIL;
4359 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004360 break;
4361
4362 /*
4363 * String constant: "string".
4364 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004365 case '"': if (eval_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004366 return FAIL;
4367 break;
4368
4369 /*
4370 * Literal string constant: 'str''ing'.
4371 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004372 case '\'': if (eval_lit_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004373 return FAIL;
4374 break;
4375
4376 /*
4377 * Constant Vim variable.
4378 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004379 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004380 ret = NOTDONE;
4381 break;
4382
4383 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004384 * "true" constant
4385 */
4386 case 't': if (STRNCMP(*arg, "true", 4) == 0
4387 && !eval_isnamec((*arg)[4]))
4388 {
4389 *arg += 4;
4390 rettv->v_type = VAR_BOOL;
4391 rettv->vval.v_number = VVAL_TRUE;
4392 }
4393 else
4394 ret = NOTDONE;
4395 break;
4396
4397 /*
4398 * "false" constant
4399 */
4400 case 'f': if (STRNCMP(*arg, "false", 5) == 0
4401 && !eval_isnamec((*arg)[5]))
4402 {
4403 *arg += 5;
4404 rettv->v_type = VAR_BOOL;
4405 rettv->vval.v_number = VVAL_FALSE;
4406 }
4407 else
4408 ret = NOTDONE;
4409 break;
4410
4411 /*
Bram Moolenaar67977822021-01-03 21:53:53 +01004412 * "null" constant
4413 */
4414 case 'n': if (STRNCMP(*arg, "null", 4) == 0
Bram Moolenaarc23555d2021-03-10 19:04:07 +01004415 && !eval_isnamec((*arg)[4]))
Bram Moolenaar67977822021-01-03 21:53:53 +01004416 {
4417 *arg += 4;
4418 rettv->v_type = VAR_SPECIAL;
4419 rettv->vval.v_number = VVAL_NULL;
4420 }
4421 else
4422 ret = NOTDONE;
4423 break;
4424
4425 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004426 * List: [expr, expr]
4427 */
Bram Moolenaare507ff12021-01-31 21:47:42 +01004428 case '[': if (generate_ppconst(cctx, ppconst) == FAIL)
4429 return FAIL;
4430 ret = compile_list(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004431 break;
4432
4433 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004434 * Dictionary: {'key': val, 'key': val}
4435 */
Bram Moolenaare507ff12021-01-31 21:47:42 +01004436 case '{': if (generate_ppconst(cctx, ppconst) == FAIL)
4437 return FAIL;
4438 ret = compile_dict(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004439 break;
4440
4441 /*
4442 * Option value: &name
4443 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004444 case '&': if (generate_ppconst(cctx, ppconst) == FAIL)
4445 return FAIL;
4446 ret = compile_get_option(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004447 break;
4448
4449 /*
4450 * Environment variable: $VAR.
4451 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004452 case '$': if (generate_ppconst(cctx, ppconst) == FAIL)
4453 return FAIL;
4454 ret = compile_get_env(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004455 break;
4456
4457 /*
4458 * Register contents: @r.
4459 */
Bram Moolenaar3fc71282020-08-21 20:43:17 +02004460 case '@': if (generate_ppconst(cctx, ppconst) == FAIL)
4461 return FAIL;
4462 ret = compile_get_register(arg, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004463 break;
4464 /*
4465 * nested expression: (expression).
Bram Moolenaar65c44152020-12-24 15:14:01 +01004466 * lambda: (arg, arg) => expr
4467 * funcref: (arg, arg) => { statement }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004468 */
Bram Moolenaare462f522020-12-27 14:43:30 +01004469 case '(': // if compile_lambda returns NOTDONE then it must be (expr)
4470 ret = compile_lambda(arg, cctx);
4471 if (ret == NOTDONE)
Bram Moolenaar7e368202020-12-25 21:56:57 +01004472 ret = compile_parenthesis(arg, cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004473 break;
4474
4475 default: ret = NOTDONE;
4476 break;
4477 }
4478 if (ret == FAIL)
4479 return FAIL;
4480
Bram Moolenaar1c747212020-05-09 18:28:34 +02004481 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004482 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004483 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004484 clear_tv(rettv);
4485 else
4486 // A constant expression can possibly be handled compile time,
4487 // return the value instead of generating code.
4488 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004489 }
4490 else if (ret == NOTDONE)
4491 {
4492 char_u *p;
4493 int r;
4494
4495 if (!eval_isnamec1(**arg))
4496 {
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01004497 if (!vim9_bad_comment(*arg))
4498 {
4499 if (ends_excmd(*skipwhite(*arg)))
4500 semsg(_(e_empty_expression_str), *arg);
4501 else
4502 semsg(_(e_name_expected_str), *arg);
4503 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004504 return FAIL;
4505 }
4506
4507 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01004508 p = to_name_end(*arg, TRUE);
Bram Moolenaar962c43b2021-04-10 17:18:09 +02004509 if (p - *arg == (size_t)1 && **arg == '_')
4510 {
4511 emsg(_(e_cannot_use_underscore_here));
4512 return FAIL;
4513 }
4514
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004515 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02004516 {
4517 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
4518 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004519 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02004520 {
4521 if (generate_ppconst(cctx, ppconst) == FAIL)
4522 return FAIL;
Bram Moolenaar0f769812020-09-12 18:32:34 +02004523 r = compile_load(arg, p, cctx, TRUE, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004524 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004525 if (r == FAIL)
4526 return FAIL;
4527 }
4528
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004529 // Handle following "[]", ".member", etc.
4530 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004531 if (compile_subscript(arg, cctx, start_leader, &end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02004532 ppconst) == FAIL)
4533 return FAIL;
4534 if (ppconst->pp_used > 0)
4535 {
4536 // apply the '!', '-' and '+' before the constant
4537 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004538 if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004539 return FAIL;
4540 return OK;
4541 }
Bram Moolenaar59eccb92020-08-10 23:09:37 +02004542 if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004543 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004544 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004545}
4546
4547/*
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004548 * Give the "white on both sides" error, taking the operator from "p[len]".
4549 */
4550 void
4551error_white_both(char_u *op, int len)
4552{
4553 char_u buf[10];
4554
4555 vim_strncpy(buf, op, len);
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004556 semsg(_(e_white_space_required_before_and_after_str_at_str), buf, op);
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004557}
4558
4559/*
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004560 * <type>expr7: runtime type check / conversion
4561 */
4562 static int
4563compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
4564{
4565 type_T *want_type = NULL;
4566
4567 // Recognize <type>
4568 if (**arg == '<' && eval_isnamec1((*arg)[1]))
4569 {
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004570 ++*arg;
Bram Moolenaar9e68c322020-12-25 12:38:04 +01004571 want_type = parse_type(arg, cctx->ctx_type_list, TRUE);
4572 if (want_type == NULL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004573 return FAIL;
4574
4575 if (**arg != '>')
4576 {
4577 if (*skipwhite(*arg) == '>')
Bram Moolenaarba98fb52021-02-07 18:06:29 +01004578 semsg(_(e_no_white_space_allowed_before_str_str), ">", *arg);
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004579 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02004580 emsg(_(e_missing_gt));
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004581 return FAIL;
4582 }
4583 ++*arg;
Bram Moolenaar5afd0812021-01-03 18:33:13 +01004584 if (may_get_next_line_error(*arg, arg, cctx) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004585 return FAIL;
4586 }
4587
4588 if (compile_expr7(arg, cctx, ppconst) == FAIL)
4589 return FAIL;
4590
4591 if (want_type != NULL)
4592 {
4593 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaard1103582020-08-14 22:44:25 +02004594 type_T *actual;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01004595 where_T where;
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004596
Bram Moolenaard1103582020-08-14 22:44:25 +02004597 generate_ppconst(cctx, ppconst);
4598 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarf785aa12021-02-11 21:19:34 +01004599 where.wt_index = 0;
4600 where.wt_variable = FALSE;
4601 if (check_type(want_type, actual, FALSE, where) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004602 {
Bram Moolenaar351ead02021-01-16 16:07:01 +01004603 if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004604 return FAIL;
4605 }
4606 }
4607
4608 return OK;
4609}
4610
4611/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004612 * * number multiplication
4613 * / number division
4614 * % number modulo
4615 */
4616 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004617compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004618{
4619 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004620 char_u *next;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004621 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004622
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004623 // get the first expression
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004624 if (compile_expr7t(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004625 return FAIL;
4626
4627 /*
4628 * Repeat computing, until no "*", "/" or "%" is following.
4629 */
4630 for (;;)
4631 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004632 op = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004633 if (*op != '*' && *op != '/' && *op != '%')
4634 break;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004635 if (next != NULL)
4636 {
4637 *arg = next_line_from_context(cctx, TRUE);
4638 op = skipwhite(*arg);
4639 }
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004640
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004641 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004642 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004643 error_white_both(op, 1);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004644 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004645 }
Bram Moolenaar918a4242020-12-06 14:37:08 +01004646 if (may_get_next_line_error(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004647 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004648
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004649 // get the second expression
Bram Moolenaar64d662d2020-08-09 19:02:50 +02004650 if (compile_expr7t(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004651 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004652
4653 if (ppconst->pp_used == ppconst_used + 2
4654 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4655 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004656 {
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004657 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4658 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
4659 varnumber_T res = 0;
4660 int failed = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004661
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004662 // both are numbers: compute the result
4663 switch (*op)
4664 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004665 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004666 break;
Bram Moolenaare64f83c2021-01-19 22:16:41 +01004667 case '/': res = num_divide(tv1->vval.v_number,
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004668 tv2->vval.v_number, &failed);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004669 break;
Bram Moolenaare64f83c2021-01-19 22:16:41 +01004670 case '%': res = num_modulus(tv1->vval.v_number,
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004671 tv2->vval.v_number, &failed);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004672 break;
4673 }
Bram Moolenaarc5f59fa2021-01-21 12:34:14 +01004674 if (failed)
4675 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004676 tv1->vval.v_number = res;
4677 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004678 }
4679 else
4680 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004681 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004682 generate_two_op(cctx, op);
4683 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004684 }
4685
4686 return OK;
4687}
4688
4689/*
Bram Moolenaard345fb92021-03-10 18:43:09 +01004690 * + number addition or list/blobl concatenation
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004691 * - number subtraction
4692 * .. string concatenation
4693 */
4694 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004695compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004696{
4697 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004698 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004699 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004700 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004701
4702 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004703 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004704 return FAIL;
4705
4706 /*
4707 * Repeat computing, until no "+", "-" or ".." is following.
4708 */
4709 for (;;)
4710 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004711 op = may_peek_next_line(cctx, *arg, &next);
4712 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004713 break;
4714 oplen = (*op == '.' ? 2 : 1);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004715 if (next != NULL)
4716 {
4717 *arg = next_line_from_context(cctx, TRUE);
4718 op = skipwhite(*arg);
4719 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004720
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004721 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004722 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004723 error_white_both(op, oplen);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004724 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004725 }
4726
Bram Moolenaare0de1712020-12-02 17:36:54 +01004727 if (may_get_next_line_error(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004728 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004729
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004730 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004731 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004732 return FAIL;
4733
Bram Moolenaara5565e42020-05-09 15:44:01 +02004734 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004735 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02004736 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
4737 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
4738 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4739 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004740 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004741 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4742 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004743
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004744 // concat/subtract/add constant numbers
4745 if (*op == '+')
4746 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
4747 else if (*op == '-')
4748 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
4749 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004750 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004751 // concatenate constant strings
4752 char_u *s1 = tv1->vval.v_string;
4753 char_u *s2 = tv2->vval.v_string;
4754 size_t len1 = STRLEN(s1);
4755
4756 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
4757 if (tv1->vval.v_string == NULL)
4758 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004759 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004760 return FAIL;
4761 }
4762 mch_memmove(tv1->vval.v_string, s1, len1);
4763 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004764 vim_free(s1);
4765 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004766 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004767 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004768 }
4769 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004770 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004771 generate_ppconst(cctx, ppconst);
Bram Moolenaard345fb92021-03-10 18:43:09 +01004772 ppconst->pp_is_const = FALSE;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004773 if (*op == '.')
4774 {
4775 if (may_generate_2STRING(-2, cctx) == FAIL
4776 || may_generate_2STRING(-1, cctx) == FAIL)
4777 return FAIL;
4778 generate_instr_drop(cctx, ISN_CONCAT, 1);
4779 }
4780 else
4781 generate_two_op(cctx, op);
4782 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004783 }
4784
4785 return OK;
4786}
4787
4788/*
4789 * expr5a == expr5b
4790 * expr5a =~ expr5b
4791 * expr5a != expr5b
4792 * expr5a !~ expr5b
4793 * expr5a > expr5b
4794 * expr5a >= expr5b
4795 * expr5a < expr5b
4796 * expr5a <= expr5b
4797 * expr5a is expr5b
4798 * expr5a isnot expr5b
4799 *
4800 * Produces instructions:
4801 * EVAL expr5a Push result of "expr5a"
4802 * EVAL expr5b Push result of "expr5b"
4803 * COMPARE one of the compare instructions
4804 */
4805 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004806compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004807{
Bram Moolenaar657137c2021-01-09 15:45:23 +01004808 exprtype_T type = EXPR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004809 char_u *p;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004810 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004811 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004812 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004813 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004814
4815 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004816 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004817 return FAIL;
4818
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004819 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004820 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004821
4822 /*
4823 * If there is a comparative operator, use it.
4824 */
4825 if (type != EXPR_UNKNOWN)
4826 {
4827 int ic = FALSE; // Default: do not ignore case
4828
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004829 if (next != NULL)
4830 {
4831 *arg = next_line_from_context(cctx, TRUE);
4832 p = skipwhite(*arg);
4833 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004834 if (type_is && (p[len] == '?' || p[len] == '#'))
4835 {
4836 semsg(_(e_invexpr2), *arg);
4837 return FAIL;
4838 }
4839 // extra question mark appended: ignore case
4840 if (p[len] == '?')
4841 {
4842 ic = TRUE;
4843 ++len;
4844 }
4845 // extra '#' appended: match case (ignored)
4846 else if (p[len] == '#')
4847 ++len;
4848 // nothing appended: match case
4849
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004850 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004851 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004852 error_white_both(p, len);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004853 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004854 }
4855
4856 // get the second variable
Bram Moolenaar918a4242020-12-06 14:37:08 +01004857 if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004858 return FAIL;
4859
Bram Moolenaara5565e42020-05-09 15:44:01 +02004860 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004861 return FAIL;
4862
Bram Moolenaara5565e42020-05-09 15:44:01 +02004863 if (ppconst->pp_used == ppconst_used + 2)
4864 {
4865 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
4866 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
4867 int ret;
4868
4869 // Both sides are a constant, compute the result now.
4870 // First check for a valid combination of types, this is more
4871 // strict than typval_compare().
Bram Moolenaar543e6f32020-07-10 22:45:38 +02004872 if (check_compare_types(type, tv1, tv2) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004873 ret = FAIL;
4874 else
4875 {
4876 ret = typval_compare(tv1, tv2, type, ic);
4877 tv1->v_type = VAR_BOOL;
4878 tv1->vval.v_number = tv1->vval.v_number
4879 ? VVAL_TRUE : VVAL_FALSE;
4880 clear_tv(tv2);
4881 --ppconst->pp_used;
4882 }
4883 return ret;
4884 }
4885
4886 generate_ppconst(cctx, ppconst);
4887 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004888 }
4889
4890 return OK;
4891}
4892
Bram Moolenaar7f141552020-05-09 17:35:53 +02004893static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
4894
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004895/*
4896 * Compile || or &&.
4897 */
4898 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004899compile_and_or(
4900 char_u **arg,
4901 cctx_T *cctx,
4902 char *op,
4903 ppconst_T *ppconst,
4904 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004905{
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004906 char_u *next;
4907 char_u *p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004908 int opchar = *op;
4909
4910 if (p[0] == opchar && p[1] == opchar)
4911 {
4912 garray_T *instr = &cctx->ctx_instr;
4913 garray_T end_ga;
4914
4915 /*
4916 * Repeat until there is no following "||" or "&&"
4917 */
4918 ga_init2(&end_ga, sizeof(int), 10);
4919 while (p[0] == opchar && p[1] == opchar)
4920 {
Bram Moolenaara7511c02021-04-03 21:47:07 +02004921 long start_lnum = SOURCING_LNUM;
4922 int start_ctx_lnum = cctx->ctx_lnum;
4923 int save_lnum;
4924
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004925 if (next != NULL)
4926 {
4927 *arg = next_line_from_context(cctx, TRUE);
4928 p = skipwhite(*arg);
4929 }
4930
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004931 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
4932 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01004933 semsg(_(e_white_space_required_before_and_after_str_at_str),
Bram Moolenaar90193e62021-04-04 20:49:50 +02004934 op, p);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004935 return FAIL;
4936 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004937
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004938 // TODO: use ppconst if the value is a constant and check
4939 // evaluating to bool
Bram Moolenaara5565e42020-05-09 15:44:01 +02004940 generate_ppconst(cctx, ppconst);
4941
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004942 // Every part must evaluate to a bool.
Bram Moolenaara7511c02021-04-03 21:47:07 +02004943 SOURCING_LNUM = start_lnum;
4944 save_lnum = cctx->ctx_lnum;
4945 cctx->ctx_lnum = start_ctx_lnum;
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004946 if (bool_on_stack(cctx) == FAIL)
4947 {
Bram Moolenaara7511c02021-04-03 21:47:07 +02004948 cctx->ctx_lnum = save_lnum;
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004949 ga_clear(&end_ga);
4950 return FAIL;
4951 }
Bram Moolenaara7511c02021-04-03 21:47:07 +02004952 cctx->ctx_lnum = save_lnum;
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004953
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004954 if (ga_grow(&end_ga, 1) == FAIL)
4955 {
4956 ga_clear(&end_ga);
4957 return FAIL;
4958 }
4959 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
4960 ++end_ga.ga_len;
4961 generate_JUMP(cctx, opchar == '|'
Bram Moolenaar2bb26582020-10-03 22:52:39 +02004962 ? JUMP_IF_COND_TRUE : JUMP_IF_COND_FALSE, 0);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004963
4964 // eval the next expression
Bram Moolenaar918a4242020-12-06 14:37:08 +01004965 if (may_get_next_line_error(p + 2, arg, cctx) == FAIL)
Bram Moolenaar8bb0f542020-12-06 16:03:55 +01004966 {
4967 ga_clear(&end_ga);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004968 return FAIL;
Bram Moolenaar8bb0f542020-12-06 16:03:55 +01004969 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004970
Bram Moolenaara5565e42020-05-09 15:44:01 +02004971 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
4972 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004973 {
4974 ga_clear(&end_ga);
4975 return FAIL;
4976 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004977
4978 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004979 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004980 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004981
Bram Moolenaarea2d4072020-11-12 12:08:51 +01004982 // Every part must evaluate to a bool.
4983 if (bool_on_stack(cctx) == FAIL)
4984 {
4985 ga_clear(&end_ga);
4986 return FAIL;
4987 }
4988
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004989 // Fill in the end label in all jumps.
4990 while (end_ga.ga_len > 0)
4991 {
4992 isn_T *isn;
4993
4994 --end_ga.ga_len;
4995 isn = ((isn_T *)instr->ga_data)
4996 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
4997 isn->isn_arg.jump.jump_where = instr->ga_len;
4998 }
4999 ga_clear(&end_ga);
5000 }
5001
5002 return OK;
5003}
5004
5005/*
5006 * expr4a && expr4a && expr4a logical AND
5007 *
5008 * Produces instructions:
5009 * EVAL expr4a Push result of "expr4a"
Bram Moolenaarea2d4072020-11-12 12:08:51 +01005010 * COND2BOOL convert to bool if needed
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005011 * JUMP_IF_COND_FALSE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005012 * EVAL expr4b Push result of "expr4b"
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005013 * JUMP_IF_COND_FALSE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005014 * EVAL expr4c Push result of "expr4c"
5015 * end:
5016 */
5017 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02005018compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005019{
Bram Moolenaara5565e42020-05-09 15:44:01 +02005020 int ppconst_used = ppconst->pp_used;
5021
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005022 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02005023 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005024 return FAIL;
5025
5026 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02005027 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005028}
5029
5030/*
5031 * expr3a || expr3b || expr3c logical OR
5032 *
5033 * Produces instructions:
5034 * EVAL expr3a Push result of "expr3a"
Bram Moolenaarea2d4072020-11-12 12:08:51 +01005035 * COND2BOOL convert to bool if needed
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005036 * JUMP_IF_COND_TRUE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005037 * EVAL expr3b Push result of "expr3b"
Bram Moolenaar2bb26582020-10-03 22:52:39 +02005038 * JUMP_IF_COND_TRUE end
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005039 * EVAL expr3c Push result of "expr3c"
5040 * end:
5041 */
5042 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02005043compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005044{
Bram Moolenaara5565e42020-05-09 15:44:01 +02005045 int ppconst_used = ppconst->pp_used;
5046
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005047 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02005048 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005049 return FAIL;
5050
5051 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02005052 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005053}
5054
5055/*
5056 * Toplevel expression: expr2 ? expr1a : expr1b
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005057 * Produces instructions:
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005058 * EVAL expr2 Push result of "expr2"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005059 * JUMP_IF_FALSE alt jump if false
5060 * EVAL expr1a
5061 * JUMP_ALWAYS end
5062 * alt: EVAL expr1b
5063 * end:
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005064 *
5065 * Toplevel expression: expr2 ?? expr1
5066 * Produces instructions:
5067 * EVAL expr2 Push result of "expr2"
5068 * JUMP_AND_KEEP_IF_TRUE end jump if true
5069 * EVAL expr1
5070 * end:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005071 */
5072 static int
Bram Moolenaar7e368202020-12-25 21:56:57 +01005073compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005074{
5075 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005076 int ppconst_used = ppconst->pp_used;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02005077 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005078
Bram Moolenaar3988f642020-08-27 22:43:03 +02005079 // Ignore all kinds of errors when not producing code.
5080 if (cctx->ctx_skip == SKIP_YES)
5081 {
Bram Moolenaar7e368202020-12-25 21:56:57 +01005082 skip_expr_cctx(arg, cctx);
Bram Moolenaar3988f642020-08-27 22:43:03 +02005083 return OK;
5084 }
5085
Bram Moolenaar61a89812020-05-07 16:58:17 +02005086 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02005087 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005088 return FAIL;
5089
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02005090 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005091 if (*p == '?')
5092 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005093 int op_falsy = p[1] == '?';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005094 garray_T *instr = &cctx->ctx_instr;
5095 garray_T *stack = &cctx->ctx_type_stack;
5096 int alt_idx = instr->ga_len;
Bram Moolenaar38041da2020-06-21 22:17:18 +02005097 int end_idx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005098 isn_T *isn;
Bram Moolenaar38041da2020-06-21 22:17:18 +02005099 type_T *type1 = NULL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005100 int has_const_expr = FALSE;
5101 int const_value = FALSE;
5102 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005103
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02005104 if (next != NULL)
5105 {
5106 *arg = next_line_from_context(cctx, TRUE);
5107 p = skipwhite(*arg);
5108 }
5109
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005110 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1 + op_falsy]))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02005111 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01005112 semsg(_(e_white_space_required_before_and_after_str_at_str),
5113 op_falsy ? "??" : "?", *arg);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02005114 return FAIL;
5115 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005116
Bram Moolenaara5565e42020-05-09 15:44:01 +02005117 if (ppconst->pp_used == ppconst_used + 1)
5118 {
5119 // the condition is a constant, we know whether the ? or the :
5120 // expression is to be evaluated.
5121 has_const_expr = TRUE;
Bram Moolenaar13106602020-10-04 16:06:05 +02005122 if (op_falsy)
5123 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
5124 else
5125 {
5126 int error = FALSE;
5127
5128 const_value = tv_get_bool_chk(&ppconst->pp_tv[ppconst_used],
5129 &error);
5130 if (error)
5131 return FAIL;
5132 }
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005133 cctx->ctx_skip = save_skip == SKIP_YES ||
5134 (op_falsy ? const_value : !const_value) ? SKIP_YES : SKIP_NOT;
5135
5136 if (op_falsy && cctx->ctx_skip == SKIP_YES)
5137 // "left ?? right" and "left" is truthy: produce "left"
5138 generate_ppconst(cctx, ppconst);
5139 else
5140 {
5141 clear_tv(&ppconst->pp_tv[ppconst_used]);
5142 --ppconst->pp_used;
5143 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02005144 }
5145 else
5146 {
5147 generate_ppconst(cctx, ppconst);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005148 if (op_falsy)
5149 end_idx = instr->ga_len;
5150 generate_JUMP(cctx, op_falsy
5151 ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
5152 if (op_falsy)
5153 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaara5565e42020-05-09 15:44:01 +02005154 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005155
5156 // evaluate the second expression; any type is accepted
Bram Moolenaar918a4242020-12-06 14:37:08 +01005157 if (may_get_next_line_error(p + 1 + op_falsy, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02005158 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005159 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01005160 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005161
Bram Moolenaara5565e42020-05-09 15:44:01 +02005162 if (!has_const_expr)
5163 {
5164 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005165
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005166 if (!op_falsy)
5167 {
5168 // remember the type and drop it
5169 --stack->ga_len;
5170 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005171
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005172 end_idx = instr->ga_len;
5173 generate_JUMP(cctx, JUMP_ALWAYS, 0);
Bram Moolenaara5565e42020-05-09 15:44:01 +02005174
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005175 // jump here from JUMP_IF_FALSE
5176 isn = ((isn_T *)instr->ga_data) + alt_idx;
5177 isn->isn_arg.jump.jump_where = instr->ga_len;
5178 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02005179 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005180
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005181 if (!op_falsy)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005182 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005183 // Check for the ":".
5184 p = may_peek_next_line(cctx, *arg, &next);
5185 if (*p != ':')
5186 {
5187 emsg(_(e_missing_colon));
5188 return FAIL;
5189 }
5190 if (next != NULL)
5191 {
5192 *arg = next_line_from_context(cctx, TRUE);
5193 p = skipwhite(*arg);
5194 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02005195
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005196 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
5197 {
Bram Moolenaare7a73e02021-01-01 19:17:55 +01005198 semsg(_(e_white_space_required_before_and_after_str_at_str),
5199 ":", p);
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005200 return FAIL;
5201 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005202
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005203 // evaluate the third expression
5204 if (has_const_expr)
5205 cctx->ctx_skip = save_skip == SKIP_YES || const_value
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005206 ? SKIP_YES : SKIP_NOT;
Bram Moolenaar918a4242020-12-06 14:37:08 +01005207 if (may_get_next_line_error(p + 1, arg, cctx) == FAIL)
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005208 return FAIL;
5209 if (compile_expr1(arg, cctx, ppconst) == FAIL)
5210 return FAIL;
5211 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005212
Bram Moolenaara5565e42020-05-09 15:44:01 +02005213 if (!has_const_expr)
5214 {
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005215 type_T **typep;
5216
Bram Moolenaara5565e42020-05-09 15:44:01 +02005217 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005218
Bram Moolenaara5565e42020-05-09 15:44:01 +02005219 // If the types differ, the result has a more generic type.
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005220 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
5221 common_type(type1, *typep, typep, cctx->ctx_type_list);
Bram Moolenaara5565e42020-05-09 15:44:01 +02005222
Bram Moolenaar92f26c22020-10-03 20:17:30 +02005223 // jump here from JUMP_ALWAYS or JUMP_AND_KEEP_IF_TRUE
Bram Moolenaara5565e42020-05-09 15:44:01 +02005224 isn = ((isn_T *)instr->ga_data) + end_idx;
5225 isn->isn_arg.jump.jump_where = instr->ga_len;
5226 }
5227
5228 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005229 }
5230 return OK;
5231}
5232
5233/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02005234 * Toplevel expression.
Bram Moolenaar334a8b42020-10-19 16:07:42 +02005235 * Sets "is_const" (if not NULL) to indicate the value is a constant.
5236 * Returns OK or FAIL.
Bram Moolenaara5565e42020-05-09 15:44:01 +02005237 */
5238 static int
Bram Moolenaar334a8b42020-10-19 16:07:42 +02005239compile_expr0_ext(char_u **arg, cctx_T *cctx, int *is_const)
Bram Moolenaara5565e42020-05-09 15:44:01 +02005240{
5241 ppconst_T ppconst;
5242
5243 CLEAR_FIELD(ppconst);
5244 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
5245 {
5246 clear_ppconst(&ppconst);
5247 return FAIL;
5248 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02005249 if (is_const != NULL)
5250 *is_const = ppconst.pp_used > 0 || ppconst.pp_is_const;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005251 if (generate_ppconst(cctx, &ppconst) == FAIL)
5252 return FAIL;
5253 return OK;
5254}
5255
5256/*
Bram Moolenaar334a8b42020-10-19 16:07:42 +02005257 * Toplevel expression.
5258 */
5259 static int
5260compile_expr0(char_u **arg, cctx_T *cctx)
5261{
5262 return compile_expr0_ext(arg, cctx, NULL);
5263}
5264
5265/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005266 * compile "return [expr]"
5267 */
5268 static char_u *
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005269compile_return(char_u *arg, int check_return_type, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005270{
5271 char_u *p = arg;
5272 garray_T *stack = &cctx->ctx_type_stack;
5273 type_T *stack_type;
5274
5275 if (*p != NUL && *p != '|' && *p != '\n')
5276 {
5277 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02005278 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005279 return NULL;
5280
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005281 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar05a55512020-07-05 15:52:19 +02005282 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005283 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar6b553772020-12-31 13:31:23 +01005284 if (check_return_type && (cctx->ctx_ufunc->uf_ret_type == NULL
Bram Moolenaar328eac22021-01-07 19:23:08 +01005285 || cctx->ctx_ufunc->uf_ret_type == &t_unknown
5286 || cctx->ctx_ufunc->uf_ret_type == &t_any))
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005287 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005288 cctx->ctx_ufunc->uf_ret_type = stack_type;
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005289 }
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005290 else
Bram Moolenaar05a55512020-07-05 15:52:19 +02005291 {
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005292 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
5293 && stack_type->tt_type != VAR_VOID
5294 && stack_type->tt_type != VAR_UNKNOWN)
5295 {
5296 emsg(_(e_returning_value_in_function_without_return_type));
5297 return NULL;
5298 }
5299 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
Bram Moolenaar351ead02021-01-16 16:07:01 +01005300 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005301 return NULL;
5302 }
Bram Moolenaar05a55512020-07-05 15:52:19 +02005303 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005304 }
5305 else
5306 {
Bram Moolenaar9e68c322020-12-25 12:38:04 +01005307 // "check_return_type" cannot be TRUE, only used for a lambda which
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02005308 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02005309 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
5310 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005311 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005312 emsg(_(e_missing_return_value));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005313 return NULL;
5314 }
5315
5316 // No argument, return zero.
5317 generate_PUSHNR(cctx, 0);
5318 }
Bram Moolenaar7cd24222021-01-12 18:58:39 +01005319
5320 // Undo any command modifiers.
5321 generate_undo_cmdmods(cctx);
5322
Bram Moolenaar8e02faf2020-11-18 16:35:02 +01005323 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_RETURN) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005324 return NULL;
5325
5326 // "return val | endif" is possible
5327 return skipwhite(p);
5328}
5329
5330/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02005331 * Get a line from the compilation context, compatible with exarg_T getline().
5332 * Return a pointer to the line in allocated memory.
5333 * Return NULL for end-of-file or some error.
5334 */
5335 static char_u *
5336exarg_getline(
5337 int c UNUSED,
5338 void *cookie,
5339 int indent UNUSED,
Bram Moolenaar66250c92020-08-20 15:02:42 +02005340 getline_opt_T options UNUSED)
Bram Moolenaar04b12692020-05-04 23:24:44 +02005341{
5342 cctx_T *cctx = (cctx_T *)cookie;
Bram Moolenaar66250c92020-08-20 15:02:42 +02005343 char_u *p;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005344
Bram Moolenaar66250c92020-08-20 15:02:42 +02005345 for (;;)
Bram Moolenaar04b12692020-05-04 23:24:44 +02005346 {
Bram Moolenaar2914a202020-09-27 18:24:03 +02005347 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len - 1)
Bram Moolenaar66250c92020-08-20 15:02:42 +02005348 return NULL;
5349 ++cctx->ctx_lnum;
5350 p = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
5351 // Comment lines result in NULL pointers, skip them.
5352 if (p != NULL)
5353 return vim_strsave(p);
Bram Moolenaar04b12692020-05-04 23:24:44 +02005354 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02005355}
5356
Bram Moolenaar7a6eaa02021-03-21 20:53:29 +01005357 void
5358fill_exarg_from_cctx(exarg_T *eap, cctx_T *cctx)
5359{
5360 eap->getline = exarg_getline;
5361 eap->cookie = cctx;
5362}
5363
Bram Moolenaar04b12692020-05-04 23:24:44 +02005364/*
5365 * Compile a nested :def command.
5366 */
5367 static char_u *
5368compile_nested_function(exarg_T *eap, cctx_T *cctx)
5369{
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005370 int is_global = *eap->arg == 'g' && eap->arg[1] == ':';
Bram Moolenaar04b12692020-05-04 23:24:44 +02005371 char_u *name_start = eap->arg;
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005372 char_u *name_end = to_name_end(eap->arg, TRUE);
Bram Moolenaareef21022020-08-01 22:16:43 +02005373 char_u *lambda_name;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005374 ufunc_T *ufunc;
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005375 int r = FAIL;
Bram Moolenaar04b12692020-05-04 23:24:44 +02005376
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02005377 if (eap->forceit)
Bram Moolenaar8b848ca2020-09-10 22:28:01 +02005378 {
5379 emsg(_(e_cannot_use_bang_with_nested_def));
5380 return NULL;
5381 }
5382
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01005383 if (*name_start == '/')
5384 {
5385 name_end = skip_regexp(name_start + 1, '/', TRUE);
5386 if (*name_end == '/')
5387 ++name_end;
5388 eap->nextcmd = check_nextcmd(name_end);
5389 }
5390 if (name_end == name_start || *skipwhite(name_end) != '(')
5391 {
5392 if (!ends_excmd2(name_start, name_end))
5393 {
5394 semsg(_(e_invalid_command_str), eap->cmd);
5395 return NULL;
5396 }
5397
5398 // "def" or "def Name": list functions
5399 if (generate_DEF(cctx, name_start, name_end - name_start) == FAIL)
5400 return NULL;
5401 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5402 }
5403
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005404 // Only g:Func() can use a namespace.
5405 if (name_start[1] == ':' && !is_global)
5406 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005407 semsg(_(e_namespace_not_supported_str), name_start);
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02005408 return NULL;
5409 }
Bram Moolenaar057e84a2021-02-28 16:55:11 +01005410 if (check_defined(name_start, name_end - name_start, cctx, FALSE) == FAIL)
Bram Moolenaareef21022020-08-01 22:16:43 +02005411 return NULL;
5412
Bram Moolenaar04b12692020-05-04 23:24:44 +02005413 eap->arg = name_end;
Bram Moolenaar7a6eaa02021-03-21 20:53:29 +01005414 fill_exarg_from_cctx(eap, cctx);
5415
Bram Moolenaar04b12692020-05-04 23:24:44 +02005416 eap->forceit = FALSE;
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005417 lambda_name = vim_strsave(get_lambda_name());
5418 if (lambda_name == NULL)
5419 return NULL;
Bram Moolenaarfbbcd002020-10-15 12:46:44 +02005420 ufunc = define_function(eap, lambda_name);
Bram Moolenaar04b12692020-05-04 23:24:44 +02005421
Bram Moolenaar822ba242020-05-24 23:00:18 +02005422 if (ufunc == NULL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005423 {
5424 r = eap->skip ? OK : FAIL;
5425 goto theend;
5426 }
Bram Moolenaar8863bda2021-03-17 18:42:08 +01005427
5428 // copy over the block scope IDs before compiling
5429 if (!is_global && cctx->ctx_ufunc->uf_block_depth > 0)
5430 {
5431 int block_depth = cctx->ctx_ufunc->uf_block_depth;
5432
5433 ufunc->uf_block_ids = ALLOC_MULT(int, block_depth);
5434 if (ufunc->uf_block_ids != NULL)
5435 {
5436 mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids,
5437 sizeof(int) * block_depth);
5438 ufunc->uf_block_depth = block_depth;
5439 }
5440 }
5441
Bram Moolenaare5ea3462021-01-25 21:01:48 +01005442 if (func_needs_compiling(ufunc, PROFILING(ufunc))
5443 && compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx)
Bram Moolenaarb2049902021-01-24 12:53:53 +01005444 == FAIL)
Bram Moolenaar4ee711f2020-09-23 18:51:11 +02005445 {
5446 func_ptr_unref(ufunc);
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005447 goto theend;
Bram Moolenaar4ee711f2020-09-23 18:51:11 +02005448 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02005449
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005450 if (is_global)
5451 {
5452 char_u *func_name = vim_strnsave(name_start + 2,
5453 name_end - name_start - 2);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02005454
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005455 if (func_name == NULL)
5456 r = FAIL;
5457 else
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005458 {
Bram Moolenaareef21022020-08-01 22:16:43 +02005459 r = generate_NEWFUNC(cctx, lambda_name, func_name);
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005460 lambda_name = NULL;
5461 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005462 }
5463 else
5464 {
5465 // Define a local variable for the function reference.
Bram Moolenaare8211a32020-10-09 22:04:29 +02005466 lvar_T *lvar = reserve_local(cctx, name_start, name_end - name_start,
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005467 TRUE, ufunc->uf_func_type);
Bram Moolenaare8211a32020-10-09 22:04:29 +02005468
Bram Moolenaareef21022020-08-01 22:16:43 +02005469 if (lvar == NULL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005470 goto theend;
Bram Moolenaar5a849da2020-08-08 16:47:30 +02005471 if (generate_FUNCREF(cctx, ufunc) == FAIL)
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005472 goto theend;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005473 r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
5474 }
Bram Moolenaar61a89812020-05-07 16:58:17 +02005475 // TODO: warning for trailing text?
Bram Moolenaar58a52f22020-12-22 18:56:55 +01005476
5477theend:
5478 vim_free(lambda_name);
Bram Moolenaar38ddf332020-07-31 22:05:04 +02005479 return r == FAIL ? NULL : (char_u *)"";
Bram Moolenaar04b12692020-05-04 23:24:44 +02005480}
5481
5482/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005483 * Return the length of an assignment operator, or zero if there isn't one.
5484 */
5485 int
5486assignment_len(char_u *p, int *heredoc)
5487{
5488 if (*p == '=')
5489 {
5490 if (p[1] == '<' && p[2] == '<')
5491 {
5492 *heredoc = TRUE;
5493 return 3;
5494 }
5495 return 1;
5496 }
5497 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
5498 return 2;
5499 if (STRNCMP(p, "..=", 3) == 0)
5500 return 3;
5501 return 0;
5502}
5503
5504// words that cannot be used as a variable
5505static char *reserved[] = {
5506 "true",
5507 "false",
Bram Moolenaar67977822021-01-03 21:53:53 +01005508 "null",
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005509 NULL
5510};
5511
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005512/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005513 * Generate the load instruction for "name".
5514 */
5515 static void
5516generate_loadvar(
5517 cctx_T *cctx,
5518 assign_dest_T dest,
5519 char_u *name,
5520 lvar_T *lvar,
5521 type_T *type)
5522{
5523 switch (dest)
5524 {
5525 case dest_option:
5526 // TODO: check the option exists
5527 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
5528 break;
5529 case dest_global:
Bram Moolenaar03290b82020-12-19 16:30:44 +01005530 if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
5531 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
5532 else
5533 generate_LOAD(cctx, ISN_LOADAUTO, 0, name, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005534 break;
5535 case dest_buffer:
5536 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
5537 break;
5538 case dest_window:
5539 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
5540 break;
5541 case dest_tab:
5542 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
5543 break;
5544 case dest_script:
5545 compile_load_scriptvar(cctx,
5546 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
5547 break;
5548 case dest_env:
5549 // Include $ in the name here
5550 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
5551 break;
5552 case dest_reg:
5553 generate_LOAD(cctx, ISN_LOADREG, name[1], NULL, &t_string);
5554 break;
5555 case dest_vimvar:
5556 generate_LOADV(cctx, name + 2, TRUE);
5557 break;
5558 case dest_local:
Bram Moolenaarab360522021-01-10 14:02:28 +01005559 if (lvar->lv_from_outer > 0)
5560 generate_LOADOUTER(cctx, lvar->lv_idx, lvar->lv_from_outer,
5561 type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005562 else
5563 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
5564 break;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01005565 case dest_expr:
5566 // list or dict value should already be on the stack.
5567 break;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005568 }
5569}
5570
Bram Moolenaardc234ca2020-11-28 18:52:33 +01005571/*
5572 * Skip over "[expr]" or ".member".
5573 * Does not check for any errors.
5574 */
5575 static char_u *
5576skip_index(char_u *start)
5577{
5578 char_u *p = start;
5579
5580 if (*p == '[')
5581 {
5582 p = skipwhite(p + 1);
5583 (void)skip_expr(&p, NULL);
5584 p = skipwhite(p);
5585 if (*p == ']')
5586 return p + 1;
5587 return p;
5588 }
5589 // if (*p == '.')
5590 return to_name_end(p + 1, TRUE);
5591}
5592
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005593 void
5594vim9_declare_error(char_u *name)
5595{
5596 char *scope = "";
5597
5598 switch (*name)
5599 {
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005600 case 'g': scope = _("global"); break;
5601 case 'b': scope = _("buffer"); break;
5602 case 'w': scope = _("window"); break;
5603 case 't': scope = _("tab"); break;
5604 case 'v': scope = "v:"; break;
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02005605 case '$': semsg(_(e_cannot_declare_an_environment_variable), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005606 return;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02005607 case '&': semsg(_(e_cannot_declare_an_option), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005608 return;
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02005609 case '@': semsg(_(e_cannot_declare_a_register_str), name);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005610 return;
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005611 default: return;
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005612 }
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02005613 semsg(_(e_cannot_declare_a_scope_variable), scope, name);
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005614}
5615
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005616/*
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005617 * For one assignment figure out the type of destination. Return it in "dest".
5618 * When not recognized "dest" is not set.
5619 * For an option "opt_flags" is set.
5620 * For a v:var "vimvaridx" is set.
5621 * "type" is set to the destination type if known, unchanted otherwise.
5622 * Return FAIL if an error message was given.
5623 */
5624 static int
5625get_var_dest(
5626 char_u *name,
5627 assign_dest_T *dest,
5628 int cmdidx,
5629 int *opt_flags,
5630 int *vimvaridx,
5631 type_T **type,
5632 cctx_T *cctx)
5633{
5634 char_u *p;
5635
5636 if (*name == '&')
5637 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005638 int cc;
5639 long numval;
5640 getoption_T opt_type;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005641
5642 *dest = dest_option;
5643 if (cmdidx == CMD_final || cmdidx == CMD_const)
5644 {
5645 emsg(_(e_const_option));
5646 return FAIL;
5647 }
5648 p = name;
5649 p = find_option_end(&p, opt_flags);
5650 if (p == NULL)
5651 {
5652 // cannot happen?
5653 emsg(_(e_letunexp));
5654 return FAIL;
5655 }
5656 cc = *p;
5657 *p = NUL;
5658 opt_type = get_option_value(skip_option_env_lead(name),
5659 &numval, NULL, *opt_flags);
5660 *p = cc;
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005661 switch (opt_type)
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005662 {
Bram Moolenaardd1f4262020-12-31 17:41:01 +01005663 case gov_unknown:
5664 semsg(_(e_unknown_option), name);
5665 return FAIL;
5666 case gov_string:
5667 case gov_hidden_string:
5668 *type = &t_string;
5669 break;
5670 case gov_bool:
5671 case gov_hidden_bool:
5672 *type = &t_bool;
5673 break;
5674 case gov_number:
5675 case gov_hidden_number:
5676 *type = &t_number;
5677 break;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005678 }
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005679 }
5680 else if (*name == '$')
5681 {
5682 *dest = dest_env;
5683 *type = &t_string;
5684 }
5685 else if (*name == '@')
5686 {
5687 if (!valid_yank_reg(name[1], FALSE) || name[1] == '.')
5688 {
5689 emsg_invreg(name[1]);
5690 return FAIL;
5691 }
5692 *dest = dest_reg;
5693 *type = &t_string;
5694 }
5695 else if (STRNCMP(name, "g:", 2) == 0)
5696 {
5697 *dest = dest_global;
5698 }
5699 else if (STRNCMP(name, "b:", 2) == 0)
5700 {
5701 *dest = dest_buffer;
5702 }
5703 else if (STRNCMP(name, "w:", 2) == 0)
5704 {
5705 *dest = dest_window;
5706 }
5707 else if (STRNCMP(name, "t:", 2) == 0)
5708 {
5709 *dest = dest_tab;
5710 }
5711 else if (STRNCMP(name, "v:", 2) == 0)
5712 {
5713 typval_T *vtv;
5714 int di_flags;
5715
5716 *vimvaridx = find_vim_var(name + 2, &di_flags);
5717 if (*vimvaridx < 0)
5718 {
5719 semsg(_(e_variable_not_found_str), name);
5720 return FAIL;
5721 }
5722 // We use the current value of "sandbox" here, is that OK?
5723 if (var_check_ro(di_flags, name, FALSE))
5724 return FAIL;
5725 *dest = dest_vimvar;
5726 vtv = get_vim_var_tv(*vimvaridx);
5727 *type = typval2type_vimvar(vtv, cctx->ctx_type_list);
5728 }
5729 return OK;
5730}
5731
5732/*
5733 * Generate a STORE instruction for "dest", not being "dest_local".
5734 * Return FAIL when out of memory.
5735 */
5736 static int
5737generate_store_var(
5738 cctx_T *cctx,
5739 assign_dest_T dest,
5740 int opt_flags,
5741 int vimvaridx,
5742 int scriptvar_idx,
5743 int scriptvar_sid,
5744 type_T *type,
5745 char_u *name)
5746{
5747 switch (dest)
5748 {
5749 case dest_option:
5750 return generate_STOREOPT(cctx, skip_option_env_lead(name),
5751 opt_flags);
5752 case dest_global:
5753 // include g: with the name, easier to execute that way
Bram Moolenaar03290b82020-12-19 16:30:44 +01005754 return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL
5755 ? ISN_STOREG : ISN_STOREAUTO, 0, name);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005756 case dest_buffer:
5757 // include b: with the name, easier to execute that way
5758 return generate_STORE(cctx, ISN_STOREB, 0, name);
5759 case dest_window:
5760 // include w: with the name, easier to execute that way
5761 return generate_STORE(cctx, ISN_STOREW, 0, name);
5762 case dest_tab:
5763 // include t: with the name, easier to execute that way
5764 return generate_STORE(cctx, ISN_STORET, 0, name);
5765 case dest_env:
5766 return generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5767 case dest_reg:
5768 return generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5769 case dest_vimvar:
5770 return generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5771 case dest_script:
5772 if (scriptvar_idx < 0)
Bram Moolenaar643ce6c2021-04-06 21:17:27 +02005773 // "s:" may be included in the name.
5774 return generate_OLDSCRIPT(cctx, ISN_STORES, name,
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005775 scriptvar_sid, type);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01005776 return generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
5777 scriptvar_sid, scriptvar_idx, type);
5778 case dest_local:
5779 case dest_expr:
5780 // cannot happen
5781 break;
5782 }
5783 return FAIL;
5784}
5785
Bram Moolenaar752fc692021-01-04 21:57:11 +01005786 static int
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02005787generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count)
5788{
5789 if (lhs->lhs_dest != dest_local)
5790 return generate_store_var(cctx, lhs->lhs_dest,
5791 lhs->lhs_opt_flags, lhs->lhs_vimvaridx,
5792 lhs->lhs_scriptvar_idx, lhs->lhs_scriptvar_sid,
5793 lhs->lhs_type, lhs->lhs_name);
5794
5795 if (lhs->lhs_lvar != NULL)
5796 {
5797 garray_T *instr = &cctx->ctx_instr;
5798 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
5799
5800 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE into
5801 // ISN_STORENR
5802 if (lhs->lhs_lvar->lv_from_outer == 0
5803 && instr->ga_len == instr_count + 1
5804 && isn->isn_type == ISN_PUSHNR)
5805 {
5806 varnumber_T val = isn->isn_arg.number;
5807 garray_T *stack = &cctx->ctx_type_stack;
5808
5809 isn->isn_type = ISN_STORENR;
5810 isn->isn_arg.storenr.stnr_idx = lhs->lhs_lvar->lv_idx;
5811 isn->isn_arg.storenr.stnr_val = val;
5812 if (stack->ga_len > 0)
5813 --stack->ga_len;
5814 }
5815 else if (lhs->lhs_lvar->lv_from_outer > 0)
5816 generate_STOREOUTER(cctx, lhs->lhs_lvar->lv_idx,
5817 lhs->lhs_lvar->lv_from_outer);
5818 else
5819 generate_STORE(cctx, ISN_STORE, lhs->lhs_lvar->lv_idx, NULL);
5820 }
5821 return OK;
5822}
5823
5824 static int
Bram Moolenaar752fc692021-01-04 21:57:11 +01005825is_decl_command(int cmdidx)
5826{
5827 return cmdidx == CMD_let || cmdidx == CMD_var
5828 || cmdidx == CMD_final || cmdidx == CMD_const;
5829}
5830
5831/*
5832 * Figure out the LHS type and other properties for an assignment or one item
5833 * of ":unlet" with an index.
5834 * Returns OK or FAIL.
5835 */
5836 static int
5837compile_lhs(
5838 char_u *var_start,
5839 lhs_T *lhs,
5840 int cmdidx,
5841 int heredoc,
5842 int oplen,
5843 cctx_T *cctx)
5844{
5845 char_u *var_end;
5846 int is_decl = is_decl_command(cmdidx);
5847
5848 CLEAR_POINTER(lhs);
5849 lhs->lhs_dest = dest_local;
5850 lhs->lhs_vimvaridx = -1;
5851 lhs->lhs_scriptvar_idx = -1;
5852
5853 // "dest_end" is the end of the destination, including "[expr]" or
5854 // ".name".
5855 // "var_end" is the end of the variable/option/etc. name.
5856 lhs->lhs_dest_end = skip_var_one(var_start, FALSE);
5857 if (*var_start == '@')
5858 var_end = var_start + 2;
5859 else
5860 {
5861 // skip over the leading "&", "&l:", "&g:" and "$"
5862 var_end = skip_option_env_lead(var_start);
5863 var_end = to_name_end(var_end, TRUE);
5864 }
5865
5866 // "a: type" is declaring variable "a" with a type, not dict "a:".
5867 if (is_decl && lhs->lhs_dest_end == var_start + 2
5868 && lhs->lhs_dest_end[-1] == ':')
5869 --lhs->lhs_dest_end;
5870 if (is_decl && var_end == var_start + 2 && var_end[-1] == ':')
5871 --var_end;
5872
5873 // compute the length of the destination without "[expr]" or ".name"
5874 lhs->lhs_varlen = var_end - var_start;
5875 lhs->lhs_name = vim_strnsave(var_start, lhs->lhs_varlen);
5876 if (lhs->lhs_name == NULL)
5877 return FAIL;
Bram Moolenaar08251752021-01-11 21:20:18 +01005878
5879 if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen)
5880 // Something follows after the variable: "var[idx]" or "var.key".
5881 lhs->lhs_has_index = TRUE;
5882
Bram Moolenaar752fc692021-01-04 21:57:11 +01005883 if (heredoc)
5884 lhs->lhs_type = &t_list_string;
5885 else
5886 lhs->lhs_type = &t_any;
5887
5888 if (cctx->ctx_skip != SKIP_YES)
5889 {
5890 int declare_error = FALSE;
5891
5892 if (get_var_dest(lhs->lhs_name, &lhs->lhs_dest, cmdidx,
5893 &lhs->lhs_opt_flags, &lhs->lhs_vimvaridx,
5894 &lhs->lhs_type, cctx) == FAIL)
5895 return FAIL;
Bram Moolenaard877a572021-04-01 19:42:48 +02005896 if (lhs->lhs_dest != dest_local
5897 && cmdidx != CMD_const && cmdidx != CMD_final)
Bram Moolenaar752fc692021-01-04 21:57:11 +01005898 {
5899 // Specific kind of variable recognized.
5900 declare_error = is_decl;
5901 }
5902 else
5903 {
5904 int idx;
5905
5906 // No specific kind of variable recognized, just a name.
5907 for (idx = 0; reserved[idx] != NULL; ++idx)
5908 if (STRCMP(reserved[idx], lhs->lhs_name) == 0)
5909 {
5910 semsg(_(e_cannot_use_reserved_name), lhs->lhs_name);
5911 return FAIL;
5912 }
5913
5914
5915 if (lookup_local(var_start, lhs->lhs_varlen,
5916 &lhs->lhs_local_lvar, cctx) == OK)
5917 lhs->lhs_lvar = &lhs->lhs_local_lvar;
5918 else
5919 {
5920 CLEAR_FIELD(lhs->lhs_arg_lvar);
5921 if (arg_exists(var_start, lhs->lhs_varlen,
5922 &lhs->lhs_arg_lvar.lv_idx, &lhs->lhs_arg_lvar.lv_type,
5923 &lhs->lhs_arg_lvar.lv_from_outer, cctx) == OK)
5924 {
5925 if (is_decl)
5926 {
5927 semsg(_(e_str_is_used_as_argument), lhs->lhs_name);
5928 return FAIL;
5929 }
5930 lhs->lhs_lvar = &lhs->lhs_arg_lvar;
5931 }
5932 }
5933 if (lhs->lhs_lvar != NULL)
5934 {
5935 if (is_decl)
5936 {
5937 semsg(_(e_variable_already_declared), lhs->lhs_name);
5938 return FAIL;
5939 }
5940 }
5941 else
5942 {
5943 int script_namespace = lhs->lhs_varlen > 1
5944 && STRNCMP(var_start, "s:", 2) == 0;
5945 int script_var = (script_namespace
5946 ? script_var_exists(var_start + 2, lhs->lhs_varlen - 2,
Bram Moolenaar15e5e532021-04-07 21:21:13 +02005947 cctx)
Bram Moolenaar752fc692021-01-04 21:57:11 +01005948 : script_var_exists(var_start, lhs->lhs_varlen,
Bram Moolenaar15e5e532021-04-07 21:21:13 +02005949 cctx)) == OK;
Bram Moolenaar752fc692021-01-04 21:57:11 +01005950 imported_T *import =
5951 find_imported(var_start, lhs->lhs_varlen, cctx);
5952
5953 if (script_namespace || script_var || import != NULL)
5954 {
5955 char_u *rawname = lhs->lhs_name
5956 + (lhs->lhs_name[1] == ':' ? 2 : 0);
5957
5958 if (is_decl)
5959 {
5960 if (script_namespace)
5961 semsg(_(e_cannot_declare_script_variable_in_function),
5962 lhs->lhs_name);
5963 else
Bram Moolenaar057e84a2021-02-28 16:55:11 +01005964 semsg(_(e_variable_already_declared_in_script_str),
Bram Moolenaar752fc692021-01-04 21:57:11 +01005965 lhs->lhs_name);
5966 return FAIL;
5967 }
5968 else if (cctx->ctx_ufunc->uf_script_ctx_version
5969 == SCRIPT_VERSION_VIM9
5970 && script_namespace
5971 && !script_var && import == NULL)
5972 {
5973 semsg(_(e_unknown_variable_str), lhs->lhs_name);
5974 return FAIL;
5975 }
5976
5977 lhs->lhs_dest = dest_script;
5978
5979 // existing script-local variables should have a type
5980 lhs->lhs_scriptvar_sid = current_sctx.sc_sid;
5981 if (import != NULL)
5982 lhs->lhs_scriptvar_sid = import->imp_sid;
5983 if (SCRIPT_ID_VALID(lhs->lhs_scriptvar_sid))
5984 {
Bram Moolenaar08251752021-01-11 21:20:18 +01005985 // Check writable only when no index follows.
Bram Moolenaar752fc692021-01-04 21:57:11 +01005986 lhs->lhs_scriptvar_idx = get_script_item_idx(
Bram Moolenaar08251752021-01-11 21:20:18 +01005987 lhs->lhs_scriptvar_sid, rawname,
5988 lhs->lhs_has_index ? ASSIGN_FINAL : ASSIGN_CONST,
5989 cctx);
Bram Moolenaar752fc692021-01-04 21:57:11 +01005990 if (lhs->lhs_scriptvar_idx >= 0)
5991 {
5992 scriptitem_T *si = SCRIPT_ITEM(
5993 lhs->lhs_scriptvar_sid);
5994 svar_T *sv =
5995 ((svar_T *)si->sn_var_vals.ga_data)
5996 + lhs->lhs_scriptvar_idx;
5997 lhs->lhs_type = sv->sv_type;
5998 }
5999 }
6000 }
Bram Moolenaar057e84a2021-02-28 16:55:11 +01006001 else if (check_defined(var_start, lhs->lhs_varlen, cctx, FALSE)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006002 == FAIL)
6003 return FAIL;
6004 }
6005 }
6006
6007 if (declare_error)
6008 {
6009 vim9_declare_error(lhs->lhs_name);
6010 return FAIL;
6011 }
6012 }
6013
6014 // handle "a:name" as a name, not index "name" on "a"
6015 if (lhs->lhs_varlen > 1 || var_start[lhs->lhs_varlen] != ':')
6016 var_end = lhs->lhs_dest_end;
6017
6018 if (lhs->lhs_dest != dest_option)
6019 {
6020 if (is_decl && *var_end == ':')
6021 {
6022 char_u *p;
6023
6024 // parse optional type: "let var: type = expr"
6025 if (!VIM_ISWHITE(var_end[1]))
6026 {
Bram Moolenaarc3fc75d2021-02-07 15:28:09 +01006027 semsg(_(e_white_space_required_after_str_str), ":", var_end);
Bram Moolenaar752fc692021-01-04 21:57:11 +01006028 return FAIL;
6029 }
6030 p = skipwhite(var_end + 1);
6031 lhs->lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
6032 if (lhs->lhs_type == NULL)
6033 return FAIL;
6034 lhs->lhs_has_type = TRUE;
6035 }
6036 else if (lhs->lhs_lvar != NULL)
6037 lhs->lhs_type = lhs->lhs_lvar->lv_type;
6038 }
6039
Bram Moolenaare42939a2021-04-05 17:11:17 +02006040 if (oplen == 3 && !heredoc
6041 && lhs->lhs_dest != dest_global
6042 && !lhs->lhs_has_index
6043 && lhs->lhs_type->tt_type != VAR_STRING
6044 && lhs->lhs_type->tt_type != VAR_ANY)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006045 {
6046 emsg(_(e_can_only_concatenate_to_string));
6047 return FAIL;
6048 }
6049
6050 if (lhs->lhs_lvar == NULL && lhs->lhs_dest == dest_local
6051 && cctx->ctx_skip != SKIP_YES)
6052 {
6053 if (oplen > 1 && !heredoc)
6054 {
6055 // +=, /=, etc. require an existing variable
6056 semsg(_(e_cannot_use_operator_on_new_variable), lhs->lhs_name);
6057 return FAIL;
6058 }
6059 if (!is_decl)
6060 {
6061 semsg(_(e_unknown_variable_str), lhs->lhs_name);
6062 return FAIL;
6063 }
6064
Bram Moolenaar3f327882021-03-17 20:56:38 +01006065 // Check the name is valid for a funcref.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006066 if ((lhs->lhs_type->tt_type == VAR_FUNC
6067 || lhs->lhs_type->tt_type == VAR_PARTIAL)
Bram Moolenaar3f327882021-03-17 20:56:38 +01006068 && var_wrong_func_name(lhs->lhs_name, TRUE))
Bram Moolenaar752fc692021-01-04 21:57:11 +01006069 return FAIL;
Bram Moolenaar3f327882021-03-17 20:56:38 +01006070
6071 // New local variable.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006072 lhs->lhs_lvar = reserve_local(cctx, var_start, lhs->lhs_varlen,
6073 cmdidx == CMD_final || cmdidx == CMD_const, lhs->lhs_type);
6074 if (lhs->lhs_lvar == NULL)
6075 return FAIL;
6076 lhs->lhs_new_local = TRUE;
6077 }
6078
6079 lhs->lhs_member_type = lhs->lhs_type;
Bram Moolenaar08251752021-01-11 21:20:18 +01006080 if (lhs->lhs_has_index)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006081 {
6082 // Something follows after the variable: "var[idx]" or "var.key".
6083 // TODO: should we also handle "->func()" here?
6084 if (is_decl)
6085 {
6086 emsg(_(e_cannot_use_index_when_declaring_variable));
6087 return FAIL;
6088 }
6089
6090 if (var_start[lhs->lhs_varlen] == '['
6091 || var_start[lhs->lhs_varlen] == '.')
6092 {
6093 char_u *after = var_start + lhs->lhs_varlen;
6094 char_u *p;
6095
6096 // Only the last index is used below, if there are others
6097 // before it generate code for the expression. Thus for
6098 // "ll[1][2]" the expression is "ll[1]" and "[2]" is the index.
6099 for (;;)
6100 {
6101 p = skip_index(after);
6102 if (*p != '[' && *p != '.')
6103 break;
6104 after = p;
6105 }
6106 if (after > var_start + lhs->lhs_varlen)
6107 {
6108 lhs->lhs_varlen = after - var_start;
6109 lhs->lhs_dest = dest_expr;
6110 // We don't know the type before evaluating the expression,
6111 // use "any" until then.
6112 lhs->lhs_type = &t_any;
6113 }
6114
Bram Moolenaar752fc692021-01-04 21:57:11 +01006115 if (lhs->lhs_type->tt_member == NULL)
6116 lhs->lhs_member_type = &t_any;
6117 else
6118 lhs->lhs_member_type = lhs->lhs_type->tt_member;
6119 }
6120 else
6121 {
6122 semsg("Not supported yet: %s", var_start);
6123 return FAIL;
6124 }
6125 }
6126 return OK;
6127}
6128
6129/*
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02006130 * Figure out the LHS and check a few errors.
6131 */
6132 static int
6133compile_assign_lhs(
6134 char_u *var_start,
6135 lhs_T *lhs,
6136 int cmdidx,
6137 int is_decl,
6138 int heredoc,
6139 int oplen,
6140 cctx_T *cctx)
6141{
6142 if (compile_lhs(var_start, lhs, cmdidx, heredoc, oplen, cctx) == FAIL)
6143 return FAIL;
6144
6145 if (!lhs->lhs_has_index && lhs->lhs_lvar == &lhs->lhs_arg_lvar)
6146 {
6147 semsg(_(e_cannot_assign_to_argument), lhs->lhs_name);
6148 return FAIL;
6149 }
6150 if (!is_decl && lhs->lhs_lvar != NULL
6151 && lhs->lhs_lvar->lv_const && !lhs->lhs_has_index)
6152 {
6153 semsg(_(e_cannot_assign_to_constant), lhs->lhs_name);
6154 return FAIL;
6155 }
6156 return OK;
6157}
6158
6159/*
Bram Moolenaare42939a2021-04-05 17:11:17 +02006160 * For an assignment with an index, compile the "idx" in "var[idx]" or "key" in
6161 * "var.key".
Bram Moolenaar752fc692021-01-04 21:57:11 +01006162 */
6163 static int
Bram Moolenaare42939a2021-04-05 17:11:17 +02006164compile_assign_index(
Bram Moolenaar752fc692021-01-04 21:57:11 +01006165 char_u *var_start,
6166 lhs_T *lhs,
Bram Moolenaare42939a2021-04-05 17:11:17 +02006167 int *range,
Bram Moolenaar752fc692021-01-04 21:57:11 +01006168 cctx_T *cctx)
6169{
Bram Moolenaar752fc692021-01-04 21:57:11 +01006170 size_t varlen = lhs->lhs_varlen;
Bram Moolenaare42939a2021-04-05 17:11:17 +02006171 char_u *p;
6172 int r = OK;
Bram Moolenaar68452172021-04-12 21:21:02 +02006173 int need_white_before = TRUE;
6174 int empty_second;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006175
Bram Moolenaar752fc692021-01-04 21:57:11 +01006176 p = var_start + varlen;
6177 if (*p == '[')
6178 {
6179 p = skipwhite(p + 1);
Bram Moolenaar68452172021-04-12 21:21:02 +02006180 if (*p == ':')
6181 {
6182 // empty first index, push zero
6183 r = generate_PUSHNR(cctx, 0);
6184 need_white_before = FALSE;
6185 }
6186 else
6187 r = compile_expr0(&p, cctx);
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006188
6189 if (r == OK && *skipwhite(p) == ':')
6190 {
6191 // unlet var[idx : idx]
Bram Moolenaar68452172021-04-12 21:21:02 +02006192 // blob[idx : idx] = value
Bram Moolenaare42939a2021-04-05 17:11:17 +02006193 *range = TRUE;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006194 p = skipwhite(p);
Bram Moolenaar68452172021-04-12 21:21:02 +02006195 empty_second = *skipwhite(p + 1) == ']';
6196 if ((need_white_before && !IS_WHITE_OR_NUL(p[-1]))
6197 || (!empty_second && !IS_WHITE_OR_NUL(p[1])))
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006198 {
6199 semsg(_(e_white_space_required_before_and_after_str_at_str),
6200 ":", p);
6201 return FAIL;
6202 }
6203 p = skipwhite(p + 1);
Bram Moolenaar68452172021-04-12 21:21:02 +02006204 if (*p == ']')
6205 // empty second index, push "none"
6206 r = generate_PUSHSPEC(cctx, VVAL_NONE);
6207 else
6208 r = compile_expr0(&p, cctx);
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006209 }
6210
Bram Moolenaar752fc692021-01-04 21:57:11 +01006211 if (r == OK && *skipwhite(p) != ']')
6212 {
6213 // this should not happen
6214 emsg(_(e_missbrac));
6215 r = FAIL;
6216 }
6217 }
6218 else // if (*p == '.')
6219 {
6220 char_u *key_end = to_name_end(p + 1, TRUE);
6221 char_u *key = vim_strnsave(p + 1, key_end - p - 1);
6222
6223 r = generate_PUSHS(cctx, key);
6224 }
Bram Moolenaare42939a2021-04-05 17:11:17 +02006225 return r;
6226}
6227
6228/*
Bram Moolenaarb9c0cd82021-04-05 20:51:00 +02006229 * For a LHS with an index, load the variable to be indexed.
6230 */
6231 static int
6232compile_load_lhs(
6233 lhs_T *lhs,
6234 char_u *var_start,
6235 type_T *rhs_type,
6236 cctx_T *cctx)
6237{
6238 if (lhs->lhs_dest == dest_expr)
6239 {
6240 size_t varlen = lhs->lhs_varlen;
6241 int c = var_start[varlen];
6242 char_u *p = var_start;
6243 garray_T *stack = &cctx->ctx_type_stack;
6244
6245 // Evaluate "ll[expr]" of "ll[expr][idx]"
6246 var_start[varlen] = NUL;
6247 if (compile_expr0(&p, cctx) == OK && p != var_start + varlen)
6248 {
6249 // this should not happen
6250 emsg(_(e_missbrac));
Bram Moolenaarc9605f02021-04-06 21:29:32 +02006251 var_start[varlen] = c;
Bram Moolenaarb9c0cd82021-04-05 20:51:00 +02006252 return FAIL;
6253 }
6254 var_start[varlen] = c;
6255
6256 lhs->lhs_type = stack->ga_len == 0 ? &t_void
6257 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
6258 // now we can properly check the type
6259 if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL
6260 && rhs_type != &t_void
6261 && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx,
6262 FALSE, FALSE) == FAIL)
6263 return FAIL;
6264 }
6265 else
6266 generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name,
6267 lhs->lhs_lvar, lhs->lhs_type);
6268 return OK;
6269}
6270
6271/*
Bram Moolenaare42939a2021-04-05 17:11:17 +02006272 * Assignment to a list or dict member, or ":unlet" for the item, using the
6273 * information in "lhs".
6274 * Returns OK or FAIL.
6275 */
6276 static int
6277compile_assign_unlet(
6278 char_u *var_start,
6279 lhs_T *lhs,
6280 int is_assign,
6281 type_T *rhs_type,
6282 cctx_T *cctx)
6283{
Bram Moolenaare42939a2021-04-05 17:11:17 +02006284 vartype_T dest_type;
Bram Moolenaare42939a2021-04-05 17:11:17 +02006285 garray_T *stack = &cctx->ctx_type_stack;
6286 int range = FALSE;
6287
Bram Moolenaar68452172021-04-12 21:21:02 +02006288 if (compile_assign_index(var_start, lhs, &range, cctx) == FAIL)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006289 return FAIL;
Bram Moolenaar68452172021-04-12 21:21:02 +02006290 if (is_assign && range && lhs->lhs_type != &t_blob
6291 && lhs->lhs_type != &t_any)
6292 {
6293 semsg(_(e_cannot_use_range_with_assignment_str), var_start);
6294 return FAIL;
6295 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006296
6297 if (lhs->lhs_type == &t_any)
6298 {
6299 // Index on variable of unknown type: check at runtime.
6300 dest_type = VAR_ANY;
6301 }
6302 else
6303 {
6304 dest_type = lhs->lhs_type->tt_type;
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006305 if (dest_type == VAR_DICT && range)
6306 {
6307 emsg(e_cannot_use_range_with_dictionary);
6308 return FAIL;
6309 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006310 if (dest_type == VAR_DICT && may_generate_2STRING(-1, cctx) == FAIL)
6311 return FAIL;
Bram Moolenaar51e93322021-04-17 20:44:56 +02006312 if (dest_type == VAR_LIST || dest_type == VAR_BLOB)
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006313 {
Bram Moolenaar51e93322021-04-17 20:44:56 +02006314 type_T *type;
6315
6316 if (range)
6317 {
6318 type = ((type_T **)stack->ga_data)[stack->ga_len - 2];
6319 if (need_type(type, &t_number,
6320 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006321 return FAIL;
Bram Moolenaar51e93322021-04-17 20:44:56 +02006322 }
6323 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6324 if ((dest_type != VAR_BLOB || type != &t_special)
6325 && need_type(type, &t_number,
6326 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006327 return FAIL;
6328 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006329 }
6330
6331 // Load the dict or list. On the stack we then have:
6332 // - value (for assignment, not for :unlet)
6333 // - index
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006334 // - for [a : b] second index
Bram Moolenaar752fc692021-01-04 21:57:11 +01006335 // - variable
Bram Moolenaarb9c0cd82021-04-05 20:51:00 +02006336 if (compile_load_lhs(lhs, var_start, rhs_type, cctx) == FAIL)
6337 return FAIL;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006338
Bram Moolenaar68452172021-04-12 21:21:02 +02006339 if (dest_type == VAR_LIST || dest_type == VAR_DICT
6340 || dest_type == VAR_BLOB || dest_type == VAR_ANY)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006341 {
6342 if (is_assign)
6343 {
Bram Moolenaar68452172021-04-12 21:21:02 +02006344 if (range)
6345 {
6346 if (generate_instr_drop(cctx, ISN_STORERANGE, 4) == NULL)
6347 return FAIL;
6348 }
6349 else
6350 {
6351 isn_T *isn = generate_instr_drop(cctx, ISN_STOREINDEX, 3);
Bram Moolenaar752fc692021-01-04 21:57:11 +01006352
Bram Moolenaar68452172021-04-12 21:21:02 +02006353 if (isn == NULL)
6354 return FAIL;
6355 isn->isn_arg.vartype = dest_type;
6356 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006357 }
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01006358 else if (range)
6359 {
6360 if (generate_instr_drop(cctx, ISN_UNLETRANGE, 3) == NULL)
6361 return FAIL;
6362 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006363 else
6364 {
6365 if (generate_instr_drop(cctx, ISN_UNLETINDEX, 2) == NULL)
6366 return FAIL;
6367 }
6368 }
6369 else
6370 {
6371 emsg(_(e_indexable_type_required));
6372 return FAIL;
6373 }
6374
6375 return OK;
6376}
6377
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01006378/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006379 * Compile declaration and assignment:
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006380 * "let name"
6381 * "var name = expr"
6382 * "final name = expr"
6383 * "const name = expr"
6384 * "name = expr"
6385 * "arg" points to "name".
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006386 * Return NULL for an error.
6387 * Return "arg" if it does not look like a variable list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006388 */
6389 static char_u *
6390compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
6391{
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006392 char_u *var_start;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006393 char_u *p;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006394 char_u *end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006395 char_u *ret = NULL;
6396 int var_count = 0;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006397 int var_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006398 int semicolon = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006399 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006400 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006401 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006402 int oplen = 0;
6403 int heredoc = FALSE;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006404 type_T *rhs_type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006405 char_u *sp;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006406 int is_decl = is_decl_command(cmdidx);
6407 lhs_T lhs;
Bram Moolenaar77709b12021-04-03 21:01:01 +02006408 long start_lnum = SOURCING_LNUM;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006409
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006410 // Skip over the "var" or "[var, var]" to get to any "=".
6411 p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
6412 if (p == NULL)
6413 return *arg == '[' ? arg : NULL;
6414
6415 if (var_count > 0 && is_decl)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006416 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02006417 // TODO: should we allow this, and figure out type inference from list
6418 // members?
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006419 emsg(_(e_cannot_use_list_for_declaration));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006420 return NULL;
6421 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006422 lhs.lhs_name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006423
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006424 sp = p;
6425 p = skipwhite(p);
6426 op = p;
6427 oplen = assignment_len(p, &heredoc);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006428
6429 if (var_count > 0 && oplen == 0)
6430 // can be something like "[1, 2]->func()"
6431 return arg;
6432
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006433 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !IS_WHITE_OR_NUL(op[oplen])))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006434 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02006435 error_white_both(op, oplen);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006436 return NULL;
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02006437 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006438
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006439 if (heredoc)
6440 {
6441 list_T *l;
6442 listitem_T *li;
6443
6444 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02006445 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006446 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02006447 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaarc0e29012020-09-27 14:22:48 +02006448 if (l == NULL)
6449 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006450
Bram Moolenaar078269b2020-09-21 20:35:55 +02006451 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006452 {
Bram Moolenaar078269b2020-09-21 20:35:55 +02006453 // Push each line and the create the list.
6454 FOR_ALL_LIST_ITEMS(l, li)
6455 {
6456 generate_PUSHS(cctx, li->li_tv.vval.v_string);
6457 li->li_tv.vval.v_string = NULL;
6458 }
6459 generate_NEWLIST(cctx, l->lv_len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006460 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006461 list_free(l);
6462 p += STRLEN(p);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006463 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006464 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006465 else if (var_count > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006466 {
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006467 char_u *wp;
6468
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006469 // for "[var, var] = expr" evaluate the expression here, loop over the
6470 // list of variables below.
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006471 // A line break may follow the "=".
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02006472
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006473 wp = op + oplen;
Bram Moolenaar8ff16e02020-12-07 21:49:52 +01006474 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
Bram Moolenaar004d9b02020-11-30 21:40:03 +01006475 return FAIL;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006476 if (compile_expr0(&p, cctx) == FAIL)
6477 return NULL;
6478 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006479
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006480 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006481 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006482 type_T *stacktype;
6483
Bram Moolenaarec5929d2020-04-07 20:53:39 +02006484 stacktype = stack->ga_len == 0 ? &t_void
6485 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006486 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006487 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006488 emsg(_(e_cannot_use_void_value));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006489 goto theend;
6490 }
Bram Moolenaar351ead02021-01-16 16:07:01 +01006491 if (need_type(stacktype, &t_list_any, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006492 FALSE, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006493 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02006494 // TODO: check the length of a constant list here
Bram Moolenaar9af78762020-06-16 11:34:42 +02006495 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
6496 semicolon);
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006497 if (stacktype->tt_member != NULL)
6498 rhs_type = stacktype->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006499 }
6500 }
6501
6502 /*
6503 * Loop over variables in "[var, var] = expr".
6504 * For "var = expr" and "let var: type" this is done only once.
6505 */
6506 if (var_count > 0)
6507 var_start = skipwhite(arg + 1); // skip over the "["
6508 else
6509 var_start = arg;
6510 for (var_idx = 0; var_idx == 0 || var_idx < var_count; var_idx++)
6511 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006512 int instr_count = -1;
6513
Bram Moolenaarf93bbd02021-04-10 22:35:43 +02006514 if (var_start[0] == '_' && !eval_isnamec(var_start[1]))
6515 {
6516 // Ignore underscore in "[a, _, b] = list".
6517 if (var_count > 0)
6518 {
6519 var_start = skipwhite(var_start + 2);
6520 continue;
6521 }
6522 emsg(_(e_cannot_use_underscore_here));
6523 goto theend;
6524 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006525 vim_free(lhs.lhs_name);
6526
6527 /*
6528 * Figure out the LHS type and other properties.
6529 */
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02006530 if (compile_assign_lhs(var_start, &lhs, cmdidx,
6531 is_decl, heredoc, oplen, cctx) == FAIL)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006532 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006533 if (!heredoc)
6534 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006535 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006536 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006537 if (oplen > 0 && var_count == 0)
6538 {
6539 // skip over the "=" and the expression
6540 p = skipwhite(op + oplen);
6541 compile_expr0(&p, cctx);
6542 }
6543 }
6544 else if (oplen > 0)
6545 {
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006546 int is_const = FALSE;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006547 char_u *wp;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006548
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006549 // For "var = expr" evaluate the expression.
6550 if (var_count == 0)
6551 {
6552 int r;
6553
6554 // for "+=", "*=", "..=" etc. first load the current value
6555 if (*op != '=')
6556 {
Bram Moolenaarb9c0cd82021-04-05 20:51:00 +02006557 compile_load_lhs(&lhs, var_start, NULL, cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006558
Bram Moolenaar752fc692021-01-04 21:57:11 +01006559 if (lhs.lhs_has_index)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006560 {
Bram Moolenaare42939a2021-04-05 17:11:17 +02006561 int range = FALSE;
6562
6563 // Get member from list or dict. First compile the
6564 // index value.
6565 if (compile_assign_index(var_start, &lhs,
Bram Moolenaar68452172021-04-12 21:21:02 +02006566 &range, cctx) == FAIL)
Bram Moolenaare42939a2021-04-05 17:11:17 +02006567 goto theend;
Bram Moolenaar68452172021-04-12 21:21:02 +02006568 if (range)
6569 {
Bram Moolenaarb1419262021-04-14 20:54:07 +02006570 semsg(_(e_cannot_use_range_with_assignment_operator_str),
Bram Moolenaar68452172021-04-12 21:21:02 +02006571 var_start);
Bram Moolenaarf387f5d2021-04-15 13:42:21 +02006572 goto theend;
Bram Moolenaar68452172021-04-12 21:21:02 +02006573 }
Bram Moolenaare42939a2021-04-05 17:11:17 +02006574
6575 // Get the member.
6576 if (compile_member(FALSE, cctx) == FAIL)
6577 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006578 }
6579 }
6580
6581 // Compile the expression. Temporarily hide the new local
6582 // variable here, it is not available to this expression.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006583 if (lhs.lhs_new_local)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006584 --cctx->ctx_locals.ga_len;
6585 instr_count = instr->ga_len;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006586 wp = op + oplen;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006587 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
Bram Moolenaar21e51222020-12-04 12:43:29 +01006588 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006589 if (lhs.lhs_new_local)
Bram Moolenaar21e51222020-12-04 12:43:29 +01006590 ++cctx->ctx_locals.ga_len;
Bram Moolenaar7f764942020-12-02 15:11:18 +01006591 goto theend;
Bram Moolenaar21e51222020-12-04 12:43:29 +01006592 }
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006593 r = compile_expr0_ext(&p, cctx, &is_const);
Bram Moolenaar752fc692021-01-04 21:57:11 +01006594 if (lhs.lhs_new_local)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006595 ++cctx->ctx_locals.ga_len;
6596 if (r == FAIL)
6597 goto theend;
6598 }
Bram Moolenaar9af78762020-06-16 11:34:42 +02006599 else if (semicolon && var_idx == var_count - 1)
6600 {
6601 // For "[var; var] = expr" get the rest of the list
6602 if (generate_SLICE(cctx, var_count - 1) == FAIL)
6603 goto theend;
6604 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006605 else
6606 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006607 // For "[var, var] = expr" get the "var_idx" item from the
6608 // list.
6609 if (generate_GETITEM(cctx, var_idx) == FAIL)
Bram Moolenaar7f764942020-12-02 15:11:18 +01006610 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006611 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006612
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006613 rhs_type = stack->ga_len == 0 ? &t_void
Bram Moolenaar6802cce2020-07-19 15:49:49 +02006614 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar752fc692021-01-04 21:57:11 +01006615 if (lhs.lhs_lvar != NULL && (is_decl || !lhs.lhs_has_type))
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006616 {
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006617 if ((rhs_type->tt_type == VAR_FUNC
6618 || rhs_type->tt_type == VAR_PARTIAL)
Bram Moolenaar3f327882021-03-17 20:56:38 +01006619 && !lhs.lhs_has_index
Bram Moolenaar752fc692021-01-04 21:57:11 +01006620 && var_wrong_func_name(lhs.lhs_name, TRUE))
Bram Moolenaar0f769812020-09-12 18:32:34 +02006621 goto theend;
6622
Bram Moolenaar752fc692021-01-04 21:57:11 +01006623 if (lhs.lhs_new_local && !lhs.lhs_has_type)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006624 {
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006625 if (rhs_type->tt_type == VAR_VOID)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006626 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006627 emsg(_(e_cannot_use_void_value));
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006628 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006629 }
6630 else
6631 {
Bram Moolenaar04bdd572020-09-23 13:25:32 +02006632 // An empty list or dict has a &t_unknown member,
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006633 // for a variable that implies &t_any.
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006634 if (rhs_type == &t_list_empty)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006635 lhs.lhs_lvar->lv_type = &t_list_any;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006636 else if (rhs_type == &t_dict_empty)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006637 lhs.lhs_lvar->lv_type = &t_dict_any;
Bram Moolenaardc234ca2020-11-28 18:52:33 +01006638 else if (rhs_type == &t_unknown)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006639 lhs.lhs_lvar->lv_type = &t_any;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006640 else
Bram Moolenaar752fc692021-01-04 21:57:11 +01006641 lhs.lhs_lvar->lv_type = rhs_type;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006642 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006643 }
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006644 else if (*op == '=')
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006645 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006646 type_T *use_type = lhs.lhs_lvar->lv_type;
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006647
Bram Moolenaar77709b12021-04-03 21:01:01 +02006648 // Without operator check type here, otherwise below.
6649 // Use the line number of the assignment.
6650 SOURCING_LNUM = start_lnum;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006651 if (lhs.lhs_has_index)
6652 use_type = lhs.lhs_member_type;
Bram Moolenaar351ead02021-01-16 16:07:01 +01006653 if (need_type(rhs_type, use_type, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006654 FALSE, is_const) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006655 goto theend;
6656 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006657 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006658 else if (*p != '=' && need_type(rhs_type, lhs.lhs_member_type,
Bram Moolenaar351ead02021-01-16 16:07:01 +01006659 -1, 0, cctx, FALSE, FALSE) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006660 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006661 }
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006662 else if (cmdidx == CMD_final)
6663 {
6664 emsg(_(e_final_requires_a_value));
6665 goto theend;
6666 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006667 else if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006668 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02006669 emsg(_(e_const_requires_a_value));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006670 goto theend;
6671 }
Bram Moolenaar752fc692021-01-04 21:57:11 +01006672 else if (!lhs.lhs_has_type || lhs.lhs_dest == dest_option)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006673 {
Bram Moolenaarbc4c5052020-08-13 22:47:35 +02006674 emsg(_(e_type_or_initialization_required));
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006675 goto theend;
6676 }
6677 else
6678 {
6679 // variables are always initialized
6680 if (ga_grow(instr, 1) == FAIL)
6681 goto theend;
Bram Moolenaar752fc692021-01-04 21:57:11 +01006682 switch (lhs.lhs_member_type->tt_type)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006683 {
6684 case VAR_BOOL:
6685 generate_PUSHBOOL(cctx, VVAL_FALSE);
6686 break;
6687 case VAR_FLOAT:
6688#ifdef FEAT_FLOAT
6689 generate_PUSHF(cctx, 0.0);
6690#endif
6691 break;
6692 case VAR_STRING:
6693 generate_PUSHS(cctx, NULL);
6694 break;
6695 case VAR_BLOB:
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02006696 generate_PUSHBLOB(cctx, blob_alloc());
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006697 break;
6698 case VAR_FUNC:
6699 generate_PUSHFUNC(cctx, NULL, &t_func_void);
6700 break;
6701 case VAR_LIST:
6702 generate_NEWLIST(cctx, 0);
6703 break;
6704 case VAR_DICT:
6705 generate_NEWDICT(cctx, 0);
6706 break;
6707 case VAR_JOB:
6708 generate_PUSHJOB(cctx, NULL);
6709 break;
6710 case VAR_CHANNEL:
6711 generate_PUSHCHANNEL(cctx, NULL);
6712 break;
6713 case VAR_NUMBER:
6714 case VAR_UNKNOWN:
6715 case VAR_ANY:
6716 case VAR_PARTIAL:
6717 case VAR_VOID:
6718 case VAR_SPECIAL: // cannot happen
6719 generate_PUSHNR(cctx, 0);
6720 break;
6721 }
6722 }
6723 if (var_count == 0)
6724 end = p;
6725 }
6726
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006727 // no need to parse more when skipping
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006728 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02006729 break;
6730
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006731 if (oplen > 0 && *op != '=')
6732 {
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006733 type_T *expected;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006734 type_T *stacktype;
6735
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006736 if (*op == '.')
6737 expected = &t_string;
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006738 else
Bram Moolenaar752fc692021-01-04 21:57:11 +01006739 expected = lhs.lhs_member_type;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006740 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006741 if (
6742#ifdef FEAT_FLOAT
6743 // If variable is float operation with number is OK.
6744 !(expected == &t_float && stacktype == &t_number) &&
6745#endif
Bram Moolenaar351ead02021-01-16 16:07:01 +01006746 need_type(stacktype, expected, -1, 0, cctx,
Bram Moolenaar334a8b42020-10-19 16:07:42 +02006747 FALSE, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006748 goto theend;
6749
6750 if (*op == '.')
Bram Moolenaardd29f1b2020-08-07 20:46:20 +02006751 {
6752 if (generate_instr_drop(cctx, ISN_CONCAT, 1) == NULL)
6753 goto theend;
6754 }
6755 else if (*op == '+')
6756 {
6757 if (generate_add_instr(cctx,
Bram Moolenaar752fc692021-01-04 21:57:11 +01006758 operator_type(lhs.lhs_member_type, stacktype),
6759 lhs.lhs_member_type, stacktype) == FAIL)
Bram Moolenaardd29f1b2020-08-07 20:46:20 +02006760 goto theend;
6761 }
Bram Moolenaar93ad1472020-08-19 22:02:41 +02006762 else if (generate_two_op(cctx, op) == FAIL)
6763 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006764 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006765
Bram Moolenaar752fc692021-01-04 21:57:11 +01006766 if (lhs.lhs_has_index)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006767 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006768 // Use the info in "lhs" to store the value at the index in the
6769 // list or dict.
6770 if (compile_assign_unlet(var_start, &lhs, TRUE, rhs_type, cctx)
6771 == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006772 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006773 }
6774 else
6775 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006776 if (is_decl && cmdidx == CMD_const && (lhs.lhs_dest == dest_script
Bram Moolenaard877a572021-04-01 19:42:48 +02006777 || lhs.lhs_dest == dest_global
Bram Moolenaar752fc692021-01-04 21:57:11 +01006778 || lhs.lhs_dest == dest_local))
Bram Moolenaar30fd8202020-09-26 15:09:30 +02006779 // ":const var": lock the value, but not referenced variables
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02006780 generate_LOCKCONST(cctx);
6781
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006782 if (is_decl
Bram Moolenaar752fc692021-01-04 21:57:11 +01006783 && (lhs.lhs_type->tt_type == VAR_DICT
6784 || lhs.lhs_type->tt_type == VAR_LIST)
6785 && lhs.lhs_type->tt_member != NULL
6786 && lhs.lhs_type->tt_member != &t_any
6787 && lhs.lhs_type->tt_member != &t_unknown)
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006788 // Set the type in the list or dict, so that it can be checked,
6789 // also in legacy script.
Bram Moolenaar752fc692021-01-04 21:57:11 +01006790 generate_SETTYPE(cctx, lhs.lhs_type);
Bram Moolenaaraa210a32021-01-02 15:41:03 +01006791
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02006792 if (generate_store_lhs(cctx, &lhs, instr_count) == FAIL)
6793 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006794 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006795
6796 if (var_idx + 1 < var_count)
Bram Moolenaar752fc692021-01-04 21:57:11 +01006797 var_start = skipwhite(lhs.lhs_dest_end + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006798 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006799
6800 // for "[var, var] = expr" drop the "expr" value
Bram Moolenaar9af78762020-06-16 11:34:42 +02006801 if (var_count > 0 && !semicolon)
6802 {
Bram Moolenaarec792292020-12-13 21:26:56 +01006803 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
Bram Moolenaar9af78762020-06-16 11:34:42 +02006804 goto theend;
6805 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02006806
Bram Moolenaarb2097502020-07-19 17:17:02 +02006807 ret = skipwhite(end);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006808
6809theend:
Bram Moolenaar752fc692021-01-04 21:57:11 +01006810 vim_free(lhs.lhs_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006811 return ret;
6812}
6813
6814/*
Bram Moolenaar17126b12021-01-07 22:03:02 +01006815 * Check for an assignment at "eap->cmd", compile it if found.
6816 * Return NOTDONE if there is none, FAIL for failure, OK if done.
6817 */
6818 static int
6819may_compile_assignment(exarg_T *eap, char_u **line, cctx_T *cctx)
6820{
6821 char_u *pskip;
6822 char_u *p;
6823
6824 // Assuming the command starts with a variable or function name,
6825 // find what follows.
6826 // Skip over "var.member", "var[idx]" and the like.
6827 // Also "&opt = val", "$ENV = val" and "@r = val".
6828 pskip = (*eap->cmd == '&' || *eap->cmd == '$' || *eap->cmd == '@')
6829 ? eap->cmd + 1 : eap->cmd;
6830 p = to_name_end(pskip, TRUE);
6831 if (p > eap->cmd && *p != NUL)
6832 {
6833 char_u *var_end;
6834 int oplen;
6835 int heredoc;
6836
6837 if (eap->cmd[0] == '@')
6838 var_end = eap->cmd + 2;
6839 else
6840 var_end = find_name_end(pskip, NULL, NULL,
6841 FNE_CHECK_START | FNE_INCL_BR);
6842 oplen = assignment_len(skipwhite(var_end), &heredoc);
6843 if (oplen > 0)
6844 {
6845 size_t len = p - eap->cmd;
6846
6847 // Recognize an assignment if we recognize the variable
6848 // name:
6849 // "g:var = expr"
6850 // "local = expr" where "local" is a local var.
6851 // "script = expr" where "script" is a script-local var.
6852 // "import = expr" where "import" is an imported var
6853 // "&opt = expr"
6854 // "$ENV = expr"
6855 // "@r = expr"
6856 if (*eap->cmd == '&'
6857 || *eap->cmd == '$'
6858 || *eap->cmd == '@'
6859 || ((len) > 2 && eap->cmd[1] == ':')
Bram Moolenaare0890d62021-02-17 14:52:14 +01006860 || variable_exists(eap->cmd, len, cctx))
Bram Moolenaar17126b12021-01-07 22:03:02 +01006861 {
6862 *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx);
6863 if (*line == NULL || *line == eap->cmd)
6864 return FAIL;
6865 return OK;
6866 }
6867 }
6868 }
6869
6870 if (*eap->cmd == '[')
6871 {
6872 // [var, var] = expr
6873 *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx);
6874 if (*line == NULL)
6875 return FAIL;
6876 if (*line != eap->cmd)
6877 return OK;
6878 }
6879 return NOTDONE;
6880}
6881
6882/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006883 * Check if "name" can be "unlet".
6884 */
6885 int
6886check_vim9_unlet(char_u *name)
6887{
6888 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
6889 {
Bram Moolenaar84367732020-08-23 15:21:55 +02006890 // "unlet s:var" is allowed in legacy script.
6891 if (*name == 's' && !script_is_vim9())
6892 return OK;
Bram Moolenaar451c2e32020-08-15 16:33:28 +02006893 semsg(_(e_cannot_unlet_str), name);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006894 return FAIL;
6895 }
6896 return OK;
6897}
6898
6899/*
6900 * Callback passed to ex_unletlock().
6901 */
6902 static int
6903compile_unlet(
6904 lval_T *lvp,
6905 char_u *name_end,
6906 exarg_T *eap,
6907 int deep UNUSED,
6908 void *coookie)
6909{
Bram Moolenaar752fc692021-01-04 21:57:11 +01006910 cctx_T *cctx = coookie;
6911 char_u *p = lvp->ll_name;
6912 int cc = *name_end;
6913 int ret = OK;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006914
Bram Moolenaar752fc692021-01-04 21:57:11 +01006915 if (cctx->ctx_skip == SKIP_YES)
6916 return OK;
6917
6918 *name_end = NUL;
6919 if (*p == '$')
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006920 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006921 // :unlet $ENV_VAR
6922 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
6923 }
6924 else if (vim_strchr(p, '.') != NULL || vim_strchr(p, '[') != NULL)
6925 {
6926 lhs_T lhs;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006927
Bram Moolenaar752fc692021-01-04 21:57:11 +01006928 // This is similar to assigning: lookup the list/dict, compile the
6929 // idx/key. Then instead of storing the value unlet the item.
6930 // unlet {list}[idx]
6931 // unlet {dict}[key] dict.key
6932 //
6933 // Figure out the LHS type and other properties.
6934 //
6935 ret = compile_lhs(p, &lhs, CMD_unlet, FALSE, 0, cctx);
6936
6937 // : unlet an indexed item
6938 if (!lhs.lhs_has_index)
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01006939 {
Bram Moolenaar752fc692021-01-04 21:57:11 +01006940 iemsg("called compile_lhs() without an index");
6941 ret = FAIL;
6942 }
6943 else
6944 {
6945 // Use the info in "lhs" to unlet the item at the index in the
6946 // list or dict.
6947 ret = compile_assign_unlet(p, &lhs, FALSE, &t_void, cctx);
Bram Moolenaar2ef951d2021-01-03 20:55:26 +01006948 }
6949
Bram Moolenaar752fc692021-01-04 21:57:11 +01006950 vim_free(lhs.lhs_name);
6951 }
6952 else if (check_vim9_unlet(p) == FAIL)
6953 {
6954 ret = FAIL;
6955 }
6956 else
6957 {
6958 // Normal name. Only supports g:, w:, t: and b: namespaces.
6959 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006960 }
6961
Bram Moolenaar752fc692021-01-04 21:57:11 +01006962 *name_end = cc;
6963 return ret;
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006964}
6965
6966/*
Bram Moolenaarb2cb6c82021-03-28 20:38:34 +02006967 * Callback passed to ex_unletlock().
6968 */
6969 static int
6970compile_lock_unlock(
6971 lval_T *lvp,
6972 char_u *name_end,
6973 exarg_T *eap,
6974 int deep UNUSED,
6975 void *coookie)
6976{
6977 cctx_T *cctx = coookie;
6978 int cc = *name_end;
6979 char_u *p = lvp->ll_name;
6980 int ret = OK;
6981 size_t len;
6982 char_u *buf;
6983
6984 if (cctx->ctx_skip == SKIP_YES)
6985 return OK;
6986
6987 // Cannot use :lockvar and :unlockvar on local variables.
6988 if (p[1] != ':')
6989 {
6990 char_u *end = skip_var_one(p, FALSE);
6991
6992 if (lookup_local(p, end - p, NULL, cctx) == OK)
6993 {
6994 emsg(_(e_cannot_lock_unlock_local_variable));
6995 return FAIL;
6996 }
6997 }
6998
6999 // Checking is done at runtime.
7000 *name_end = NUL;
7001 len = name_end - p + 20;
7002 buf = alloc(len);
7003 if (buf == NULL)
7004 ret = FAIL;
7005 else
7006 {
7007 vim_snprintf((char *)buf, len, "%s %s",
7008 eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
7009 p);
7010 ret = generate_EXEC(cctx, buf);
7011
7012 vim_free(buf);
7013 *name_end = cc;
7014 }
7015 return ret;
7016}
7017
7018/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007019 * compile "unlet var", "lock var" and "unlock var"
7020 * "arg" points to "var".
7021 */
7022 static char_u *
7023compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
7024{
Bram Moolenaarb2cb6c82021-03-28 20:38:34 +02007025 ex_unletlock(eap, arg, 0, GLV_NO_AUTOLOAD | GLV_COMPILING,
7026 eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
7027 cctx);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007028 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
7029}
7030
7031/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007032 * Compile an :import command.
7033 */
7034 static char_u *
7035compile_import(char_u *arg, cctx_T *cctx)
7036{
Bram Moolenaar1c991142020-07-04 13:15:31 +02007037 return handle_import(arg, &cctx->ctx_imports, 0, NULL, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007038}
7039
7040/*
7041 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
7042 */
7043 static int
7044compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
7045{
7046 garray_T *instr = &cctx->ctx_instr;
7047 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
7048
7049 if (endlabel == NULL)
7050 return FAIL;
7051 endlabel->el_next = *el;
7052 *el = endlabel;
7053 endlabel->el_end_label = instr->ga_len;
7054
7055 generate_JUMP(cctx, when, 0);
7056 return OK;
7057}
7058
7059 static void
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007060compile_fill_jump_to_end(endlabel_T **el, int jump_where, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007061{
7062 garray_T *instr = &cctx->ctx_instr;
7063
7064 while (*el != NULL)
7065 {
7066 endlabel_T *cur = (*el);
7067 isn_T *isn;
7068
7069 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007070 isn->isn_arg.jump.jump_where = jump_where;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007071 *el = cur->el_next;
7072 vim_free(cur);
7073 }
7074}
7075
Bram Moolenaar3cca2992020-04-02 22:57:36 +02007076 static void
7077compile_free_jump_to_end(endlabel_T **el)
7078{
7079 while (*el != NULL)
7080 {
7081 endlabel_T *cur = (*el);
7082
7083 *el = cur->el_next;
7084 vim_free(cur);
7085 }
7086}
7087
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007088/*
7089 * Create a new scope and set up the generic items.
7090 */
7091 static scope_T *
7092new_scope(cctx_T *cctx, scopetype_T type)
7093{
7094 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
7095
7096 if (scope == NULL)
7097 return NULL;
7098 scope->se_outer = cctx->ctx_scope;
7099 cctx->ctx_scope = scope;
7100 scope->se_type = type;
7101 scope->se_local_count = cctx->ctx_locals.ga_len;
7102 return scope;
7103}
7104
7105/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007106 * Free the current scope and go back to the outer scope.
7107 */
7108 static void
7109drop_scope(cctx_T *cctx)
7110{
7111 scope_T *scope = cctx->ctx_scope;
7112
7113 if (scope == NULL)
7114 {
7115 iemsg("calling drop_scope() without a scope");
7116 return;
7117 }
7118 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02007119 switch (scope->se_type)
7120 {
7121 case IF_SCOPE:
7122 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
7123 case FOR_SCOPE:
7124 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
7125 case WHILE_SCOPE:
7126 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
7127 case TRY_SCOPE:
7128 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
7129 case NO_SCOPE:
7130 case BLOCK_SCOPE:
7131 break;
7132 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007133 vim_free(scope);
7134}
7135
7136/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007137 * compile "if expr"
7138 *
7139 * "if expr" Produces instructions:
7140 * EVAL expr Push result of "expr"
7141 * JUMP_IF_FALSE end
7142 * ... body ...
7143 * end:
7144 *
7145 * "if expr | else" Produces instructions:
7146 * EVAL expr Push result of "expr"
7147 * JUMP_IF_FALSE else
7148 * ... body ...
7149 * JUMP_ALWAYS end
7150 * else:
7151 * ... body ...
7152 * end:
7153 *
7154 * "if expr1 | elseif expr2 | else" Produces instructions:
7155 * EVAL expr Push result of "expr"
7156 * JUMP_IF_FALSE elseif
7157 * ... body ...
7158 * JUMP_ALWAYS end
7159 * elseif:
7160 * EVAL expr Push result of "expr"
7161 * JUMP_IF_FALSE else
7162 * ... body ...
7163 * JUMP_ALWAYS end
7164 * else:
7165 * ... body ...
7166 * end:
7167 */
7168 static char_u *
7169compile_if(char_u *arg, cctx_T *cctx)
7170{
7171 char_u *p = arg;
7172 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007173 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007174 scope_T *scope;
Bram Moolenaarefd88552020-06-18 20:50:10 +02007175 skip_T skip_save = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007176 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007177
Bram Moolenaara5565e42020-05-09 15:44:01 +02007178 CLEAR_FIELD(ppconst);
7179 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007180 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02007181 clear_ppconst(&ppconst);
7182 return NULL;
7183 }
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01007184 if (!ends_excmd2(arg, skipwhite(p)))
7185 {
7186 semsg(_(e_trailing_arg), p);
7187 return NULL;
7188 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02007189 if (cctx->ctx_skip == SKIP_YES)
7190 clear_ppconst(&ppconst);
7191 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaara5565e42020-05-09 15:44:01 +02007192 {
Bram Moolenaar13106602020-10-04 16:06:05 +02007193 int error = FALSE;
7194 int v;
7195
Bram Moolenaara5565e42020-05-09 15:44:01 +02007196 // The expression results in a constant.
Bram Moolenaar13106602020-10-04 16:06:05 +02007197 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
Bram Moolenaardda749c2020-10-04 17:24:29 +02007198 clear_ppconst(&ppconst);
Bram Moolenaar13106602020-10-04 16:06:05 +02007199 if (error)
7200 return NULL;
7201 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007202 }
7203 else
7204 {
7205 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007206 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007207 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007208 return NULL;
Bram Moolenaar13106602020-10-04 16:06:05 +02007209 if (bool_on_stack(cctx) == FAIL)
7210 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007211 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007212
Bram Moolenaara91a7132021-03-25 21:12:15 +01007213 // CMDMOD_REV must come before the jump
7214 generate_undo_cmdmods(cctx);
7215
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007216 scope = new_scope(cctx, IF_SCOPE);
7217 if (scope == NULL)
7218 return NULL;
Bram Moolenaarefd88552020-06-18 20:50:10 +02007219 scope->se_skip_save = skip_save;
7220 // "is_had_return" will be reset if any block does not end in :return
7221 scope->se_u.se_if.is_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007222
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007223 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007224 {
7225 // "where" is set when ":elseif", "else" or ":endif" is found
7226 scope->se_u.se_if.is_if_label = instr->ga_len;
7227 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
7228 }
7229 else
7230 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007231
Bram Moolenaarced68a02021-01-24 17:53:47 +01007232#ifdef FEAT_PROFILE
7233 if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES
7234 && skip_save != SKIP_YES)
7235 {
7236 // generated a profile start, need to generate a profile end, since it
7237 // won't be done after returning
7238 cctx->ctx_skip = SKIP_NOT;
7239 generate_instr(cctx, ISN_PROF_END);
7240 cctx->ctx_skip = SKIP_YES;
7241 }
7242#endif
7243
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007244 return p;
7245}
7246
7247 static char_u *
7248compile_elseif(char_u *arg, cctx_T *cctx)
7249{
7250 char_u *p = arg;
7251 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02007252 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007253 isn_T *isn;
7254 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02007255 ppconst_T ppconst;
Bram Moolenaar749639e2020-08-27 23:08:47 +02007256 skip_T save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007257
7258 if (scope == NULL || scope->se_type != IF_SCOPE)
7259 {
7260 emsg(_(e_elseif_without_if));
7261 return NULL;
7262 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01007263 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007264 if (!cctx->ctx_had_return)
7265 scope->se_u.se_if.is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007266
Bram Moolenaarced68a02021-01-24 17:53:47 +01007267 if (cctx->ctx_skip == SKIP_NOT)
7268 {
7269 // previous block was executed, this one and following will not
7270 cctx->ctx_skip = SKIP_YES;
7271 scope->se_u.se_if.is_seen_skip_not = TRUE;
7272 }
7273 if (scope->se_u.se_if.is_seen_skip_not)
7274 {
7275 // A previous block was executed, skip over expression and bail out.
Bram Moolenaara91a7132021-03-25 21:12:15 +01007276 // Do not count the "elseif" for profiling and cmdmod
7277 instr->ga_len = current_instr_idx(cctx);
7278
Bram Moolenaarced68a02021-01-24 17:53:47 +01007279 skip_expr_cctx(&p, cctx);
7280 return p;
7281 }
7282
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007283 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007284 {
Bram Moolenaara91a7132021-03-25 21:12:15 +01007285 int moved_cmdmod = FALSE;
7286
7287 // Move any CMDMOD instruction to after the jump
7288 if (((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type == ISN_CMDMOD)
7289 {
7290 if (ga_grow(instr, 1) == FAIL)
7291 return NULL;
7292 ((isn_T *)instr->ga_data)[instr->ga_len] =
7293 ((isn_T *)instr->ga_data)[instr->ga_len - 1];
7294 --instr->ga_len;
7295 moved_cmdmod = TRUE;
7296 }
7297
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007298 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007299 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007300 return NULL;
7301 // previous "if" or "elseif" jumps here
7302 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
7303 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaara91a7132021-03-25 21:12:15 +01007304 if (moved_cmdmod)
7305 ++instr->ga_len;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007306 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007307
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007308 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02007309 CLEAR_FIELD(ppconst);
Bram Moolenaar749639e2020-08-27 23:08:47 +02007310 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarced68a02021-01-24 17:53:47 +01007311 {
Bram Moolenaar749639e2020-08-27 23:08:47 +02007312 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaarced68a02021-01-24 17:53:47 +01007313#ifdef FEAT_PROFILE
7314 if (cctx->ctx_profiling)
7315 {
7316 // the previous block was skipped, need to profile this line
7317 generate_instr(cctx, ISN_PROF_START);
7318 instr_count = instr->ga_len;
7319 }
7320#endif
7321 }
Bram Moolenaar7f141552020-05-09 17:35:53 +02007322 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007323 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02007324 clear_ppconst(&ppconst);
7325 return NULL;
7326 }
Bram Moolenaar749639e2020-08-27 23:08:47 +02007327 cctx->ctx_skip = save_skip;
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01007328 if (!ends_excmd2(arg, skipwhite(p)))
7329 {
7330 semsg(_(e_trailing_arg), p);
7331 return NULL;
7332 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02007333 if (scope->se_skip_save == SKIP_YES)
7334 clear_ppconst(&ppconst);
7335 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaar7f141552020-05-09 17:35:53 +02007336 {
Bram Moolenaar13106602020-10-04 16:06:05 +02007337 int error = FALSE;
7338 int v;
7339
Bram Moolenaar7f141552020-05-09 17:35:53 +02007340 // The expression results in a constant.
7341 // TODO: how about nesting?
Bram Moolenaar13106602020-10-04 16:06:05 +02007342 v = tv_get_bool_chk(&ppconst.pp_tv[0], &error);
7343 if (error)
7344 return NULL;
7345 cctx->ctx_skip = v ? SKIP_NOT : SKIP_YES;
Bram Moolenaar7f141552020-05-09 17:35:53 +02007346 clear_ppconst(&ppconst);
7347 scope->se_u.se_if.is_if_label = -1;
7348 }
7349 else
7350 {
7351 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007352 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaar7f141552020-05-09 17:35:53 +02007353 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007354 return NULL;
Bram Moolenaar13106602020-10-04 16:06:05 +02007355 if (bool_on_stack(cctx) == FAIL)
7356 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007357
Bram Moolenaara91a7132021-03-25 21:12:15 +01007358 // CMDMOD_REV must come before the jump
7359 generate_undo_cmdmods(cctx);
7360
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007361 // "where" is set when ":elseif", "else" or ":endif" is found
7362 scope->se_u.se_if.is_if_label = instr->ga_len;
7363 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
7364 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007365
7366 return p;
7367}
7368
7369 static char_u *
7370compile_else(char_u *arg, cctx_T *cctx)
7371{
7372 char_u *p = arg;
7373 garray_T *instr = &cctx->ctx_instr;
7374 isn_T *isn;
7375 scope_T *scope = cctx->ctx_scope;
7376
7377 if (scope == NULL || scope->se_type != IF_SCOPE)
7378 {
7379 emsg(_(e_else_without_if));
7380 return NULL;
7381 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01007382 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007383 if (!cctx->ctx_had_return)
7384 scope->se_u.se_if.is_had_return = FALSE;
7385 scope->se_u.se_if.is_seen_else = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007386
Bram Moolenaarced68a02021-01-24 17:53:47 +01007387#ifdef FEAT_PROFILE
7388 if (cctx->ctx_profiling)
7389 {
7390 if (cctx->ctx_skip == SKIP_NOT
7391 && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
7392 .isn_type == ISN_PROF_START)
7393 // the previous block was executed, do not count "else" for profiling
7394 --instr->ga_len;
7395 if (cctx->ctx_skip == SKIP_YES && !scope->se_u.se_if.is_seen_skip_not)
7396 {
7397 // the previous block was not executed, this one will, do count the
7398 // "else" for profiling
7399 cctx->ctx_skip = SKIP_NOT;
7400 generate_instr(cctx, ISN_PROF_END);
7401 generate_instr(cctx, ISN_PROF_START);
7402 cctx->ctx_skip = SKIP_YES;
7403 }
7404 }
7405#endif
7406
7407 if (!scope->se_u.se_if.is_seen_skip_not && scope->se_skip_save != SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007408 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02007409 // jump from previous block to the end, unless the else block is empty
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007410 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007411 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02007412 if (!cctx->ctx_had_return
7413 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
7414 JUMP_ALWAYS, cctx) == FAIL)
7415 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007416 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007417
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007418 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02007419 {
7420 if (scope->se_u.se_if.is_if_label >= 0)
7421 {
7422 // previous "if" or "elseif" jumps here
7423 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
7424 isn->isn_arg.jump.jump_where = instr->ga_len;
7425 scope->se_u.se_if.is_if_label = -1;
7426 }
7427 }
7428
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02007429 if (cctx->ctx_skip != SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02007430 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
7431 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007432
7433 return p;
7434}
7435
7436 static char_u *
7437compile_endif(char_u *arg, cctx_T *cctx)
7438{
7439 scope_T *scope = cctx->ctx_scope;
7440 ifscope_T *ifscope;
7441 garray_T *instr = &cctx->ctx_instr;
7442 isn_T *isn;
7443
Bram Moolenaarfa984412021-03-25 22:15:28 +01007444 if (misplaced_cmdmod(cctx))
7445 return NULL;
7446
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007447 if (scope == NULL || scope->se_type != IF_SCOPE)
7448 {
7449 emsg(_(e_endif_without_if));
7450 return NULL;
7451 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007452 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007453 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007454 if (!cctx->ctx_had_return)
7455 ifscope->is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007456
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007457 if (scope->se_u.se_if.is_if_label >= 0)
7458 {
7459 // previous "if" or "elseif" jumps here
7460 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
7461 isn->isn_arg.jump.jump_where = instr->ga_len;
7462 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007463 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007464 compile_fill_jump_to_end(&ifscope->is_end_label, instr->ga_len, cctx);
Bram Moolenaarced68a02021-01-24 17:53:47 +01007465
7466#ifdef FEAT_PROFILE
7467 // even when skipping we count the endif as executed, unless the block it's
7468 // in is skipped
7469 if (cctx->ctx_profiling && cctx->ctx_skip == SKIP_YES
7470 && scope->se_skip_save != SKIP_YES)
7471 {
7472 cctx->ctx_skip = SKIP_NOT;
7473 generate_instr(cctx, ISN_PROF_START);
7474 }
7475#endif
Bram Moolenaarefd88552020-06-18 20:50:10 +02007476 cctx->ctx_skip = scope->se_skip_save;
7477
7478 // If all the blocks end in :return and there is an :else then the
7479 // had_return flag is set.
7480 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007481
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007482 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007483 return arg;
7484}
7485
7486/*
Bram Moolenaar792f7862020-11-23 08:31:18 +01007487 * Compile "for var in expr":
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007488 *
7489 * Produces instructions:
7490 * PUSHNR -1
7491 * STORE loop-idx Set index to -1
Bram Moolenaar792f7862020-11-23 08:31:18 +01007492 * EVAL expr result of "expr" on top of stack
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007493 * top: FOR loop-idx, end Increment index, use list on bottom of stack
7494 * - if beyond end, jump to "end"
7495 * - otherwise get item from list and push it
7496 * STORE var Store item in "var"
7497 * ... body ...
7498 * JUMP top Jump back to repeat
7499 * end: DROP Drop the result of "expr"
7500 *
Bram Moolenaar792f7862020-11-23 08:31:18 +01007501 * Compile "for [var1, var2] in expr" - as above, but instead of "STORE var":
7502 * UNPACK 2 Split item in 2
7503 * STORE var1 Store item in "var1"
7504 * STORE var2 Store item in "var2"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007505 */
7506 static char_u *
Bram Moolenaar792f7862020-11-23 08:31:18 +01007507compile_for(char_u *arg_start, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007508{
Bram Moolenaar792f7862020-11-23 08:31:18 +01007509 char_u *arg;
7510 char_u *arg_end;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007511 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007512 char_u *p;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007513 char_u *wp;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007514 int var_count = 0;
7515 int semicolon = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007516 size_t varlen;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007517 garray_T *stack = &cctx->ctx_type_stack;
7518 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007519 lvar_T *loop_lvar; // loop iteration variable
7520 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007521 type_T *vartype;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007522 type_T *item_type = &t_any;
7523 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007524
Bram Moolenaar792f7862020-11-23 08:31:18 +01007525 p = skip_var_list(arg_start, TRUE, &var_count, &semicolon, FALSE);
Bram Moolenaar036d0712021-01-17 20:23:38 +01007526 if (p == NULL)
7527 return NULL;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007528 if (var_count == 0)
7529 var_count = 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007530
7531 // consume "in"
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007532 wp = p;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007533 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
7534 return NULL;
7535 if (STRNCMP(p, "in", 2) != 0 || !IS_WHITE_OR_NUL(p[2]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007536 {
7537 emsg(_(e_missing_in));
7538 return NULL;
7539 }
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007540 wp = p + 2;
Bram Moolenaar38bd8de2020-12-02 13:23:36 +01007541 if (may_get_next_line_error(wp, &p, cctx) == FAIL)
7542 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007543
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007544 scope = new_scope(cctx, FOR_SCOPE);
7545 if (scope == NULL)
7546 return NULL;
7547
Bram Moolenaar792f7862020-11-23 08:31:18 +01007548 // Reserve a variable to store the loop iteration counter and initialize it
7549 // to -1.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007550 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
7551 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007552 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007553 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007554 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007555 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007556 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007557 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007558
7559 // compile "expr", it remains on the stack until "endfor"
7560 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02007561 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007562 {
7563 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007564 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007565 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007566 arg_end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007567
Bram Moolenaard551d6c2021-04-18 13:15:58 +02007568 // If we know the type of "var" and it is a not a supported type we can
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01007569 // give an error now.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007570 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01007571 if (vartype->tt_type != VAR_LIST && vartype->tt_type != VAR_STRING
Bram Moolenaard551d6c2021-04-18 13:15:58 +02007572 && vartype->tt_type != VAR_BLOB && vartype->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007573 {
Bram Moolenaar74e54fc2021-03-26 20:41:29 +01007574 semsg(_(e_for_loop_on_str_not_supported),
7575 vartype_name(vartype->tt_type));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02007576 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007577 return NULL;
7578 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007579
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007580 if (vartype->tt_type == VAR_STRING)
7581 item_type = &t_string;
Bram Moolenaard551d6c2021-04-18 13:15:58 +02007582 else if (vartype->tt_type == VAR_BLOB)
7583 item_type = &t_number;
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007584 else if (vartype->tt_type == VAR_LIST
7585 && vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar792f7862020-11-23 08:31:18 +01007586 {
7587 if (var_count == 1)
7588 item_type = vartype->tt_member;
7589 else if (vartype->tt_member->tt_type == VAR_LIST
7590 && vartype->tt_member->tt_member->tt_type != VAR_ANY)
Bram Moolenaard551d6c2021-04-18 13:15:58 +02007591 // TODO: should get the type for each lhs
Bram Moolenaar792f7862020-11-23 08:31:18 +01007592 item_type = vartype->tt_member->tt_member;
7593 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007594
Bram Moolenaara91a7132021-03-25 21:12:15 +01007595 // CMDMOD_REV must come before the FOR instruction
7596 generate_undo_cmdmods(cctx);
7597
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007598 // "for_end" is set when ":endfor" is found
Bram Moolenaara91a7132021-03-25 21:12:15 +01007599 scope->se_u.se_for.fs_top_label = current_instr_idx(cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007600 generate_FOR(cctx, loop_lvar->lv_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007601
Bram Moolenaar792f7862020-11-23 08:31:18 +01007602 arg = arg_start;
7603 if (var_count > 1)
7604 {
7605 generate_UNPACK(cctx, var_count, semicolon);
7606 arg = skipwhite(arg + 1); // skip white after '['
7607
7608 // the list item is replaced by a number of items
7609 if (ga_grow(stack, var_count - 1) == FAIL)
7610 {
7611 drop_scope(cctx);
7612 return NULL;
7613 }
7614 --stack->ga_len;
7615 for (idx = 0; idx < var_count; ++idx)
7616 {
7617 ((type_T **)stack->ga_data)[stack->ga_len] =
7618 (semicolon && idx == 0) ? vartype : item_type;
7619 ++stack->ga_len;
7620 }
7621 }
7622
7623 for (idx = 0; idx < var_count; ++idx)
7624 {
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007625 assign_dest_T dest = dest_local;
7626 int opt_flags = 0;
7627 int vimvaridx = -1;
7628 type_T *type = &t_any;
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007629 type_T *lhs_type = &t_any;
7630 where_T where;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007631
7632 p = skip_var_one(arg, FALSE);
Bram Moolenaar792f7862020-11-23 08:31:18 +01007633 varlen = p - arg;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007634 name = vim_strnsave(arg, varlen);
7635 if (name == NULL)
7636 goto failed;
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007637 if (*p == ':')
7638 {
7639 p = skipwhite(p + 1);
7640 lhs_type = parse_type(&p, cctx->ctx_type_list, TRUE);
7641 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007642
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007643 // TODO: script var not supported?
7644 if (get_var_dest(name, &dest, CMD_for, &opt_flags,
7645 &vimvaridx, &type, cctx) == FAIL)
7646 goto failed;
7647 if (dest != dest_local)
Bram Moolenaar792f7862020-11-23 08:31:18 +01007648 {
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007649 if (generate_store_var(cctx, dest, opt_flags, vimvaridx,
7650 0, 0, type, name) == FAIL)
7651 goto failed;
Bram Moolenaar792f7862020-11-23 08:31:18 +01007652 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007653 else
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007654 {
Bram Moolenaar709664c2020-12-12 14:33:41 +01007655 if (lookup_local(arg, varlen, NULL, cctx) == OK)
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007656 {
7657 semsg(_(e_variable_already_declared), arg);
7658 goto failed;
7659 }
7660
Bram Moolenaarea870692020-12-02 14:24:30 +01007661 if (STRNCMP(name, "s:", 2) == 0)
7662 {
7663 semsg(_(e_cannot_declare_script_variable_in_function), name);
7664 goto failed;
7665 }
7666
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007667 // Reserve a variable to store "var".
Bram Moolenaarfe090eb2021-04-15 21:48:32 +02007668 where.wt_index = var_count > 1 ? idx + 1 : 0;
7669 where.wt_variable = TRUE;
7670 if (lhs_type == &t_any)
7671 lhs_type = item_type;
7672 else if (item_type != &t_unknown
7673 && !(var_count > 1 && item_type == &t_any)
7674 && check_type(lhs_type, item_type, TRUE, where) == FAIL)
7675 goto failed;
7676 var_lvar = reserve_local(cctx, arg, varlen, TRUE, lhs_type);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007677 if (var_lvar == NULL)
7678 // out of memory or used as an argument
7679 goto failed;
7680
7681 if (semicolon && idx == var_count - 1)
7682 var_lvar->lv_type = vartype;
7683 else
7684 var_lvar->lv_type = item_type;
7685 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
7686 }
Bram Moolenaar792f7862020-11-23 08:31:18 +01007687
7688 if (*p == ',' || *p == ';')
7689 ++p;
7690 arg = skipwhite(p);
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007691 vim_free(name);
Bram Moolenaar792f7862020-11-23 08:31:18 +01007692 }
7693
7694 return arg_end;
Bram Moolenaar4b8a0652020-12-01 16:30:44 +01007695
7696failed:
7697 vim_free(name);
7698 drop_scope(cctx);
7699 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007700}
7701
7702/*
7703 * compile "endfor"
7704 */
7705 static char_u *
7706compile_endfor(char_u *arg, cctx_T *cctx)
7707{
7708 garray_T *instr = &cctx->ctx_instr;
7709 scope_T *scope = cctx->ctx_scope;
7710 forscope_T *forscope;
7711 isn_T *isn;
7712
Bram Moolenaarfa984412021-03-25 22:15:28 +01007713 if (misplaced_cmdmod(cctx))
7714 return NULL;
Bram Moolenaara91a7132021-03-25 21:12:15 +01007715
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007716 if (scope == NULL || scope->se_type != FOR_SCOPE)
7717 {
7718 emsg(_(e_for));
7719 return NULL;
7720 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007721 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007722 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007723 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007724
7725 // At end of ":for" scope jump back to the FOR instruction.
7726 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
7727
7728 // Fill in the "end" label in the FOR statement so it can jump here
7729 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
7730 isn->isn_arg.forloop.for_end = instr->ga_len;
7731
7732 // Fill in the "end" label any BREAK statements
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007733 compile_fill_jump_to_end(&forscope->fs_end_label, instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007734
7735 // Below the ":for" scope drop the "expr" list from the stack.
7736 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
7737 return NULL;
7738
7739 vim_free(scope);
7740
7741 return arg;
7742}
7743
7744/*
7745 * compile "while expr"
7746 *
7747 * Produces instructions:
7748 * top: EVAL expr Push result of "expr"
7749 * JUMP_IF_FALSE end jump if false
7750 * ... body ...
7751 * JUMP top Jump back to repeat
7752 * end:
7753 *
7754 */
7755 static char_u *
7756compile_while(char_u *arg, cctx_T *cctx)
7757{
7758 char_u *p = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007759 scope_T *scope;
7760
7761 scope = new_scope(cctx, WHILE_SCOPE);
7762 if (scope == NULL)
7763 return NULL;
7764
Bram Moolenaara91a7132021-03-25 21:12:15 +01007765 // "endwhile" jumps back here, one before when profiling or using cmdmods
7766 scope->se_u.se_while.ws_top_label = current_instr_idx(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007767
7768 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02007769 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007770 return NULL;
Bram Moolenaar6628b7e2021-02-07 16:33:35 +01007771 if (!ends_excmd2(arg, skipwhite(p)))
7772 {
7773 semsg(_(e_trailing_arg), p);
7774 return NULL;
7775 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007776
Bram Moolenaar13106602020-10-04 16:06:05 +02007777 if (bool_on_stack(cctx) == FAIL)
7778 return FAIL;
7779
Bram Moolenaara91a7132021-03-25 21:12:15 +01007780 // CMDMOD_REV must come before the jump
7781 generate_undo_cmdmods(cctx);
7782
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007783 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007784 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007785 JUMP_IF_FALSE, cctx) == FAIL)
7786 return FAIL;
7787
7788 return p;
7789}
7790
7791/*
7792 * compile "endwhile"
7793 */
7794 static char_u *
7795compile_endwhile(char_u *arg, cctx_T *cctx)
7796{
7797 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007798 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007799
Bram Moolenaarfa984412021-03-25 22:15:28 +01007800 if (misplaced_cmdmod(cctx))
7801 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007802 if (scope == NULL || scope->se_type != WHILE_SCOPE)
7803 {
7804 emsg(_(e_while));
7805 return NULL;
7806 }
7807 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007808 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007809
Bram Moolenaarf002a412021-01-24 13:34:18 +01007810#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01007811 // count the endwhile before jumping
7812 may_generate_prof_end(cctx, cctx->ctx_lnum);
Bram Moolenaarf002a412021-01-24 13:34:18 +01007813#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01007814
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007815 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007816 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007817
7818 // Fill in the "end" label in the WHILE statement so it can jump here.
7819 // And in any jumps for ":break"
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01007820 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label,
7821 instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007822
7823 vim_free(scope);
7824
7825 return arg;
7826}
7827
7828/*
7829 * compile "continue"
7830 */
7831 static char_u *
7832compile_continue(char_u *arg, cctx_T *cctx)
7833{
7834 scope_T *scope = cctx->ctx_scope;
Bram Moolenaarc150c092021-02-13 15:02:46 +01007835 int try_scopes = 0;
7836 int loop_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007837
7838 for (;;)
7839 {
7840 if (scope == NULL)
7841 {
7842 emsg(_(e_continue));
7843 return NULL;
7844 }
Bram Moolenaarc150c092021-02-13 15:02:46 +01007845 if (scope->se_type == FOR_SCOPE)
7846 {
7847 loop_label = scope->se_u.se_for.fs_top_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007848 break;
Bram Moolenaarc150c092021-02-13 15:02:46 +01007849 }
7850 if (scope->se_type == WHILE_SCOPE)
7851 {
7852 loop_label = scope->se_u.se_while.ws_top_label;
7853 break;
7854 }
7855 if (scope->se_type == TRY_SCOPE)
7856 ++try_scopes;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007857 scope = scope->se_outer;
7858 }
7859
Bram Moolenaarc150c092021-02-13 15:02:46 +01007860 if (try_scopes > 0)
7861 // Inside one or more try/catch blocks we first need to jump to the
7862 // "finally" or "endtry" to cleanup.
7863 generate_TRYCONT(cctx, try_scopes, loop_label);
7864 else
7865 // Jump back to the FOR or WHILE instruction.
7866 generate_JUMP(cctx, JUMP_ALWAYS, loop_label);
7867
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007868 return arg;
7869}
7870
7871/*
7872 * compile "break"
7873 */
7874 static char_u *
7875compile_break(char_u *arg, cctx_T *cctx)
7876{
7877 scope_T *scope = cctx->ctx_scope;
7878 endlabel_T **el;
7879
7880 for (;;)
7881 {
7882 if (scope == NULL)
7883 {
7884 emsg(_(e_break));
7885 return NULL;
7886 }
7887 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
7888 break;
7889 scope = scope->se_outer;
7890 }
7891
7892 // Jump to the end of the FOR or WHILE loop.
7893 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007894 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007895 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01007896 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007897 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
7898 return FAIL;
7899
7900 return arg;
7901}
7902
7903/*
7904 * compile "{" start of block
7905 */
7906 static char_u *
7907compile_block(char_u *arg, cctx_T *cctx)
7908{
7909 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
7910 return NULL;
7911 return skipwhite(arg + 1);
7912}
7913
7914/*
7915 * compile end of block: drop one scope
7916 */
7917 static void
7918compile_endblock(cctx_T *cctx)
7919{
7920 scope_T *scope = cctx->ctx_scope;
7921
7922 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007923 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007924 vim_free(scope);
7925}
7926
7927/*
7928 * compile "try"
7929 * Creates a new scope for the try-endtry, pointing to the first catch and
7930 * finally.
7931 * Creates another scope for the "try" block itself.
7932 * TRY instruction sets up exception handling at runtime.
7933 *
7934 * "try"
7935 * TRY -> catch1, -> finally push trystack entry
7936 * ... try block
7937 * "throw {exception}"
7938 * EVAL {exception}
7939 * THROW create exception
7940 * ... try block
7941 * " catch {expr}"
7942 * JUMP -> finally
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01007943 * catch1: PUSH exception
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007944 * EVAL {expr}
7945 * MATCH
7946 * JUMP nomatch -> catch2
7947 * CATCH remove exception
7948 * ... catch block
7949 * " catch"
7950 * JUMP -> finally
7951 * catch2: CATCH remove exception
7952 * ... catch block
7953 * " finally"
7954 * finally:
7955 * ... finally block
7956 * " endtry"
7957 * ENDTRY pop trystack entry, may rethrow
7958 */
7959 static char_u *
7960compile_try(char_u *arg, cctx_T *cctx)
7961{
7962 garray_T *instr = &cctx->ctx_instr;
7963 scope_T *try_scope;
7964 scope_T *scope;
7965
Bram Moolenaarfa984412021-03-25 22:15:28 +01007966 if (misplaced_cmdmod(cctx))
7967 return NULL;
7968
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007969 // scope that holds the jumps that go to catch/finally/endtry
7970 try_scope = new_scope(cctx, TRY_SCOPE);
7971 if (try_scope == NULL)
7972 return NULL;
7973
Bram Moolenaar69f70502021-01-01 16:10:46 +01007974 if (cctx->ctx_skip != SKIP_YES)
7975 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007976 isn_T *isn;
7977
7978 // "try_catch" is set when the first ":catch" is found or when no catch
7979 // is found and ":finally" is found.
7980 // "try_finally" is set when ":finally" is found
7981 // "try_endtry" is set when ":endtry" is found
Bram Moolenaar69f70502021-01-01 16:10:46 +01007982 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01007983 if ((isn = generate_instr(cctx, ISN_TRY)) == NULL)
7984 return NULL;
7985 isn->isn_arg.try.try_ref = ALLOC_CLEAR_ONE(tryref_T);
7986 if (isn->isn_arg.try.try_ref == NULL)
Bram Moolenaar69f70502021-01-01 16:10:46 +01007987 return NULL;
7988 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007989
7990 // scope for the try block itself
7991 scope = new_scope(cctx, BLOCK_SCOPE);
7992 if (scope == NULL)
7993 return NULL;
7994
7995 return arg;
7996}
7997
7998/*
7999 * compile "catch {expr}"
8000 */
8001 static char_u *
8002compile_catch(char_u *arg, cctx_T *cctx UNUSED)
8003{
8004 scope_T *scope = cctx->ctx_scope;
8005 garray_T *instr = &cctx->ctx_instr;
8006 char_u *p;
8007 isn_T *isn;
8008
Bram Moolenaarfa984412021-03-25 22:15:28 +01008009 if (misplaced_cmdmod(cctx))
8010 return NULL;
8011
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008012 // end block scope from :try or :catch
8013 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
8014 compile_endblock(cctx);
8015 scope = cctx->ctx_scope;
8016
8017 // Error if not in a :try scope
8018 if (scope == NULL || scope->se_type != TRY_SCOPE)
8019 {
8020 emsg(_(e_catch));
8021 return NULL;
8022 }
8023
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008024 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008025 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008026 emsg(_(e_catch_unreachable_after_catch_all));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008027 return NULL;
8028 }
8029
Bram Moolenaar69f70502021-01-01 16:10:46 +01008030 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008031 {
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008032#ifdef FEAT_PROFILE
8033 // the profile-start should be after the jump
8034 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
8035 .isn_type == ISN_PROF_START)
8036 --instr->ga_len;
8037#endif
Bram Moolenaar69f70502021-01-01 16:10:46 +01008038 // Jump from end of previous block to :finally or :endtry
8039 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
8040 JUMP_ALWAYS, cctx) == FAIL)
8041 return NULL;
8042
8043 // End :try or :catch scope: set value in ISN_TRY instruction
8044 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008045 if (isn->isn_arg.try.try_ref->try_catch == 0)
8046 isn->isn_arg.try.try_ref->try_catch = instr->ga_len;
Bram Moolenaar69f70502021-01-01 16:10:46 +01008047 if (scope->se_u.se_try.ts_catch_label != 0)
8048 {
8049 // Previous catch without match jumps here
8050 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
8051 isn->isn_arg.jump.jump_where = instr->ga_len;
8052 }
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008053#ifdef FEAT_PROFILE
8054 if (cctx->ctx_profiling)
8055 {
8056 // a "throw" that jumps here needs to be counted
8057 generate_instr(cctx, ISN_PROF_END);
8058 // the "catch" is also counted
8059 generate_instr(cctx, ISN_PROF_START);
8060 }
8061#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008062 }
8063
8064 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02008065 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008066 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008067 scope->se_u.se_try.ts_caught_all = TRUE;
8068 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008069 }
8070 else
8071 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008072 char_u *end;
8073 char_u *pat;
8074 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02008075 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01008076 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008077
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008078 // Push v:exception, push {expr} and MATCH
8079 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
8080
Bram Moolenaard93a7fc2021-01-04 12:42:13 +01008081 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008082 if (*end != *p)
8083 {
Bram Moolenaar7cb6fc22020-08-21 22:36:47 +02008084 semsg(_(e_separator_mismatch_str), p);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008085 vim_free(tofree);
8086 return FAIL;
8087 }
8088 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01008089 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008090 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02008091 len = (int)(end - tofree);
8092 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008093 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02008094 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01008095 if (pat == NULL)
8096 return FAIL;
8097 if (generate_PUSHS(cctx, pat) == FAIL)
8098 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008099
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008100 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
8101 return NULL;
8102
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008103 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008104 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
8105 return NULL;
8106 }
8107
Bram Moolenaar69f70502021-01-01 16:10:46 +01008108 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008109 return NULL;
8110
8111 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
8112 return NULL;
8113 return p;
8114}
8115
8116 static char_u *
8117compile_finally(char_u *arg, cctx_T *cctx)
8118{
8119 scope_T *scope = cctx->ctx_scope;
8120 garray_T *instr = &cctx->ctx_instr;
8121 isn_T *isn;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008122 int this_instr;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008123
Bram Moolenaarfa984412021-03-25 22:15:28 +01008124 if (misplaced_cmdmod(cctx))
8125 return NULL;
8126
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008127 // end block scope from :try or :catch
8128 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
8129 compile_endblock(cctx);
8130 scope = cctx->ctx_scope;
8131
8132 // Error if not in a :try scope
8133 if (scope == NULL || scope->se_type != TRY_SCOPE)
8134 {
8135 emsg(_(e_finally));
8136 return NULL;
8137 }
8138
8139 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008140 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008141 if (isn->isn_arg.try.try_ref->try_finally != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008142 {
8143 emsg(_(e_finally_dup));
8144 return NULL;
8145 }
8146
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008147 this_instr = instr->ga_len;
8148#ifdef FEAT_PROFILE
8149 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
8150 .isn_type == ISN_PROF_START)
8151 // jump to the profile start of the "finally"
8152 --this_instr;
8153#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008154
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008155 // Fill in the "end" label in jumps at the end of the blocks.
8156 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
8157 this_instr, cctx);
8158
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008159 // If there is no :catch then an exception jumps to :finally.
8160 if (isn->isn_arg.try.try_ref->try_catch == 0)
8161 isn->isn_arg.try.try_ref->try_catch = this_instr;
8162 isn->isn_arg.try.try_ref->try_finally = this_instr;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008163 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008164 {
8165 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01008166 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008167 isn->isn_arg.jump.jump_where = this_instr;
Bram Moolenaare8593122020-07-18 15:17:02 +02008168 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008169 }
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008170 if (generate_instr(cctx, ISN_FINALLY) == NULL)
8171 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008172
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008173 // TODO: set index in ts_finally_label jumps
8174
8175 return arg;
8176}
8177
8178 static char_u *
8179compile_endtry(char_u *arg, cctx_T *cctx)
8180{
8181 scope_T *scope = cctx->ctx_scope;
8182 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaarc150c092021-02-13 15:02:46 +01008183 isn_T *try_isn;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008184
Bram Moolenaarfa984412021-03-25 22:15:28 +01008185 if (misplaced_cmdmod(cctx))
8186 return NULL;
8187
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008188 // end block scope from :catch or :finally
8189 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
8190 compile_endblock(cctx);
8191 scope = cctx->ctx_scope;
8192
8193 // Error if not in a :try scope
8194 if (scope == NULL || scope->se_type != TRY_SCOPE)
8195 {
8196 if (scope == NULL)
8197 emsg(_(e_no_endtry));
8198 else if (scope->se_type == WHILE_SCOPE)
8199 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01008200 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008201 emsg(_(e_endfor));
8202 else
8203 emsg(_(e_endif));
8204 return NULL;
8205 }
8206
Bram Moolenaarc150c092021-02-13 15:02:46 +01008207 try_isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar69f70502021-01-01 16:10:46 +01008208 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008209 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008210 if (try_isn->isn_arg.try.try_ref->try_catch == 0
8211 && try_isn->isn_arg.try.try_ref->try_finally == 0)
Bram Moolenaar69f70502021-01-01 16:10:46 +01008212 {
8213 emsg(_(e_missing_catch_or_finally));
8214 return NULL;
8215 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008216
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008217#ifdef FEAT_PROFILE
8218 if (cctx->ctx_profiling && ((isn_T *)instr->ga_data)[instr->ga_len - 1]
8219 .isn_type == ISN_PROF_START)
8220 // move the profile start after "endtry" so that it's not counted when
8221 // the exception is rethrown.
8222 --instr->ga_len;
8223#endif
8224
Bram Moolenaar69f70502021-01-01 16:10:46 +01008225 // Fill in the "end" label in jumps at the end of the blocks, if not
8226 // done by ":finally".
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008227 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label,
8228 instr->ga_len, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008229
Bram Moolenaar69f70502021-01-01 16:10:46 +01008230 if (scope->se_u.se_try.ts_catch_label != 0)
8231 {
8232 // Last catch without match jumps here
Bram Moolenaarc150c092021-02-13 15:02:46 +01008233 isn_T *isn = ((isn_T *)instr->ga_data)
8234 + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar69f70502021-01-01 16:10:46 +01008235 isn->isn_arg.jump.jump_where = instr->ga_len;
8236 }
Bram Moolenaare8593122020-07-18 15:17:02 +02008237 }
8238
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008239 compile_endblock(cctx);
8240
Bram Moolenaar4afa7742021-02-14 16:34:59 +01008241 if (cctx->ctx_skip != SKIP_YES)
8242 {
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01008243 // End :catch or :finally scope: set instruction index in ISN_TRY
8244 // instruction
8245 try_isn->isn_arg.try.try_ref->try_endtry = instr->ga_len;
Bram Moolenaar4afa7742021-02-14 16:34:59 +01008246 if (cctx->ctx_skip != SKIP_YES
8247 && generate_instr(cctx, ISN_ENDTRY) == NULL)
8248 return NULL;
Bram Moolenaar107e9ce2021-01-24 20:52:00 +01008249#ifdef FEAT_PROFILE
8250 if (cctx->ctx_profiling)
8251 generate_instr(cctx, ISN_PROF_START);
8252#endif
Bram Moolenaar4afa7742021-02-14 16:34:59 +01008253 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008254 return arg;
8255}
8256
8257/*
8258 * compile "throw {expr}"
8259 */
8260 static char_u *
8261compile_throw(char_u *arg, cctx_T *cctx UNUSED)
8262{
8263 char_u *p = skipwhite(arg);
8264
Bram Moolenaara5565e42020-05-09 15:44:01 +02008265 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008266 return NULL;
Bram Moolenaar9e1d9e32021-01-11 20:17:34 +01008267 if (cctx->ctx_skip == SKIP_YES)
8268 return p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008269 if (may_generate_2STRING(-1, cctx) == FAIL)
8270 return NULL;
8271 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
8272 return NULL;
8273
8274 return p;
8275}
8276
8277/*
8278 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02008279 * compile "echomsg expr"
8280 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01008281 * compile "execute expr"
8282 */
8283 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02008284compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01008285{
8286 char_u *p = arg;
Bram Moolenaare4984292020-12-13 14:19:25 +01008287 char_u *prev = arg;
Bram Moolenaarad39c092020-02-26 18:23:43 +01008288 int count = 0;
Bram Moolenaarc70fe462021-04-17 17:59:19 +02008289 int start_ctx_lnum = cctx->ctx_lnum;
Bram Moolenaarad39c092020-02-26 18:23:43 +01008290
8291 for (;;)
8292 {
Bram Moolenaare4984292020-12-13 14:19:25 +01008293 if (ends_excmd2(prev, p))
8294 break;
Bram Moolenaara5565e42020-05-09 15:44:01 +02008295 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01008296 return NULL;
8297 ++count;
Bram Moolenaare5abf7a2020-08-16 18:29:35 +02008298 prev = p;
Bram Moolenaarad39c092020-02-26 18:23:43 +01008299 p = skipwhite(p);
Bram Moolenaarad39c092020-02-26 18:23:43 +01008300 }
8301
Bram Moolenaare4984292020-12-13 14:19:25 +01008302 if (count > 0)
8303 {
Bram Moolenaarc70fe462021-04-17 17:59:19 +02008304 long save_lnum = cctx->ctx_lnum;
8305
8306 // Use the line number where the command started.
8307 cctx->ctx_lnum = start_ctx_lnum;
8308
Bram Moolenaare4984292020-12-13 14:19:25 +01008309 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
8310 generate_ECHO(cctx, cmdidx == CMD_echo, count);
8311 else if (cmdidx == CMD_execute)
8312 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
8313 else if (cmdidx == CMD_echomsg)
8314 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
8315 else
8316 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaarc70fe462021-04-17 17:59:19 +02008317
8318 cctx->ctx_lnum = save_lnum;
Bram Moolenaare4984292020-12-13 14:19:25 +01008319 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008320 return p;
8321}
8322
8323/*
Bram Moolenaar8e7d6222020-12-18 19:49:56 +01008324 * If "eap" has a range that is not a constant generate an ISN_RANGE
Bram Moolenaar08597872020-12-10 19:43:40 +01008325 * instruction to compute it and return OK.
8326 * Otherwise return FAIL, the caller must deal with any range.
8327 */
8328 static int
8329compile_variable_range(exarg_T *eap, cctx_T *cctx)
8330{
8331 char_u *range_end = skip_range(eap->cmd, TRUE, NULL);
8332 char_u *p = skipdigits(eap->cmd);
8333
8334 if (p == range_end)
8335 return FAIL;
8336 return generate_RANGE(cctx, vim_strnsave(eap->cmd, range_end - eap->cmd));
8337}
8338
8339/*
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008340 * :put r
8341 * :put ={expr}
8342 */
8343 static char_u *
8344compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
8345{
8346 char_u *line = arg;
8347 linenr_T lnum;
8348 char *errormsg;
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02008349 int above = eap->forceit;
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008350
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008351 eap->regname = *line;
8352
8353 if (eap->regname == '=')
8354 {
8355 char_u *p = line + 1;
8356
8357 if (compile_expr0(&p, cctx) == FAIL)
8358 return NULL;
8359 line = p;
8360 }
8361 else if (eap->regname != NUL)
8362 ++line;
8363
Bram Moolenaar08597872020-12-10 19:43:40 +01008364 if (compile_variable_range(eap, cctx) == OK)
8365 {
8366 lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE;
8367 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008368 else
Bram Moolenaar08597872020-12-10 19:43:40 +01008369 {
8370 // Either no range or a number.
8371 // "errormsg" will not be set because the range is ADDR_LINES.
8372 if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
Bram Moolenaar399ea812020-12-15 21:28:57 +01008373 // cannot happen
Bram Moolenaar08597872020-12-10 19:43:40 +01008374 return NULL;
8375 if (eap->addr_count == 0)
8376 lnum = -1;
8377 else
8378 lnum = eap->line2;
8379 if (above)
8380 --lnum;
8381 }
Bram Moolenaarc3516f72020-09-08 22:45:35 +02008382
8383 generate_PUT(cctx, eap->regname, lnum);
8384 return line;
8385}
8386
8387/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008388 * A command that is not compiled, execute with legacy code.
8389 */
8390 static char_u *
8391compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
8392{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02008393 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02008394 int has_expr = FALSE;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008395 char_u *nextcmd = (char_u *)"";
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008396
Bram Moolenaar9b68c822020-06-18 19:31:08 +02008397 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008398 goto theend;
8399
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02008400 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008401 {
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02008402 long argt = eap->argt;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008403 int usefilter = FALSE;
8404
8405 has_expr = argt & (EX_XFILE | EX_EXPAND);
8406
8407 // If the command can be followed by a bar, find the bar and truncate
8408 // it, so that the following command can be compiled.
8409 // The '|' is overwritten with a NUL, it is put back below.
8410 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
8411 && *eap->arg == '!')
8412 // :w !filter or :r !filter or :r! filter
8413 usefilter = TRUE;
8414 if ((argt & EX_TRLBAR) && !usefilter)
8415 {
Bram Moolenaarb8a92962020-08-20 18:02:47 +02008416 eap->argt = argt;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008417 separate_nextcmd(eap);
8418 if (eap->nextcmd != NULL)
8419 nextcmd = eap->nextcmd;
8420 }
Bram Moolenaara11919f2021-01-02 19:44:56 +01008421 else if (eap->cmdidx == CMD_wincmd)
8422 {
8423 p = eap->arg;
8424 if (*p != NUL)
8425 ++p;
8426 if (*p == 'g' || *p == Ctrl_G)
8427 ++p;
8428 p = skipwhite(p);
8429 if (*p == '|')
8430 {
8431 *p = NUL;
8432 nextcmd = p + 1;
8433 }
8434 }
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008435 }
8436
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02008437 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
8438 {
8439 // expand filename in "syntax include [@group] filename"
8440 has_expr = TRUE;
8441 eap->arg = skipwhite(eap->arg + 7);
8442 if (*eap->arg == '@')
8443 eap->arg = skiptowhite(eap->arg);
8444 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008445
Bram Moolenaar56ce9ea2020-12-25 18:35:29 +01008446 if ((eap->cmdidx == CMD_global || eap->cmdidx == CMD_vglobal)
8447 && STRLEN(eap->arg) > 4)
8448 {
8449 int delim = *eap->arg;
8450
Bram Moolenaard93a7fc2021-01-04 12:42:13 +01008451 p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
Bram Moolenaar56ce9ea2020-12-25 18:35:29 +01008452 if (*p == delim)
8453 {
8454 eap->arg = p + 1;
8455 has_expr = TRUE;
8456 }
8457 }
8458
Bram Moolenaarecac5912021-01-05 19:23:28 +01008459 if (eap->cmdidx == CMD_folddoopen || eap->cmdidx == CMD_folddoclosed)
8460 {
8461 // TODO: should only expand when appropriate for the command
8462 eap->arg = skiptowhite(eap->arg);
8463 has_expr = TRUE;
8464 }
8465
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02008466 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008467 {
8468 int count = 0;
8469 char_u *start = skipwhite(line);
8470
8471 // :cmd xxx`=expr1`yyy`=expr2`zzz
8472 // PUSHS ":cmd xxx"
8473 // eval expr1
8474 // PUSHS "yyy"
8475 // eval expr2
8476 // PUSHS "zzz"
8477 // EXECCONCAT 5
8478 for (;;)
8479 {
8480 if (p > start)
8481 {
Bram Moolenaar71ccd032020-06-12 22:59:11 +02008482 generate_PUSHS(cctx, vim_strnsave(start, p - start));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008483 ++count;
8484 }
8485 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02008486 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008487 return NULL;
8488 may_generate_2STRING(-1, cctx);
8489 ++count;
8490 p = skipwhite(p);
8491 if (*p != '`')
8492 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008493 emsg(_(e_missing_backtick));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008494 return NULL;
8495 }
8496 start = p + 1;
8497
8498 p = (char_u *)strstr((char *)start, "`=");
8499 if (p == NULL)
8500 {
8501 if (*skipwhite(start) != NUL)
8502 {
8503 generate_PUSHS(cctx, vim_strsave(start));
8504 ++count;
8505 }
8506 break;
8507 }
8508 }
8509 generate_EXECCONCAT(cctx, count);
8510 }
8511 else
8512 generate_EXEC(cctx, line);
8513
8514theend:
Bram Moolenaare9f262b2020-07-05 14:57:51 +02008515 if (*nextcmd != NUL)
8516 {
8517 // the parser expects a pointer to the bar, put it back
8518 --nextcmd;
8519 *nextcmd = '|';
8520 }
8521
8522 return nextcmd;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02008523}
8524
8525/*
Bram Moolenaar4c137212021-04-19 16:48:48 +02008526 * :s/pat/repl/
8527 */
8528 static char_u *
8529compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
8530{
8531 char_u *cmd = eap->arg;
8532 char_u *expr = (char_u *)strstr((char *)cmd, "\\=");
8533
8534 if (expr != NULL)
8535 {
8536 int delimiter = *cmd++;
8537
8538 // There is a \=expr, find it in the substitute part.
8539 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(),
8540 NULL, NULL, NULL);
8541 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
8542 {
8543 int instr_count = cctx->ctx_instr.ga_len;
8544 char_u *end;
8545
8546 cmd += 3;
8547 end = skip_substitute(cmd, delimiter);
8548
8549 compile_expr0(&cmd, cctx);
8550 if (end[-1] == NUL)
8551 end[-1] = delimiter;
8552 cmd = skipwhite(cmd);
8553 if (*cmd != delimiter && *cmd != NUL)
8554 {
8555 semsg(_(e_trailing_arg), cmd);
8556 return NULL;
8557 }
8558
8559 if (generate_substitute(arg, instr_count, cctx) == FAIL)
8560 return NULL;
8561
8562 // skip over flags
8563 if (*end == '&')
8564 ++end;
8565 while (ASCII_ISALPHA(*end) || *end == '#')
8566 ++end;
8567 return end;
8568 }
8569 }
8570
8571 return compile_exec(arg, eap, cctx);
8572}
8573
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02008574 static char_u *
8575compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
8576{
8577 char_u *arg = eap->arg;
8578
8579 if (cctx->ctx_redir_lhs.lhs_name != NULL)
8580 {
8581 if (STRNCMP(arg, "END", 3) == 0)
8582 {
8583 if (cctx->ctx_redir_lhs.lhs_append)
8584 {
8585 if (compile_load_lhs(&cctx->ctx_redir_lhs,
8586 cctx->ctx_redir_lhs.lhs_name, NULL, cctx) == FAIL)
8587 return NULL;
8588 if (cctx->ctx_redir_lhs.lhs_has_index)
8589 emsg("redir with index not implemented yet");
8590 }
8591
8592 // Gets the redirected text and put it on the stack, then store it
8593 // in the variable.
8594 generate_instr_type(cctx, ISN_REDIREND, &t_string);
8595
8596 if (cctx->ctx_redir_lhs.lhs_append)
8597 generate_instr_drop(cctx, ISN_CONCAT, 1);
8598
8599 if (generate_store_lhs(cctx, &cctx->ctx_redir_lhs, -1) == FAIL)
8600 return NULL;
8601
8602 VIM_CLEAR(cctx->ctx_redir_lhs.lhs_name);
8603 return arg + 3;
8604 }
8605 emsg(_(e_cannot_nest_redir));
8606 return NULL;
8607 }
8608
8609 if (arg[0] == '=' && arg[1] == '>')
8610 {
8611 int append = FALSE;
8612
8613 // redirect to a variable is compiled
8614 arg += 2;
8615 if (*arg == '>')
8616 {
8617 ++arg;
8618 append = TRUE;
8619 }
8620 arg = skipwhite(arg);
8621
8622 if (compile_assign_lhs(arg, &cctx->ctx_redir_lhs, CMD_redir,
8623 FALSE, FALSE, 1, cctx) == FAIL)
8624 return NULL;
8625 generate_instr(cctx, ISN_REDIRSTART);
8626 cctx->ctx_redir_lhs.lhs_append = append;
8627
8628 return arg + cctx->ctx_redir_lhs.lhs_varlen;
8629 }
8630
8631 // other redirects are handled like at script level
8632 return compile_exec(line, eap, cctx);
8633}
8634
Bram Moolenaar4c137212021-04-19 16:48:48 +02008635/*
Bram Moolenaar09689a02020-05-09 22:50:08 +02008636 * Add a function to the list of :def functions.
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008637 * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet.
Bram Moolenaar09689a02020-05-09 22:50:08 +02008638 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02008639 static int
Bram Moolenaar09689a02020-05-09 22:50:08 +02008640add_def_function(ufunc_T *ufunc)
8641{
8642 dfunc_T *dfunc;
8643
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008644 if (def_functions.ga_len == 0)
8645 {
8646 // The first position is not used, so that a zero uf_dfunc_idx means it
8647 // wasn't set.
8648 if (ga_grow(&def_functions, 1) == FAIL)
8649 return FAIL;
8650 ++def_functions.ga_len;
8651 }
8652
Bram Moolenaar09689a02020-05-09 22:50:08 +02008653 // Add the function to "def_functions".
8654 if (ga_grow(&def_functions, 1) == FAIL)
8655 return FAIL;
8656 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
8657 CLEAR_POINTER(dfunc);
8658 dfunc->df_idx = def_functions.ga_len;
8659 ufunc->uf_dfunc_idx = dfunc->df_idx;
8660 dfunc->df_ufunc = ufunc;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01008661 dfunc->df_name = vim_strsave(ufunc->uf_name);
8662 ++dfunc->df_refcount;
Bram Moolenaar09689a02020-05-09 22:50:08 +02008663 ++def_functions.ga_len;
8664 return OK;
8665}
8666
8667/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008668 * After ex_function() has collected all the function lines: parse and compile
8669 * the lines into instructions.
8670 * Adds the function to "def_functions".
Bram Moolenaar9e68c322020-12-25 12:38:04 +01008671 * When "check_return_type" is set then set ufunc->uf_ret_type to the type of
8672 * the return statement (used for lambda). When uf_ret_type is already set
8673 * then check that it matches.
Bram Moolenaarb2049902021-01-24 12:53:53 +01008674 * When "profiling" is true add ISN_PROF_START instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02008675 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02008676 * This can be used recursively through compile_lambda(), which may reallocate
8677 * "def_functions".
Bram Moolenaar822ba242020-05-24 23:00:18 +02008678 * Returns OK or FAIL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008679 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02008680 int
Bram Moolenaarb2049902021-01-24 12:53:53 +01008681compile_def_function(
8682 ufunc_T *ufunc,
8683 int check_return_type,
Bram Moolenaarf002a412021-01-24 13:34:18 +01008684 int profiling UNUSED,
Bram Moolenaarb2049902021-01-24 12:53:53 +01008685 cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008686{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008687 char_u *line = NULL;
Bram Moolenaarf62d7392021-04-14 12:40:00 +02008688 char_u *line_to_free = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008689 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008690 char *errormsg = NULL; // error message
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008691 cctx_T cctx;
8692 garray_T *instr;
Bram Moolenaard66960b2020-10-30 20:46:26 +01008693 int did_emsg_before = did_emsg;
Bram Moolenaar599410c2021-04-10 14:03:43 +02008694 int did_emsg_silent_before = did_emsg_silent;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008695 int ret = FAIL;
8696 sctx_T save_current_sctx = current_sctx;
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02008697 int save_estack_compiling = estack_compiling;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008698 int do_estack_push;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008699 int new_def_function = FALSE;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008700#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01008701 int prof_lnum = -1;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008702#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008703
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008704 // When using a function that was compiled before: Free old instructions.
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01008705 // The index is reused. Otherwise add a new entry in "def_functions".
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02008706 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008707 {
Bram Moolenaar09689a02020-05-09 22:50:08 +02008708 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
8709 + ufunc->uf_dfunc_idx;
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01008710 delete_def_function_contents(dfunc, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008711 }
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02008712 else
8713 {
8714 if (add_def_function(ufunc) == FAIL)
8715 return FAIL;
8716 new_def_function = TRUE;
8717 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008718
Bram Moolenaar985116a2020-07-12 17:31:09 +02008719 ufunc->uf_def_status = UF_COMPILING;
8720
Bram Moolenaara80faa82020-04-12 19:37:17 +02008721 CLEAR_FIELD(cctx);
Bram Moolenaarb2049902021-01-24 12:53:53 +01008722
Bram Moolenaarf002a412021-01-24 13:34:18 +01008723#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01008724 cctx.ctx_profiling = profiling;
Bram Moolenaarf002a412021-01-24 13:34:18 +01008725#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008726 cctx.ctx_ufunc = ufunc;
8727 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02008728 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008729 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
8730 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
8731 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
8732 cctx.ctx_type_list = &ufunc->uf_type_list;
8733 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
8734 instr = &cctx.ctx_instr;
8735
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008736 // Set the context to the function, it may be compiled when called from
8737 // another script. Set the script version to the most modern one.
8738 // The line number will be set in next_line_from_context().
8739 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008740 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
8741
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008742 // Make sure error messages are OK.
8743 do_estack_push = !estack_top_is_ufunc(ufunc, 1);
8744 if (do_estack_push)
8745 estack_push_ufunc(ufunc, 1);
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02008746 estack_compiling = TRUE;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02008747
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008748 if (ufunc->uf_def_args.ga_len > 0)
8749 {
8750 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008751 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar12bce952021-03-11 20:04:04 +01008752 int uf_args_len = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008753 int i;
8754 char_u *arg;
8755 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008756 int did_set_arg_type = FALSE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008757
8758 // Produce instructions for the default values of optional arguments.
Bram Moolenaar12bce952021-03-11 20:04:04 +01008759 SOURCING_LNUM = 0; // line number unknown
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008760 for (i = 0; i < count; ++i)
8761 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008762 garray_T *stack = &cctx.ctx_type_stack;
8763 type_T *val_type;
8764 int arg_idx = first_def_arg + i;
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008765 where_T where;
Bram Moolenaar12bce952021-03-11 20:04:04 +01008766 int r;
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02008767 int jump_instr_idx = instr->ga_len;
8768 isn_T *isn;
8769
8770 // Use a JUMP_IF_ARG_SET instruction to skip if the value was given.
8771 if (generate_JUMP_IF_ARG_SET(&cctx, i - count - off) == FAIL)
8772 goto erret;
Bram Moolenaar12bce952021-03-11 20:04:04 +01008773
8774 // Make sure later arguments are not found.
8775 ufunc->uf_args.ga_len = i;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008776
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008777 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar12bce952021-03-11 20:04:04 +01008778 r = compile_expr0(&arg, &cctx);
8779
8780 ufunc->uf_args.ga_len = uf_args_len;
8781 if (r == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008782 goto erret;
8783
8784 // If no type specified use the type of the default value.
8785 // Otherwise check that the default value type matches the
8786 // specified type.
8787 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008788 where.wt_index = arg_idx + 1;
8789 where.wt_variable = FALSE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008790 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008791 {
8792 did_set_arg_type = TRUE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008793 ufunc->uf_arg_types[arg_idx] = val_type;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008794 }
Bram Moolenaar8b565c22020-08-30 23:24:20 +02008795 else if (check_type(ufunc->uf_arg_types[arg_idx], val_type,
Bram Moolenaarf785aa12021-02-11 21:19:34 +01008796 TRUE, where) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008797 goto erret;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02008798
8799 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008800 goto erret;
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02008801
8802 // set instruction index in JUMP_IF_ARG_SET to here
8803 isn = ((isn_T *)instr->ga_data) + jump_instr_idx;
8804 isn->isn_arg.jumparg.jump_where = instr->ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008805 }
Bram Moolenaarb8070e32020-07-23 20:56:04 +02008806
8807 if (did_set_arg_type)
8808 set_function_type(ufunc);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01008809 }
8810
8811 /*
8812 * Loop over all the lines of the function and generate instructions.
8813 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008814 for (;;)
8815 {
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02008816 exarg_T ea;
Bram Moolenaar2dd0a2c2020-08-08 15:10:27 +02008817 int starts_with_colon = FALSE;
8818 char_u *cmd;
Bram Moolenaar02194d22020-10-24 23:08:38 +02008819 cmdmod_T local_cmdmod;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01008820
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02008821 // Bail out on the first error to avoid a flood of errors and report
8822 // the right line number when inside try/catch.
Bram Moolenaard66960b2020-10-30 20:46:26 +01008823 if (did_emsg_before != did_emsg)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02008824 goto erret;
8825
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008826 if (line != NULL && *line == '|')
8827 // the line continues after a '|'
8828 ++line;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02008829 else if (line != NULL && *skipwhite(line) != NUL
Bram Moolenaar7a092242020-04-16 22:10:49 +02008830 && !(*line == '#' && (line == cctx.ctx_line_start
8831 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008832 {
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02008833 semsg(_(e_trailing_arg), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008834 goto erret;
8835 }
Bram Moolenaar4b3e1962021-03-18 21:37:55 +01008836 else if (line != NULL && vim9_bad_comment(skipwhite(line)))
8837 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008838 else
8839 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02008840 line = next_line_from_context(&cctx, FALSE);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02008841 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarb2049902021-01-24 12:53:53 +01008842 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008843 // beyond the last line
Bram Moolenaarf002a412021-01-24 13:34:18 +01008844#ifdef FEAT_PROFILE
Bram Moolenaarced68a02021-01-24 17:53:47 +01008845 if (cctx.ctx_skip != SKIP_YES)
8846 may_generate_prof_end(&cctx, prof_lnum);
Bram Moolenaarf002a412021-01-24 13:34:18 +01008847#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008848 break;
Bram Moolenaarb2049902021-01-24 12:53:53 +01008849 }
Bram Moolenaarf62d7392021-04-14 12:40:00 +02008850 // Make a copy, splitting off nextcmd and removing trailing spaces
8851 // may change it.
8852 if (line != NULL)
8853 {
8854 line = vim_strsave(line);
8855 vim_free(line_to_free);
8856 line_to_free = line;
8857 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008858 }
8859
Bram Moolenaara80faa82020-04-12 19:37:17 +02008860 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008861 ea.cmdlinep = &line;
8862 ea.cmd = skipwhite(line);
8863
Bram Moolenaarb2049902021-01-24 12:53:53 +01008864 if (*ea.cmd == '#')
8865 {
8866 // "#" starts a comment
8867 line = (char_u *)"";
8868 continue;
8869 }
8870
Bram Moolenaarf002a412021-01-24 13:34:18 +01008871#ifdef FEAT_PROFILE
Bram Moolenaarced68a02021-01-24 17:53:47 +01008872 if (cctx.ctx_profiling && cctx.ctx_lnum != prof_lnum &&
8873 cctx.ctx_skip != SKIP_YES)
Bram Moolenaarb2049902021-01-24 12:53:53 +01008874 {
8875 may_generate_prof_end(&cctx, prof_lnum);
8876
8877 prof_lnum = cctx.ctx_lnum;
8878 generate_instr(&cctx, ISN_PROF_START);
8879 }
Bram Moolenaarf002a412021-01-24 13:34:18 +01008880#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01008881
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008882 // Some things can be recognized by the first character.
8883 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008884 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008885 case '}':
8886 {
8887 // "}" ends a block scope
8888 scopetype_T stype = cctx.ctx_scope == NULL
8889 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008890
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008891 if (stype == BLOCK_SCOPE)
8892 {
8893 compile_endblock(&cctx);
8894 line = ea.cmd;
8895 }
8896 else
8897 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02008898 emsg(_(e_using_rcurly_outside_if_block_scope));
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02008899 goto erret;
8900 }
8901 if (line != NULL)
8902 line = skipwhite(ea.cmd + 1);
8903 continue;
8904 }
8905
8906 case '{':
8907 // "{" starts a block scope
8908 // "{'a': 1}->func() is something else
8909 if (ends_excmd(*skipwhite(ea.cmd + 1)))
8910 {
8911 line = compile_block(ea.cmd, &cctx);
8912 continue;
8913 }
8914 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008915 }
8916
8917 /*
8918 * COMMAND MODIFIERS
8919 */
Bram Moolenaar02194d22020-10-24 23:08:38 +02008920 cctx.ctx_has_cmdmod = FALSE;
Bram Moolenaare1004402020-10-24 20:49:43 +02008921 if (parse_command_modifiers(&ea, &errormsg, &local_cmdmod, FALSE)
8922 == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008923 {
8924 if (errormsg != NULL)
8925 goto erret;
8926 // empty line or comment
8927 line = (char_u *)"";
8928 continue;
8929 }
Bram Moolenaare1004402020-10-24 20:49:43 +02008930 generate_cmdmods(&cctx, &local_cmdmod);
8931 undo_cmdmod(&local_cmdmod);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008932
Bram Moolenaare88c8e82020-11-01 17:03:37 +01008933 // Check if there was a colon after the last command modifier or before
8934 // the current position.
8935 for (p = ea.cmd; p >= line; --p)
8936 {
8937 if (*p == ':')
8938 starts_with_colon = TRUE;
8939 if (p < ea.cmd && !VIM_ISWHITE(*p))
8940 break;
8941 }
8942
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008943 // Skip ":call" to get to the function name.
Bram Moolenaar575f24b2020-08-12 14:21:11 +02008944 p = ea.cmd;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008945 if (checkforcmd(&ea.cmd, "call", 3))
Bram Moolenaar575f24b2020-08-12 14:21:11 +02008946 {
8947 if (*ea.cmd == '(')
8948 // not for "call()"
8949 ea.cmd = p;
8950 else
8951 ea.cmd = skipwhite(ea.cmd);
8952 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008953
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02008954 if (!starts_with_colon)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008955 {
Bram Moolenaar17126b12021-01-07 22:03:02 +01008956 int assign;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02008957
Bram Moolenaar17126b12021-01-07 22:03:02 +01008958 // Check for assignment after command modifiers.
8959 assign = may_compile_assignment(&ea, &line, &cctx);
8960 if (assign == OK)
8961 goto nextline;
8962 if (assign == FAIL)
8963 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008964 }
8965
8966 /*
8967 * COMMAND after range
Bram Moolenaar3d48e252020-07-15 14:15:52 +02008968 * 'text'->func() should not be confused with 'a mark
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008969 */
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008970 cmd = ea.cmd;
Bram Moolenaar7c5ad342020-08-12 15:48:55 +02008971 if (*cmd != '\'' || starts_with_colon)
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008972 {
Bram Moolenaar3bd8de42020-09-14 16:37:34 +02008973 ea.cmd = skip_range(ea.cmd, TRUE, NULL);
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008974 if (ea.cmd > cmd)
Bram Moolenaar3d48e252020-07-15 14:15:52 +02008975 {
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008976 if (!starts_with_colon)
8977 {
Bram Moolenaar6e2c2c52020-12-25 19:25:45 +01008978 semsg(_(e_colon_required_before_range_str), cmd);
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008979 goto erret;
8980 }
Bram Moolenaarada1d872021-02-20 08:16:51 +01008981 ea.addr_count = 1;
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02008982 if (ends_excmd2(line, ea.cmd))
8983 {
8984 // A range without a command: jump to the line.
8985 // TODO: compile to a more efficient command, possibly
8986 // calling parse_cmd_address().
8987 ea.cmdidx = CMD_SIZE;
8988 line = compile_exec(line, &ea, &cctx);
8989 goto nextline;
8990 }
Bram Moolenaar3d48e252020-07-15 14:15:52 +02008991 }
Bram Moolenaardf069ee2020-06-22 23:02:51 +02008992 }
Bram Moolenaar77b10ff2021-03-14 13:21:35 +01008993 p = find_ex_command(&ea, NULL, starts_with_colon
8994 ? NULL : item_exists, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008995
Bram Moolenaard1510ee2021-01-04 16:15:58 +01008996 if (p == NULL)
8997 {
8998 if (cctx.ctx_skip != SKIP_YES)
8999 emsg(_(e_ambiguous_use_of_user_defined_command));
9000 goto erret;
9001 }
9002
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009003 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
9004 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02009005 if (cctx.ctx_skip == SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01009006 {
9007 line += STRLEN(line);
Bram Moolenaarf665e972020-12-05 19:17:16 +01009008 goto nextline;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01009009 }
9010
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009011 // Expression or function call.
Bram Moolenaar007f9d62020-07-06 23:04:49 +02009012 if (ea.cmdidx != CMD_eval)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009013 {
Bram Moolenaar52c124d2020-12-20 21:43:35 +01009014 // CMD_var cannot happen, compile_assignment() above would be
9015 // used. Most likely an assignment to a non-existing variable.
9016 semsg(_(e_command_not_recognized_str), ea.cmd);
Bram Moolenaar007f9d62020-07-06 23:04:49 +02009017 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009018 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009019 }
9020
Bram Moolenaar3988f642020-08-27 22:43:03 +02009021 if (cctx.ctx_had_return
Bram Moolenaara259d8d2020-01-31 20:10:50 +01009022 && ea.cmdidx != CMD_elseif
9023 && ea.cmdidx != CMD_else
Bram Moolenaarefd88552020-06-18 20:50:10 +02009024 && ea.cmdidx != CMD_endif
9025 && ea.cmdidx != CMD_endfor
9026 && ea.cmdidx != CMD_endwhile
9027 && ea.cmdidx != CMD_catch
9028 && ea.cmdidx != CMD_finally
9029 && ea.cmdidx != CMD_endtry)
9030 {
Bram Moolenaar3988f642020-08-27 22:43:03 +02009031 emsg(_(e_unreachable_code_after_return));
9032 goto erret;
Bram Moolenaarefd88552020-06-18 20:50:10 +02009033 }
9034
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02009035 p = skipwhite(p);
9036 if (ea.cmdidx != CMD_SIZE
9037 && ea.cmdidx != CMD_write && ea.cmdidx != CMD_read)
9038 {
Bram Moolenaar9b123d82020-09-14 22:39:11 +02009039 if (ea.cmdidx >= 0)
9040 ea.argt = excmd_get_argt(ea.cmdidx);
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02009041 if ((ea.argt & EX_BANG) && *p == '!')
9042 {
9043 ea.forceit = TRUE;
9044 p = skipwhite(p + 1);
9045 }
9046 }
9047
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009048 switch (ea.cmdidx)
9049 {
9050 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02009051 ea.arg = p;
9052 line = compile_nested_function(&ea, &cctx);
9053 break;
9054
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009055 case CMD_function:
Bram Moolenaar451c2e32020-08-15 16:33:28 +02009056 // TODO: should we allow this, e.g. to declare a global
9057 // function?
9058 emsg(_(e_cannot_use_function_inside_def));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009059 goto erret;
9060
9061 case CMD_return:
Bram Moolenaar9e68c322020-12-25 12:38:04 +01009062 line = compile_return(p, check_return_type, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009063 cctx.ctx_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009064 break;
9065
9066 case CMD_let:
Bram Moolenaarc58f5452020-10-21 20:58:52 +02009067 emsg(_(e_cannot_use_let_in_vim9_script));
9068 break;
Bram Moolenaar30fd8202020-09-26 15:09:30 +02009069 case CMD_var:
9070 case CMD_final:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009071 case CMD_const:
9072 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02009073 if (line == p)
9074 line = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009075 break;
9076
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02009077 case CMD_unlet:
9078 case CMD_unlockvar:
9079 case CMD_lockvar:
9080 line = compile_unletlock(p, &ea, &cctx);
9081 break;
9082
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009083 case CMD_import:
9084 line = compile_import(p, &cctx);
9085 break;
9086
9087 case CMD_if:
9088 line = compile_if(p, &cctx);
9089 break;
9090 case CMD_elseif:
9091 line = compile_elseif(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009092 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009093 break;
9094 case CMD_else:
9095 line = compile_else(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009096 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009097 break;
9098 case CMD_endif:
9099 line = compile_endif(p, &cctx);
9100 break;
9101
9102 case CMD_while:
9103 line = compile_while(p, &cctx);
9104 break;
9105 case CMD_endwhile:
9106 line = compile_endwhile(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009107 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009108 break;
9109
9110 case CMD_for:
9111 line = compile_for(p, &cctx);
9112 break;
9113 case CMD_endfor:
9114 line = compile_endfor(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009115 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009116 break;
9117 case CMD_continue:
9118 line = compile_continue(p, &cctx);
9119 break;
9120 case CMD_break:
9121 line = compile_break(p, &cctx);
9122 break;
9123
9124 case CMD_try:
9125 line = compile_try(p, &cctx);
9126 break;
9127 case CMD_catch:
9128 line = compile_catch(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009129 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009130 break;
9131 case CMD_finally:
9132 line = compile_finally(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009133 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009134 break;
9135 case CMD_endtry:
9136 line = compile_endtry(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02009137 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009138 break;
9139 case CMD_throw:
9140 line = compile_throw(p, &cctx);
9141 break;
9142
Bram Moolenaar007f9d62020-07-06 23:04:49 +02009143 case CMD_eval:
9144 if (compile_expr0(&p, &cctx) == FAIL)
9145 goto erret;
9146
Bram Moolenaar3988f642020-08-27 22:43:03 +02009147 // drop the result
Bram Moolenaar007f9d62020-07-06 23:04:49 +02009148 generate_instr_drop(&cctx, ISN_DROP, 1);
9149
9150 line = skipwhite(p);
9151 break;
9152
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009153 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009154 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01009155 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02009156 case CMD_echomsg:
9157 case CMD_echoerr:
9158 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01009159 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009160
Bram Moolenaarc3516f72020-09-08 22:45:35 +02009161 case CMD_put:
9162 ea.cmd = cmd;
9163 line = compile_put(p, &ea, &cctx);
9164 break;
9165
Bram Moolenaar4c137212021-04-19 16:48:48 +02009166 case CMD_substitute:
9167 if (cctx.ctx_skip == SKIP_YES)
9168 line = (char_u *)"";
9169 else
9170 {
9171 ea.arg = p;
9172 line = compile_substitute(line, &ea, &cctx);
9173 }
9174 break;
9175
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009176 case CMD_redir:
9177 ea.arg = p;
9178 line = compile_redir(line, &ea, &cctx);
9179 break;
9180
Bram Moolenaar3988f642020-08-27 22:43:03 +02009181 // TODO: any other commands with an expression argument?
Bram Moolenaardf069ee2020-06-22 23:02:51 +02009182
Bram Moolenaarae616492020-07-28 20:07:27 +02009183 case CMD_append:
9184 case CMD_change:
9185 case CMD_insert:
Bram Moolenaar10b94212021-02-19 21:42:57 +01009186 case CMD_k:
Bram Moolenaarf5a48012020-08-01 17:00:03 +02009187 case CMD_t:
Bram Moolenaarae616492020-07-28 20:07:27 +02009188 case CMD_xit:
9189 not_in_vim9(&ea);
9190 goto erret;
9191
Bram Moolenaar002262f2020-07-08 17:47:57 +02009192 case CMD_SIZE:
Bram Moolenaar3988f642020-08-27 22:43:03 +02009193 if (cctx.ctx_skip != SKIP_YES)
9194 {
9195 semsg(_(e_invalid_command_str), ea.cmd);
9196 goto erret;
9197 }
9198 // We don't check for a next command here.
9199 line = (char_u *)"";
9200 break;
Bram Moolenaar002262f2020-07-08 17:47:57 +02009201
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009202 default:
Bram Moolenaar5163fcc2020-08-27 23:37:09 +02009203 if (cctx.ctx_skip == SKIP_YES)
9204 {
9205 // We don't check for a next command here.
9206 line = (char_u *)"";
9207 }
9208 else
9209 {
9210 // Not recognized, execute with do_cmdline_cmd().
9211 ea.arg = p;
9212 line = compile_exec(line, &ea, &cctx);
9213 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009214 break;
9215 }
Bram Moolenaar5d72ce62020-08-20 23:04:06 +02009216nextline:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009217 if (line == NULL)
9218 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02009219 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009220
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02009221 // Undo any command modifiers.
Bram Moolenaar02194d22020-10-24 23:08:38 +02009222 generate_undo_cmdmods(&cctx);
Bram Moolenaarf4c6e1e2020-10-23 18:02:32 +02009223
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009224 if (cctx.ctx_type_stack.ga_len < 0)
9225 {
9226 iemsg("Type stack underflow");
9227 goto erret;
9228 }
9229 }
9230
9231 if (cctx.ctx_scope != NULL)
9232 {
9233 if (cctx.ctx_scope->se_type == IF_SCOPE)
9234 emsg(_(e_endif));
9235 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
9236 emsg(_(e_endwhile));
9237 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
9238 emsg(_(e_endfor));
9239 else
Bram Moolenaar451c2e32020-08-15 16:33:28 +02009240 emsg(_(e_missing_rcurly));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009241 goto erret;
9242 }
9243
Bram Moolenaarefd88552020-06-18 20:50:10 +02009244 if (!cctx.ctx_had_return)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009245 {
9246 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
9247 {
Bram Moolenaar451c2e32020-08-15 16:33:28 +02009248 emsg(_(e_missing_return_statement));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009249 goto erret;
9250 }
9251
9252 // Return zero if there is no return at the end.
Bram Moolenaar299f3032021-01-08 20:53:09 +01009253 generate_instr(&cctx, ISN_RETURN_ZERO);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009254 }
9255
Bram Moolenaar599410c2021-04-10 14:03:43 +02009256 // When compiled with ":silent!" and there was an error don't consider the
9257 // function compiled.
9258 if (emsg_silent == 0 || did_emsg_silent == did_emsg_silent_before)
Bram Moolenaar05afcee2020-03-31 23:32:31 +02009259 {
9260 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9261 + ufunc->uf_dfunc_idx;
9262 dfunc->df_deleted = FALSE;
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01009263 dfunc->df_script_seq = current_sctx.sc_seq;
Bram Moolenaarf002a412021-01-24 13:34:18 +01009264#ifdef FEAT_PROFILE
Bram Moolenaarb2049902021-01-24 12:53:53 +01009265 if (cctx.ctx_profiling)
9266 {
9267 dfunc->df_instr_prof = instr->ga_data;
9268 dfunc->df_instr_prof_count = instr->ga_len;
9269 }
9270 else
Bram Moolenaarf002a412021-01-24 13:34:18 +01009271#endif
Bram Moolenaarb2049902021-01-24 12:53:53 +01009272 {
9273 dfunc->df_instr = instr->ga_data;
9274 dfunc->df_instr_count = instr->ga_len;
9275 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02009276 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02009277 dfunc->df_has_closure = cctx.ctx_has_closure;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02009278 if (cctx.ctx_outer_used)
9279 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009280 ufunc->uf_def_status = UF_COMPILED;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02009281 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009282
9283 ret = OK;
9284
9285erret:
Bram Moolenaar599410c2021-04-10 14:03:43 +02009286 if (ufunc->uf_def_status == UF_COMPILING)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009287 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01009288 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02009289 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9290 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009291
9292 for (idx = 0; idx < instr->ga_len; ++idx)
9293 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009294 ga_clear(instr);
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009295 VIM_CLEAR(dfunc->df_name);
Bram Moolenaar20431c92020-03-20 18:39:46 +01009296
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02009297 // If using the last entry in the table and it was added above, we
9298 // might as well remove it.
9299 if (!dfunc->df_deleted && new_def_function
Bram Moolenaar45a15082020-05-25 00:28:33 +02009300 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02009301 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01009302 --def_functions.ga_len;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02009303 ufunc->uf_dfunc_idx = 0;
9304 }
Bram Moolenaar701cc6c2021-04-10 13:33:48 +02009305 ufunc->uf_def_status = UF_COMPILE_ERROR;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009306
Bram Moolenaar3cca2992020-04-02 22:57:36 +02009307 while (cctx.ctx_scope != NULL)
9308 drop_scope(&cctx);
9309
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009310 if (errormsg != NULL)
9311 emsg(errormsg);
Bram Moolenaard66960b2020-10-30 20:46:26 +01009312 else if (did_emsg == did_emsg_before)
Bram Moolenaare13bdec2020-10-16 23:16:47 +02009313 emsg(_(e_compiling_def_function_failed));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009314 }
9315
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009316 if (cctx.ctx_redir_lhs.lhs_name != NULL)
9317 {
9318 if (ret == OK)
9319 {
9320 emsg(_(e_missing_redir_end));
9321 ret = FAIL;
9322 }
9323 vim_free(cctx.ctx_redir_lhs.lhs_name);
9324 }
9325
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009326 current_sctx = save_current_sctx;
Bram Moolenaarf4e8cdd2020-10-12 22:07:13 +02009327 estack_compiling = save_estack_compiling;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02009328 if (do_estack_push)
9329 estack_pop();
9330
Bram Moolenaarf62d7392021-04-14 12:40:00 +02009331 vim_free(line_to_free);
Bram Moolenaar20431c92020-03-20 18:39:46 +01009332 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02009333 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009334 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar822ba242020-05-24 23:00:18 +02009335 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009336}
9337
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02009338 void
9339set_function_type(ufunc_T *ufunc)
9340{
9341 int varargs = ufunc->uf_va_name != NULL;
9342 int argcount = ufunc->uf_args.ga_len;
9343
9344 // Create a type for the function, with the return type and any
9345 // argument types.
9346 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
9347 // The type is included in "tt_args".
9348 if (argcount > 0 || varargs)
9349 {
Bram Moolenaar18062fc2021-03-05 21:35:47 +01009350 if (ufunc->uf_type_list.ga_itemsize == 0)
9351 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02009352 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
9353 argcount, &ufunc->uf_type_list);
9354 // Add argument types to the function type.
9355 if (func_type_add_arg_types(ufunc->uf_func_type,
9356 argcount + varargs,
9357 &ufunc->uf_type_list) == FAIL)
9358 return;
9359 ufunc->uf_func_type->tt_argcount = argcount + varargs;
9360 ufunc->uf_func_type->tt_min_argcount =
9361 argcount - ufunc->uf_def_args.ga_len;
9362 if (ufunc->uf_arg_types == NULL)
9363 {
9364 int i;
9365
9366 // lambda does not have argument types.
9367 for (i = 0; i < argcount; ++i)
9368 ufunc->uf_func_type->tt_args[i] = &t_any;
9369 }
9370 else
9371 mch_memmove(ufunc->uf_func_type->tt_args,
9372 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
9373 if (varargs)
9374 {
9375 ufunc->uf_func_type->tt_args[argcount] =
Bram Moolenaar2a389082021-04-09 20:24:31 +02009376 ufunc->uf_va_type == NULL ? &t_list_any : ufunc->uf_va_type;
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02009377 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
9378 }
9379 }
9380 else
9381 // No arguments, can use a predefined type.
9382 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
9383 argcount, &ufunc->uf_type_list);
9384}
9385
9386
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009387/*
9388 * Delete an instruction, free what it contains.
9389 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01009390 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009391delete_instr(isn_T *isn)
9392{
9393 switch (isn->isn_type)
9394 {
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009395 case ISN_DEF:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009396 case ISN_EXEC:
Bram Moolenaar03290b82020-12-19 16:30:44 +01009397 case ISN_LOADAUTO:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009398 case ISN_LOADB:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009399 case ISN_LOADENV:
9400 case ISN_LOADG:
9401 case ISN_LOADOPT:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009402 case ISN_LOADT:
9403 case ISN_LOADW:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009404 case ISN_PUSHEXC:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009405 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009406 case ISN_PUSHS:
Bram Moolenaar08597872020-12-10 19:43:40 +01009407 case ISN_RANGE:
Bram Moolenaar03290b82020-12-19 16:30:44 +01009408 case ISN_STOREAUTO:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009409 case ISN_STOREB:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01009410 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009411 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02009412 case ISN_STORET:
Bram Moolenaar6abdcf82020-11-22 18:15:44 +01009413 case ISN_STOREW:
9414 case ISN_STRINGMEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009415 vim_free(isn->isn_arg.string);
9416 break;
9417
Bram Moolenaar4c137212021-04-19 16:48:48 +02009418 case ISN_SUBSTITUTE:
9419 vim_free(isn->isn_arg.subs.subs_cmd);
9420 vim_free(isn->isn_arg.subs.subs_instr);
9421 break;
9422
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009423 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01009424 case ISN_STORES:
9425 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009426 break;
9427
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02009428 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02009429 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02009430 vim_free(isn->isn_arg.unlet.ul_name);
9431 break;
9432
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009433 case ISN_STOREOPT:
9434 vim_free(isn->isn_arg.storeopt.so_name);
9435 break;
9436
9437 case ISN_PUSHBLOB: // push blob isn_arg.blob
9438 blob_unref(isn->isn_arg.blob);
9439 break;
9440
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009441 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01009442#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009443 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01009444#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009445 break;
9446
9447 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01009448#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009449 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01009450#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01009451 break;
9452
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009453 case ISN_UCALL:
9454 vim_free(isn->isn_arg.ufunc.cuf_name);
9455 break;
9456
Bram Moolenaar221fcc72020-05-05 19:46:20 +02009457 case ISN_FUNCREF:
9458 {
9459 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9460 + isn->isn_arg.funcref.fr_func;
Bram Moolenaar077a4232020-12-22 18:33:27 +01009461 ufunc_T *ufunc = dfunc->df_ufunc;
Bram Moolenaara05e5242020-09-19 18:19:19 +02009462
Bram Moolenaar077a4232020-12-22 18:33:27 +01009463 if (ufunc != NULL && func_name_refcount(ufunc->uf_name))
9464 func_ptr_unref(ufunc);
Bram Moolenaara05e5242020-09-19 18:19:19 +02009465 }
9466 break;
9467
9468 case ISN_DCALL:
9469 {
9470 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9471 + isn->isn_arg.dfunc.cdf_idx;
9472
Bram Moolenaar148ce7a2020-09-23 21:57:23 +02009473 if (dfunc->df_ufunc != NULL
9474 && func_name_refcount(dfunc->df_ufunc->uf_name))
Bram Moolenaara05e5242020-09-19 18:19:19 +02009475 func_ptr_unref(dfunc->df_ufunc);
Bram Moolenaar221fcc72020-05-05 19:46:20 +02009476 }
9477 break;
9478
Bram Moolenaar38ddf332020-07-31 22:05:04 +02009479 case ISN_NEWFUNC:
Bram Moolenaarce658352020-07-31 23:47:12 +02009480 {
9481 char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
9482 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
9483
9484 if (ufunc != NULL)
9485 {
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009486 unlink_def_function(ufunc);
Bram Moolenaarce658352020-07-31 23:47:12 +02009487 func_ptr_unref(ufunc);
9488 }
9489
9490 vim_free(lambda);
9491 vim_free(isn->isn_arg.newfunc.nf_global);
9492 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02009493 break;
9494
Bram Moolenaar5e654232020-09-16 15:22:00 +02009495 case ISN_CHECKTYPE:
Bram Moolenaaraa210a32021-01-02 15:41:03 +01009496 case ISN_SETTYPE:
Bram Moolenaar5e654232020-09-16 15:22:00 +02009497 free_type(isn->isn_arg.type.ct_type);
9498 break;
9499
Bram Moolenaar02194d22020-10-24 23:08:38 +02009500 case ISN_CMDMOD:
9501 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
9502 ->cmod_filter_regmatch.regprog);
9503 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
9504 break;
9505
Bram Moolenaar4aab88d2020-12-24 21:56:41 +01009506 case ISN_LOADSCRIPT:
9507 case ISN_STORESCRIPT:
9508 vim_free(isn->isn_arg.script.scriptref);
9509 break;
9510
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01009511 case ISN_TRY:
9512 vim_free(isn->isn_arg.try.try_ref);
9513 break;
9514
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009515 case ISN_2BOOL:
9516 case ISN_2STRING:
Bram Moolenaar418f1df2020-08-12 21:34:49 +02009517 case ISN_2STRING_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009518 case ISN_ADDBLOB:
9519 case ISN_ADDLIST:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009520 case ISN_ANYINDEX:
9521 case ISN_ANYSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009522 case ISN_BCALL:
Bram Moolenaar80b0e5e2020-10-19 20:45:36 +02009523 case ISN_BLOBAPPEND:
Bram Moolenaarcfc30232021-04-11 20:26:34 +02009524 case ISN_BLOBINDEX:
9525 case ISN_BLOBSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009526 case ISN_CATCH:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009527 case ISN_CHECKLEN:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009528 case ISN_CHECKNR:
Bram Moolenaar02194d22020-10-24 23:08:38 +02009529 case ISN_CMDMOD_REV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009530 case ISN_COMPAREANY:
9531 case ISN_COMPAREBLOB:
9532 case ISN_COMPAREBOOL:
9533 case ISN_COMPAREDICT:
9534 case ISN_COMPAREFLOAT:
9535 case ISN_COMPAREFUNC:
9536 case ISN_COMPARELIST:
9537 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009538 case ISN_COMPARESPECIAL:
9539 case ISN_COMPARESTRING:
9540 case ISN_CONCAT:
Bram Moolenaar2bb26582020-10-03 22:52:39 +02009541 case ISN_COND2BOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009542 case ISN_DROP:
9543 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02009544 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02009545 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009546 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02009547 case ISN_EXECCONCAT:
9548 case ISN_EXECUTE:
Bram Moolenaar7e82c5f2021-02-21 21:32:45 +01009549 case ISN_FINALLY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009550 case ISN_FOR:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009551 case ISN_GETITEM:
9552 case ISN_JUMP:
Bram Moolenaar38a3bfa2021-03-29 22:14:55 +02009553 case ISN_JUMP_IF_ARG_SET:
Bram Moolenaar1dcae592020-10-19 19:02:42 +02009554 case ISN_LISTAPPEND:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02009555 case ISN_LISTINDEX:
Bram Moolenaared591872020-08-15 22:14:53 +02009556 case ISN_LISTSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009557 case ISN_LOAD:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02009558 case ISN_LOADBDICT:
9559 case ISN_LOADGDICT:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02009560 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009561 case ISN_LOADREG:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02009562 case ISN_LOADTDICT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009563 case ISN_LOADV:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02009564 case ISN_LOADWDICT:
Bram Moolenaar0b4c66c2020-09-14 21:39:44 +02009565 case ISN_LOCKCONST:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009566 case ISN_MEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009567 case ISN_NEGATENR:
9568 case ISN_NEWDICT:
9569 case ISN_NEWLIST:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009570 case ISN_OPANY:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009571 case ISN_OPFLOAT:
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009572 case ISN_FINISH:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009573 case ISN_OPNR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009574 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02009575 case ISN_PCALL_END:
Bram Moolenaarb2049902021-01-24 12:53:53 +01009576 case ISN_PROF_END:
9577 case ISN_PROF_START:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009578 case ISN_PUSHBOOL:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009579 case ISN_PUSHF:
9580 case ISN_PUSHNR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009581 case ISN_PUSHSPEC:
Bram Moolenaarc3516f72020-09-08 22:45:35 +02009582 case ISN_PUT:
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009583 case ISN_REDIREND:
9584 case ISN_REDIRSTART:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009585 case ISN_RETURN:
Bram Moolenaar299f3032021-01-08 20:53:09 +01009586 case ISN_RETURN_ZERO:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009587 case ISN_SHUFFLE:
9588 case ISN_SLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009589 case ISN_STORE:
Bram Moolenaar4f5e3972020-12-21 17:30:50 +01009590 case ISN_STOREINDEX:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009591 case ISN_STORENR:
9592 case ISN_STOREOUTER:
Bram Moolenaar2d1c57e2021-04-19 20:50:03 +02009593 case ISN_STORERANGE:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009594 case ISN_STOREREG:
Bram Moolenaarcc673e72020-08-16 17:33:35 +02009595 case ISN_STOREV:
9596 case ISN_STRINDEX:
9597 case ISN_STRSLICE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009598 case ISN_THROW:
Bram Moolenaarc150c092021-02-13 15:02:46 +01009599 case ISN_TRYCONT:
Bram Moolenaar752fc692021-01-04 21:57:11 +01009600 case ISN_UNLETINDEX:
Bram Moolenaar5b5ae292021-02-20 17:04:02 +01009601 case ISN_UNLETRANGE:
Bram Moolenaar792f7862020-11-23 08:31:18 +01009602 case ISN_UNPACK:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009603 // nothing allocated
9604 break;
9605 }
9606}
9607
9608/*
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009609 * Free all instructions for "dfunc" except df_name.
Bram Moolenaar20431c92020-03-20 18:39:46 +01009610 */
9611 static void
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009612delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
Bram Moolenaar20431c92020-03-20 18:39:46 +01009613{
9614 int idx;
9615
9616 ga_clear(&dfunc->df_def_args_isn);
9617
9618 if (dfunc->df_instr != NULL)
9619 {
9620 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
9621 delete_instr(dfunc->df_instr + idx);
9622 VIM_CLEAR(dfunc->df_instr);
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009623 dfunc->df_instr = NULL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009624 }
Bram Moolenaarc05fe072021-01-24 21:30:48 +01009625#ifdef FEAT_PROFILE
9626 if (dfunc->df_instr_prof != NULL)
9627 {
9628 for (idx = 0; idx < dfunc->df_instr_prof_count; ++idx)
9629 delete_instr(dfunc->df_instr_prof + idx);
9630 VIM_CLEAR(dfunc->df_instr_prof);
9631 dfunc->df_instr_prof = NULL;
9632 }
9633#endif
Bram Moolenaar20431c92020-03-20 18:39:46 +01009634
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009635 if (mark_deleted)
9636 dfunc->df_deleted = TRUE;
9637 if (dfunc->df_ufunc != NULL)
9638 dfunc->df_ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar20431c92020-03-20 18:39:46 +01009639}
9640
9641/*
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009642 * When a user function is deleted, clear the contents of any associated def
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009643 * function, unless another user function still uses it.
9644 * The position in def_functions can be re-used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009645 */
9646 void
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009647unlink_def_function(ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009648{
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009649 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009650 {
9651 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9652 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009653
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009654 if (--dfunc->df_refcount <= 0)
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009655 delete_def_function_contents(dfunc, TRUE);
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02009656 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009657 ufunc->uf_dfunc_idx = 0;
9658 if (dfunc->df_ufunc == ufunc)
9659 dfunc->df_ufunc = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009660 }
9661}
9662
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009663/*
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009664 * Used when a user function refers to an existing dfunc.
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009665 */
9666 void
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009667link_def_function(ufunc_T *ufunc)
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009668{
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009669 if (ufunc->uf_dfunc_idx > 0)
9670 {
9671 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9672 + ufunc->uf_dfunc_idx;
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009673
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009674 ++dfunc->df_refcount;
9675 }
Bram Moolenaarfdeab652020-09-19 15:16:50 +02009676}
9677
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009678#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01009679/*
9680 * Free all functions defined with ":def".
9681 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009682 void
9683free_def_functions(void)
9684{
Bram Moolenaar20431c92020-03-20 18:39:46 +01009685 int idx;
9686
9687 for (idx = 0; idx < def_functions.ga_len; ++idx)
9688 {
9689 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
9690
Bram Moolenaarcdc40c42020-12-26 17:43:08 +01009691 delete_def_function_contents(dfunc, TRUE);
Bram Moolenaarcd45ed02020-12-22 17:35:54 +01009692 vim_free(dfunc->df_name);
Bram Moolenaar20431c92020-03-20 18:39:46 +01009693 }
9694
9695 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01009696}
9697#endif
9698
9699
9700#endif // FEAT_EVAL