blob: dc10b4851b8b5caca7930e5877956f10a5d9f6bd [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;
47 int is_had_return; // every block ends in :return
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010048 int is_if_label; // instruction idx at IF or ELSEIF
49 endlabel_T *is_end_label; // instructions to set end label
50} ifscope_T;
51
52/*
53 * info specific for the scope of :while
54 */
55typedef struct {
56 int ws_top_label; // instruction idx at WHILE
57 endlabel_T *ws_end_label; // instructions to set end
58} whilescope_T;
59
60/*
61 * info specific for the scope of :for
62 */
63typedef struct {
64 int fs_top_label; // instruction idx at FOR
65 endlabel_T *fs_end_label; // break instructions
66} forscope_T;
67
68/*
69 * info specific for the scope of :try
70 */
71typedef struct {
72 int ts_try_label; // instruction idx at TRY
73 endlabel_T *ts_end_label; // jump to :finally or :endtry
74 int ts_catch_label; // instruction idx of last CATCH
75 int ts_caught_all; // "catch" without argument encountered
76} tryscope_T;
77
78typedef enum {
79 NO_SCOPE,
80 IF_SCOPE,
81 WHILE_SCOPE,
82 FOR_SCOPE,
83 TRY_SCOPE,
84 BLOCK_SCOPE
85} scopetype_T;
86
87/*
88 * Info for one scope, pointed to by "ctx_scope".
89 */
90typedef struct scope_S scope_T;
91struct scope_S {
92 scope_T *se_outer; // scope containing this one
93 scopetype_T se_type;
94 int se_local_count; // ctx_locals.ga_len before scope
Bram Moolenaarefd88552020-06-18 20:50:10 +020095 skip_T se_skip_save; // ctx_skip before the block
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010096 union {
97 ifscope_T se_if;
98 whilescope_T se_while;
99 forscope_T se_for;
100 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +0100101 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100102};
103
104/*
105 * Entry for "ctx_locals". Used for arguments and local variables.
106 */
107typedef struct {
108 char_u *lv_name;
109 type_T *lv_type;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200110 int lv_idx; // index of the variable on the stack
111 int lv_from_outer; // when TRUE using ctx_outer scope
112 int lv_const; // when TRUE cannot be assigned to
113 int lv_arg; // when TRUE this is an argument
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100114} lvar_T;
115
116/*
117 * Context for compiling lines of Vim script.
118 * Stores info about the local variables and condition stack.
119 */
120struct cctx_S {
121 ufunc_T *ctx_ufunc; // current function
122 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200123 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100124 garray_T ctx_instr; // generated instructions
125
126 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200127 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100128
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200129 int ctx_closure_count; // number of closures created in the
130 // function
131
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100132 garray_T ctx_imports; // imported items
133
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200134 skip_T ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100135 scope_T *ctx_scope; // current scope, NULL at toplevel
Bram Moolenaarefd88552020-06-18 20:50:10 +0200136 int ctx_had_return; // last seen statement was "return"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100137
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200138 cctx_T *ctx_outer; // outer scope for lambda or nested
139 // function
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200140 int ctx_outer_used; // var in ctx_outer was used
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200141
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100142 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200143 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100144};
145
146static char e_var_notfound[] = N_("E1001: variable not found: %s");
147static char e_syntax_at[] = N_("E1002: Syntax error at %s");
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +0200148static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
Bram Moolenaar47a519a2020-06-14 23:05:10 +0200149static char e_cannot_use_void[] = N_("E1031: Cannot use void value");
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +0200150static char e_namespace[] = N_("E1075: Namespace not supported: %s");
Bram Moolenaarf9b2b492020-08-05 14:34:14 +0200151static char e_unknown_var[] = N_("E1089: unknown variable: %s");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100152
Bram Moolenaar20431c92020-03-20 18:39:46 +0100153static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200154static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100155
156/*
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200157 * Lookup variable "name" in the local scope and return it.
158 * Return NULL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100159 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200160 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100161lookup_local(char_u *name, size_t len, cctx_T *cctx)
162{
163 int idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200164 lvar_T *lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100165
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100166 if (len == 0)
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200167 return NULL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200168
169 // Find local in current function scope.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100170 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
171 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200172 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100173 if (STRNCMP(name, lvar->lv_name, len) == 0
174 && STRLEN(lvar->lv_name) == len)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200175 {
176 lvar->lv_from_outer = FALSE;
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200177 return lvar;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200178 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100179 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200180
181 // Find local in outer function scope.
182 if (cctx->ctx_outer != NULL)
183 {
184 lvar = lookup_local(name, len, cctx->ctx_outer);
185 if (lvar != NULL)
186 {
187 // TODO: are there situations we should not mark the outer scope as
188 // used?
189 cctx->ctx_outer_used = TRUE;
190 lvar->lv_from_outer = TRUE;
191 return lvar;
192 }
193 }
194
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200195 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100196}
197
198/*
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200199 * Lookup an argument in the current function and an enclosing function.
200 * Returns the argument index in "idxp"
201 * Returns the argument type in "type"
202 * Sets "gen_load_outer" to TRUE if found in outer scope.
203 * Returns OK when found, FAIL otherwise.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100204 */
205 static int
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200206lookup_arg(
207 char_u *name,
208 size_t len,
209 int *idxp,
210 type_T **type,
211 int *gen_load_outer,
212 cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100213{
214 int idx;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200215 char_u *va_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100216
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100217 if (len == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200218 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100219 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
220 {
221 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
222
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200223 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
224 {
225 if (idxp != NULL)
226 {
227 // Arguments are located above the frame pointer. One further
228 // if there is a vararg argument
229 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
230 + STACK_FRAME_SIZE)
231 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
232
233 if (cctx->ctx_ufunc->uf_arg_types != NULL)
234 *type = cctx->ctx_ufunc->uf_arg_types[idx];
235 else
236 *type = &t_any;
237 }
238 return OK;
239 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100240 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100241
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200242 va_name = cctx->ctx_ufunc->uf_va_name;
243 if (va_name != NULL
244 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
245 {
246 if (idxp != NULL)
247 {
248 // varargs is always the last argument
249 *idxp = -STACK_FRAME_SIZE - 1;
250 *type = cctx->ctx_ufunc->uf_va_type;
251 }
252 return OK;
253 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100254
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200255 if (cctx->ctx_outer != NULL)
256 {
257 // Lookup the name for an argument of the outer function.
258 if (lookup_arg(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
259 == OK)
260 {
261 *gen_load_outer = TRUE;
262 return OK;
263 }
264 }
265
266 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100267}
268
269/*
270 * Lookup a variable in the current script.
271 * Returns OK or FAIL.
272 */
273 static int
274lookup_script(char_u *name, size_t len)
275{
276 int cc;
277 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
278 dictitem_T *di;
279
280 cc = name[len];
281 name[len] = NUL;
282 di = find_var_in_ht(ht, 0, name, TRUE);
283 name[len] = cc;
284 return di == NULL ? FAIL: OK;
285}
286
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100287/*
288 * Check if "p[len]" is already defined, either in script "import_sid" or in
289 * compilation context "cctx".
290 * Return FAIL and give an error if it defined.
291 */
292 int
Bram Moolenaarcbb6bdc2020-07-06 21:53:17 +0200293check_defined(char_u *p, size_t len, cctx_T *cctx)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100294{
Bram Moolenaarad486a02020-08-01 23:22:18 +0200295 int c = p[len];
296
297 p[len] = NUL;
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100298 if (lookup_script(p, len) == OK
299 || (cctx != NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200300 && (lookup_local(p, len, cctx) != NULL
Bram Moolenaareef21022020-08-01 22:16:43 +0200301 || lookup_arg(p, len, NULL, NULL, NULL, cctx) == OK))
Bram Moolenaarad486a02020-08-01 23:22:18 +0200302 || find_imported(p, len, cctx) != NULL
303 || find_func_even_dead(p, FALSE, cctx) != NULL)
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100304 {
Bram Moolenaarad486a02020-08-01 23:22:18 +0200305 p[len] = c;
Bram Moolenaareef21022020-08-01 22:16:43 +0200306 semsg(_(e_already_defined), p);
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100307 return FAIL;
308 }
Bram Moolenaarad486a02020-08-01 23:22:18 +0200309 p[len] = c;
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100310 return OK;
311}
312
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200313/*
314 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
315 * be freed later.
316 */
317 static type_T *
318alloc_type(garray_T *type_gap)
319{
320 type_T *type;
321
322 if (ga_grow(type_gap, 1) == FAIL)
323 return NULL;
324 type = ALLOC_CLEAR_ONE(type_T);
325 if (type != NULL)
326 {
327 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
328 ++type_gap->ga_len;
329 }
330 return type;
331}
332
Bram Moolenaar6110e792020-07-08 19:35:21 +0200333 void
334clear_type_list(garray_T *gap)
335{
336 while (gap->ga_len > 0)
337 vim_free(((type_T **)gap->ga_data)[--gap->ga_len]);
338 ga_clear(gap);
339}
340
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100341 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200342get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100343{
344 type_T *type;
345
346 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200347 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100348 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200349 if (member_type->tt_type == VAR_VOID
350 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100351 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100352 if (member_type->tt_type == VAR_BOOL)
353 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100354 if (member_type->tt_type == VAR_NUMBER)
355 return &t_list_number;
356 if (member_type->tt_type == VAR_STRING)
357 return &t_list_string;
358
359 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200360 type = alloc_type(type_gap);
361 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100362 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100363 type->tt_type = VAR_LIST;
364 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200365 type->tt_argcount = 0;
366 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100367 return type;
368}
369
370 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200371get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100372{
373 type_T *type;
374
375 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200376 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100377 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200378 if (member_type->tt_type == VAR_VOID
379 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100380 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100381 if (member_type->tt_type == VAR_BOOL)
382 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100383 if (member_type->tt_type == VAR_NUMBER)
384 return &t_dict_number;
385 if (member_type->tt_type == VAR_STRING)
386 return &t_dict_string;
387
388 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200389 type = alloc_type(type_gap);
390 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100391 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100392 type->tt_type = VAR_DICT;
393 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200394 type->tt_argcount = 0;
395 type->tt_args = NULL;
396 return type;
397}
398
399/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200400 * Allocate a new type for a function.
401 */
402 static type_T *
403alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
404{
405 type_T *type = alloc_type(type_gap);
406
407 if (type == NULL)
408 return &t_any;
409 type->tt_type = VAR_FUNC;
410 type->tt_member = ret_type;
411 type->tt_argcount = argcount;
412 type->tt_args = NULL;
413 return type;
414}
415
416/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200417 * Get a function type, based on the return type "ret_type".
418 * If "argcount" is -1 or 0 a predefined type can be used.
419 * If "argcount" > 0 always create a new type, so that arguments can be added.
420 */
421 static type_T *
422get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
423{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200424 // recognize commonly used types
425 if (argcount <= 0)
426 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200427 if (ret_type == &t_unknown)
428 {
429 // (argcount == 0) is not possible
430 return &t_func_unknown;
431 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200432 if (ret_type == &t_void)
433 {
434 if (argcount == 0)
435 return &t_func_0_void;
436 else
437 return &t_func_void;
438 }
439 if (ret_type == &t_any)
440 {
441 if (argcount == 0)
442 return &t_func_0_any;
443 else
444 return &t_func_any;
445 }
446 if (ret_type == &t_number)
447 {
448 if (argcount == 0)
449 return &t_func_0_number;
450 else
451 return &t_func_number;
452 }
453 if (ret_type == &t_string)
454 {
455 if (argcount == 0)
456 return &t_func_0_string;
457 else
458 return &t_func_string;
459 }
460 }
461
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200462 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100463}
464
Bram Moolenaara8c17702020-04-01 21:17:24 +0200465/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200466 * For a function type, reserve space for "argcount" argument types (including
467 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200468 */
469 static int
470func_type_add_arg_types(
471 type_T *functype,
472 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200473 garray_T *type_gap)
474{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200475 // To make it easy to free the space needed for the argument types, add the
476 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200477 if (ga_grow(type_gap, 1) == FAIL)
478 return FAIL;
479 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
480 if (functype->tt_args == NULL)
481 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200482 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
483 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200484 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200485 return OK;
486}
487
488/*
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200489 * Get a type_T for a typval_T.
490 * "type_list" is used to temporarily create types in.
Bram Moolenaara8c17702020-04-01 21:17:24 +0200491 */
Bram Moolenaar34db91f2020-06-13 19:00:10 +0200492 type_T *
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200493typval2type(typval_T *tv, garray_T *type_gap)
Bram Moolenaara8c17702020-04-01 21:17:24 +0200494{
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200495 type_T *actual;
496 type_T *member_type;
497
Bram Moolenaara8c17702020-04-01 21:17:24 +0200498 if (tv->v_type == VAR_NUMBER)
499 return &t_number;
500 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200501 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200502 if (tv->v_type == VAR_STRING)
503 return &t_string;
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200504
505 if (tv->v_type == VAR_LIST
506 && tv->vval.v_list != NULL
507 && tv->vval.v_list->lv_first != NULL)
508 {
509 // Use the type of the first member, it is the most specific.
510 member_type = typval2type(&tv->vval.v_list->lv_first->li_tv, type_gap);
511 return get_list_type(member_type, type_gap);
512 }
513
514 if (tv->v_type == VAR_DICT
515 && tv->vval.v_dict != NULL
516 && tv->vval.v_dict->dv_hashtab.ht_used > 0)
517 {
518 dict_iterator_T iter;
519 typval_T *value;
520
521 // Use the type of the first value, it is the most specific.
522 dict_iterate_start(tv, &iter);
523 dict_iterate_next(&iter, &value);
524 member_type = typval2type(value, type_gap);
525 return get_dict_type(member_type, type_gap);
526 }
527
528 if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
529 {
530 char_u *name = NULL;
531 ufunc_T *ufunc = NULL;
532
533 if (tv->v_type == VAR_PARTIAL)
534 {
535 if (tv->vval.v_partial->pt_func != NULL)
536 ufunc = tv->vval.v_partial->pt_func;
537 else
538 name = tv->vval.v_partial->pt_name;
539 }
540 else
541 name = tv->vval.v_string;
542 if (name != NULL)
543 // TODO: how about a builtin function?
544 ufunc = find_func(name, FALSE, NULL);
Bram Moolenaar4fc224c2020-07-26 17:56:25 +0200545 if (ufunc != NULL)
546 {
547 // May need to get the argument types from default values by
548 // compiling the function.
549 if (ufunc->uf_def_status == UF_TO_BE_COMPILED
550 && compile_def_function(ufunc, TRUE, NULL) == FAIL)
551 return NULL;
552 if (ufunc->uf_func_type != NULL)
553 return ufunc->uf_func_type;
554 }
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200555 }
556
557 actual = alloc_type(type_gap);
558 if (actual == NULL)
559 return NULL;
560 actual->tt_type = tv->v_type;
561 actual->tt_member = &t_any;
562
563 return actual;
564}
565
566/*
567 * Get a type_T for a typval_T, used for v: variables.
568 * "type_list" is used to temporarily create types in.
569 */
570 type_T *
571typval2type_vimvar(typval_T *tv, garray_T *type_gap)
572{
Bram Moolenaara8c17702020-04-01 21:17:24 +0200573 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
574 return &t_list_string;
575 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
576 return &t_dict_any;
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +0200577 return typval2type(tv, type_gap);
578}
579
580
581/*
582 * Return FAIL if "expected" and "actual" don't match.
583 */
584 int
585check_typval_type(type_T *expected, typval_T *actual_tv)
586{
587 garray_T type_list;
588 type_T *actual_type;
589 int res = FAIL;
590
591 ga_init2(&type_list, sizeof(type_T *), 10);
592 actual_type = typval2type(actual_tv, &type_list);
593 if (actual_type != NULL)
594 res = check_type(expected, actual_type, TRUE);
595 clear_type_list(&type_list);
596 return res;
Bram Moolenaara8c17702020-04-01 21:17:24 +0200597}
598
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200599 static void
600type_mismatch(type_T *expected, type_T *actual)
601{
602 char *tofree1, *tofree2;
603
604 semsg(_("E1013: type mismatch, expected %s but got %s"),
605 type_name(expected, &tofree1), type_name(actual, &tofree2));
606 vim_free(tofree1);
607 vim_free(tofree2);
608}
609
610 static void
611arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
612{
613 char *tofree1, *tofree2;
614
615 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
616 argidx,
617 type_name(expected, &tofree1), type_name(actual, &tofree2));
618 vim_free(tofree1);
619 vim_free(tofree2);
620}
621
622/*
623 * Check if the expected and actual types match.
624 * Does not allow for assigning "any" to a specific type.
625 */
Bram Moolenaar34db91f2020-06-13 19:00:10 +0200626 int
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200627check_type(type_T *expected, type_T *actual, int give_msg)
628{
629 int ret = OK;
630
631 // When expected is "unknown" we accept any actual type.
632 // When expected is "any" we accept any actual type except "void".
633 if (expected->tt_type != VAR_UNKNOWN
634 && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID))
635
636 {
637 if (expected->tt_type != actual->tt_type)
638 {
639 if (give_msg)
640 type_mismatch(expected, actual);
641 return FAIL;
642 }
643 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
644 {
645 // "unknown" is used for an empty list or dict
646 if (actual->tt_member != &t_unknown)
647 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
648 }
649 else if (expected->tt_type == VAR_FUNC)
650 {
651 if (expected->tt_member != &t_unknown)
652 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
653 if (ret == OK && expected->tt_argcount != -1
654 && (actual->tt_argcount < expected->tt_min_argcount
655 || actual->tt_argcount > expected->tt_argcount))
656 ret = FAIL;
Bram Moolenaarb8070e32020-07-23 20:56:04 +0200657 if (expected->tt_args != NULL && actual->tt_args != NULL)
658 {
659 int i;
660
661 for (i = 0; i < expected->tt_argcount; ++i)
662 if (check_type(expected->tt_args[i], actual->tt_args[i],
663 FALSE) == FAIL)
664 {
665 ret = FAIL;
666 break;
667 }
668 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200669 }
670 if (ret == FAIL && give_msg)
671 type_mismatch(expected, actual);
672 }
673 return ret;
674}
675
Bram Moolenaar65b95452020-07-19 14:03:09 +0200676
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100677/////////////////////////////////////////////////////////////////////
678// Following generate_ functions expect the caller to call ga_grow().
679
Bram Moolenaar9b68c822020-06-18 19:31:08 +0200680#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return NULL
681#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return OK
Bram Moolenaar080457c2020-03-03 21:53:32 +0100682
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100683/*
684 * Generate an instruction without arguments.
685 * Returns a pointer to the new instruction, NULL if failed.
686 */
687 static isn_T *
688generate_instr(cctx_T *cctx, isntype_T isn_type)
689{
690 garray_T *instr = &cctx->ctx_instr;
691 isn_T *isn;
692
Bram Moolenaar080457c2020-03-03 21:53:32 +0100693 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100694 if (ga_grow(instr, 1) == FAIL)
695 return NULL;
696 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
697 isn->isn_type = isn_type;
698 isn->isn_lnum = cctx->ctx_lnum + 1;
699 ++instr->ga_len;
700
701 return isn;
702}
703
704/*
705 * Generate an instruction without arguments.
706 * "drop" will be removed from the stack.
707 * Returns a pointer to the new instruction, NULL if failed.
708 */
709 static isn_T *
710generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
711{
712 garray_T *stack = &cctx->ctx_type_stack;
713
Bram Moolenaar080457c2020-03-03 21:53:32 +0100714 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100715 stack->ga_len -= drop;
716 return generate_instr(cctx, isn_type);
717}
718
719/*
720 * Generate instruction "isn_type" and put "type" on the type stack.
721 */
722 static isn_T *
723generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
724{
725 isn_T *isn;
726 garray_T *stack = &cctx->ctx_type_stack;
727
728 if ((isn = generate_instr(cctx, isn_type)) == NULL)
729 return NULL;
730
731 if (ga_grow(stack, 1) == FAIL)
732 return NULL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +0200733 ((type_T **)stack->ga_data)[stack->ga_len] = type == NULL ? &t_any : type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100734 ++stack->ga_len;
735
736 return isn;
737}
738
739/*
740 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
741 */
742 static int
743may_generate_2STRING(int offset, cctx_T *cctx)
744{
745 isn_T *isn;
746 garray_T *stack = &cctx->ctx_type_stack;
747 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
748
749 if ((*type)->tt_type == VAR_STRING)
750 return OK;
751 *type = &t_string;
752
753 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
754 return FAIL;
755 isn->isn_arg.number = offset;
756
757 return OK;
758}
759
760 static int
761check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
762{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200763 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100764 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200765 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100766 {
767 if (*op == '+')
Bram Moolenaardf069ee2020-06-22 23:02:51 +0200768 emsg(_("E1051: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100769 else
770 semsg(_("E1036: %c requires number or float arguments"), *op);
771 return FAIL;
772 }
773 return OK;
774}
775
776/*
777 * Generate an instruction with two arguments. The instruction depends on the
778 * type of the arguments.
779 */
780 static int
781generate_two_op(cctx_T *cctx, char_u *op)
782{
783 garray_T *stack = &cctx->ctx_type_stack;
784 type_T *type1;
785 type_T *type2;
786 vartype_T vartype;
787 isn_T *isn;
788
Bram Moolenaar080457c2020-03-03 21:53:32 +0100789 RETURN_OK_IF_SKIP(cctx);
790
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100791 // Get the known type of the two items on the stack. If they are matching
792 // use a type-specific instruction. Otherwise fall back to runtime type
793 // checking.
794 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
795 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200796 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100797 if (type1->tt_type == type2->tt_type
798 && (type1->tt_type == VAR_NUMBER
799 || type1->tt_type == VAR_LIST
800#ifdef FEAT_FLOAT
801 || type1->tt_type == VAR_FLOAT
802#endif
803 || type1->tt_type == VAR_BLOB))
804 vartype = type1->tt_type;
805
806 switch (*op)
807 {
808 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200809 && type1->tt_type != VAR_ANY
810 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100811 && check_number_or_float(
812 type1->tt_type, type2->tt_type, op) == FAIL)
813 return FAIL;
814 isn = generate_instr_drop(cctx,
815 vartype == VAR_NUMBER ? ISN_OPNR
816 : vartype == VAR_LIST ? ISN_ADDLIST
817 : vartype == VAR_BLOB ? ISN_ADDBLOB
818#ifdef FEAT_FLOAT
819 : vartype == VAR_FLOAT ? ISN_OPFLOAT
820#endif
821 : ISN_OPANY, 1);
822 if (isn != NULL)
823 isn->isn_arg.op.op_type = EXPR_ADD;
824 break;
825
826 case '-':
827 case '*':
828 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
829 op) == FAIL)
830 return FAIL;
831 if (vartype == VAR_NUMBER)
832 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
833#ifdef FEAT_FLOAT
834 else if (vartype == VAR_FLOAT)
835 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
836#endif
837 else
838 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
839 if (isn != NULL)
840 isn->isn_arg.op.op_type = *op == '*'
841 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
842 break;
843
Bram Moolenaar4c683752020-04-05 21:38:23 +0200844 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100845 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200846 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100847 && type2->tt_type != VAR_NUMBER))
848 {
849 emsg(_("E1035: % requires number arguments"));
850 return FAIL;
851 }
852 isn = generate_instr_drop(cctx,
853 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
854 if (isn != NULL)
855 isn->isn_arg.op.op_type = EXPR_REM;
856 break;
857 }
858
859 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200860 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100861 {
862 type_T *type = &t_any;
863
864#ifdef FEAT_FLOAT
865 // float+number and number+float results in float
866 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
867 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
868 type = &t_float;
869#endif
870 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
871 }
872
873 return OK;
874}
875
876/*
Bram Moolenaara5565e42020-05-09 15:44:01 +0200877 * Get the instruction to use for comparing "type1" with "type2"
878 * Return ISN_DROP when failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100879 */
Bram Moolenaara5565e42020-05-09 15:44:01 +0200880 static isntype_T
881get_compare_isn(exptype_T exptype, vartype_T type1, vartype_T type2)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100882{
883 isntype_T isntype = ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100884
Bram Moolenaar4c683752020-04-05 21:38:23 +0200885 if (type1 == VAR_UNKNOWN)
886 type1 = VAR_ANY;
887 if (type2 == VAR_UNKNOWN)
888 type2 = VAR_ANY;
889
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100890 if (type1 == type2)
891 {
892 switch (type1)
893 {
894 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
895 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
896 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
897 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
898 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
899 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
900 case VAR_LIST: isntype = ISN_COMPARELIST; break;
901 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
902 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100903 default: isntype = ISN_COMPAREANY; break;
904 }
905 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200906 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100907 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
908 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
909 isntype = ISN_COMPAREANY;
910
911 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
912 && (isntype == ISN_COMPAREBOOL
913 || isntype == ISN_COMPARESPECIAL
914 || isntype == ISN_COMPARENR
915 || isntype == ISN_COMPAREFLOAT))
916 {
917 semsg(_("E1037: Cannot use \"%s\" with %s"),
918 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200919 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100920 }
921 if (isntype == ISN_DROP
922 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
923 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
924 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
925 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
926 && exptype != EXPR_IS && exptype != EXPR_ISNOT
927 && (type1 == VAR_BLOB || type2 == VAR_BLOB
928 || type1 == VAR_LIST || type2 == VAR_LIST))))
929 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100930 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100931 vartype_name(type1), vartype_name(type2));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200932 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100933 }
Bram Moolenaara5565e42020-05-09 15:44:01 +0200934 return isntype;
935}
936
Bram Moolenaar543e6f32020-07-10 22:45:38 +0200937 int
938check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2)
939{
940 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
941 return FAIL;
942 return OK;
943}
944
Bram Moolenaara5565e42020-05-09 15:44:01 +0200945/*
946 * Generate an ISN_COMPARE* instruction with a boolean result.
947 */
948 static int
949generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
950{
951 isntype_T isntype;
952 isn_T *isn;
953 garray_T *stack = &cctx->ctx_type_stack;
954 vartype_T type1;
955 vartype_T type2;
956
957 RETURN_OK_IF_SKIP(cctx);
958
959 // Get the known type of the two items on the stack. If they are matching
960 // use a type-specific instruction. Otherwise fall back to runtime type
961 // checking.
962 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
963 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
964 isntype = get_compare_isn(exptype, type1, type2);
965 if (isntype == ISN_DROP)
966 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100967
968 if ((isn = generate_instr(cctx, isntype)) == NULL)
969 return FAIL;
970 isn->isn_arg.op.op_type = exptype;
971 isn->isn_arg.op.op_ic = ic;
972
973 // takes two arguments, puts one bool back
974 if (stack->ga_len >= 2)
975 {
976 --stack->ga_len;
977 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
978 }
979
980 return OK;
981}
982
983/*
984 * Generate an ISN_2BOOL instruction.
985 */
986 static int
987generate_2BOOL(cctx_T *cctx, int invert)
988{
989 isn_T *isn;
990 garray_T *stack = &cctx->ctx_type_stack;
991
Bram Moolenaar080457c2020-03-03 21:53:32 +0100992 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100993 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
994 return FAIL;
995 isn->isn_arg.number = invert;
996
997 // type becomes bool
998 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
999
1000 return OK;
1001}
1002
1003 static int
1004generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
1005{
1006 isn_T *isn;
1007 garray_T *stack = &cctx->ctx_type_stack;
1008
Bram Moolenaar080457c2020-03-03 21:53:32 +01001009 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001010 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
1011 return FAIL;
Bram Moolenaar939b5db2020-04-28 22:49:08 +02001012 // TODO: whole type, e.g. for a function also arg and return types
1013 isn->isn_arg.type.ct_type = vartype->tt_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001014 isn->isn_arg.type.ct_off = offset;
1015
1016 // type becomes vartype
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001017 ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001018
1019 return OK;
1020}
1021
1022/*
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001023 * Check that
1024 * - "actual" is "expected" type or
1025 * - "actual" is a type that can be "expected" type: add a runtime check; or
1026 * - return FAIL.
1027 */
1028 static int
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02001029need_type(
1030 type_T *actual,
1031 type_T *expected,
1032 int offset,
1033 cctx_T *cctx,
1034 int silent)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001035{
1036 if (check_type(expected, actual, FALSE) == OK)
1037 return OK;
1038 if (actual->tt_type != VAR_ANY
1039 && actual->tt_type != VAR_UNKNOWN
1040 && !(actual->tt_type == VAR_FUNC
1041 && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
1042 {
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02001043 if (!silent)
1044 type_mismatch(expected, actual);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001045 return FAIL;
1046 }
1047 generate_TYPECHECK(cctx, expected, offset);
1048 return OK;
1049}
1050
1051/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001052 * Generate an ISN_PUSHNR instruction.
1053 */
1054 static int
1055generate_PUSHNR(cctx_T *cctx, varnumber_T number)
1056{
1057 isn_T *isn;
1058
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
1064 return OK;
1065}
1066
1067/*
1068 * Generate an ISN_PUSHBOOL instruction.
1069 */
1070 static int
1071generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
1072{
1073 isn_T *isn;
1074
Bram Moolenaar080457c2020-03-03 21:53:32 +01001075 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001076 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
1077 return FAIL;
1078 isn->isn_arg.number = number;
1079
1080 return OK;
1081}
1082
1083/*
1084 * Generate an ISN_PUSHSPEC instruction.
1085 */
1086 static int
1087generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
1088{
1089 isn_T *isn;
1090
Bram Moolenaar080457c2020-03-03 21:53:32 +01001091 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001092 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
1093 return FAIL;
1094 isn->isn_arg.number = number;
1095
1096 return OK;
1097}
1098
1099#ifdef FEAT_FLOAT
1100/*
1101 * Generate an ISN_PUSHF instruction.
1102 */
1103 static int
1104generate_PUSHF(cctx_T *cctx, float_T fnumber)
1105{
1106 isn_T *isn;
1107
Bram Moolenaar080457c2020-03-03 21:53:32 +01001108 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001109 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
1110 return FAIL;
1111 isn->isn_arg.fnumber = fnumber;
1112
1113 return OK;
1114}
1115#endif
1116
1117/*
1118 * Generate an ISN_PUSHS instruction.
1119 * Consumes "str".
1120 */
1121 static int
1122generate_PUSHS(cctx_T *cctx, char_u *str)
1123{
1124 isn_T *isn;
1125
Bram Moolenaar080457c2020-03-03 21:53:32 +01001126 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001127 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
1128 return FAIL;
1129 isn->isn_arg.string = str;
1130
1131 return OK;
1132}
1133
1134/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001135 * Generate an ISN_PUSHCHANNEL instruction.
1136 * Consumes "channel".
1137 */
1138 static int
1139generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
1140{
1141 isn_T *isn;
1142
Bram Moolenaar080457c2020-03-03 21:53:32 +01001143 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001144 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
1145 return FAIL;
1146 isn->isn_arg.channel = channel;
1147
1148 return OK;
1149}
1150
1151/*
1152 * Generate an ISN_PUSHJOB instruction.
1153 * Consumes "job".
1154 */
1155 static int
1156generate_PUSHJOB(cctx_T *cctx, job_T *job)
1157{
1158 isn_T *isn;
1159
Bram Moolenaar080457c2020-03-03 21:53:32 +01001160 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001161 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001162 return FAIL;
1163 isn->isn_arg.job = job;
1164
1165 return OK;
1166}
1167
1168/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001169 * Generate an ISN_PUSHBLOB instruction.
1170 * Consumes "blob".
1171 */
1172 static int
1173generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
1174{
1175 isn_T *isn;
1176
Bram Moolenaar080457c2020-03-03 21:53:32 +01001177 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001178 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
1179 return FAIL;
1180 isn->isn_arg.blob = blob;
1181
1182 return OK;
1183}
1184
1185/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001186 * Generate an ISN_PUSHFUNC instruction with name "name".
1187 * Consumes "name".
1188 */
1189 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001190generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001191{
1192 isn_T *isn;
1193
Bram Moolenaar080457c2020-03-03 21:53:32 +01001194 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001195 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001196 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02001197 isn->isn_arg.string = name == NULL ? NULL : vim_strsave(name);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001198
1199 return OK;
1200}
1201
1202/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001203 * Generate an ISN_GETITEM instruction with "index".
1204 */
1205 static int
1206generate_GETITEM(cctx_T *cctx, int index)
1207{
1208 isn_T *isn;
1209 garray_T *stack = &cctx->ctx_type_stack;
1210 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
1211 type_T *item_type = &t_any;
1212
1213 RETURN_OK_IF_SKIP(cctx);
1214
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001215 if (type->tt_type != VAR_LIST)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001216 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001217 // cannot happen, caller has checked the type
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001218 emsg(_(e_listreq));
1219 return FAIL;
1220 }
Bram Moolenaarc7db5772020-07-21 20:55:50 +02001221 item_type = type->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02001222 if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
1223 return FAIL;
1224 isn->isn_arg.number = index;
1225
1226 // add the item type to the type stack
1227 if (ga_grow(stack, 1) == FAIL)
1228 return FAIL;
1229 ((type_T **)stack->ga_data)[stack->ga_len] = item_type;
1230 ++stack->ga_len;
1231 return OK;
1232}
1233
1234/*
Bram Moolenaar9af78762020-06-16 11:34:42 +02001235 * Generate an ISN_SLICE instruction with "count".
1236 */
1237 static int
1238generate_SLICE(cctx_T *cctx, int count)
1239{
1240 isn_T *isn;
1241
1242 RETURN_OK_IF_SKIP(cctx);
1243 if ((isn = generate_instr(cctx, ISN_SLICE)) == NULL)
1244 return FAIL;
1245 isn->isn_arg.number = count;
1246 return OK;
1247}
1248
1249/*
1250 * Generate an ISN_CHECKLEN instruction with "min_len".
1251 */
1252 static int
1253generate_CHECKLEN(cctx_T *cctx, int min_len, int more_OK)
1254{
1255 isn_T *isn;
1256
1257 RETURN_OK_IF_SKIP(cctx);
1258
1259 if ((isn = generate_instr(cctx, ISN_CHECKLEN)) == NULL)
1260 return FAIL;
1261 isn->isn_arg.checklen.cl_min_len = min_len;
1262 isn->isn_arg.checklen.cl_more_OK = more_OK;
1263
1264 return OK;
1265}
1266
1267/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001268 * Generate an ISN_STORE instruction.
1269 */
1270 static int
1271generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
1272{
1273 isn_T *isn;
1274
Bram Moolenaar080457c2020-03-03 21:53:32 +01001275 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001276 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
1277 return FAIL;
1278 if (name != NULL)
1279 isn->isn_arg.string = vim_strsave(name);
1280 else
1281 isn->isn_arg.number = idx;
1282
1283 return OK;
1284}
1285
1286/*
1287 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
1288 */
1289 static int
1290generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
1291{
1292 isn_T *isn;
1293
Bram Moolenaar080457c2020-03-03 21:53:32 +01001294 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001295 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
1296 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +01001297 isn->isn_arg.storenr.stnr_idx = idx;
1298 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001299
1300 return OK;
1301}
1302
1303/*
1304 * Generate an ISN_STOREOPT instruction
1305 */
1306 static int
1307generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
1308{
1309 isn_T *isn;
1310
Bram Moolenaar080457c2020-03-03 21:53:32 +01001311 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001312 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
1313 return FAIL;
1314 isn->isn_arg.storeopt.so_name = vim_strsave(name);
1315 isn->isn_arg.storeopt.so_flags = opt_flags;
1316
1317 return OK;
1318}
1319
1320/*
1321 * Generate an ISN_LOAD or similar instruction.
1322 */
1323 static int
1324generate_LOAD(
1325 cctx_T *cctx,
1326 isntype_T isn_type,
1327 int idx,
1328 char_u *name,
1329 type_T *type)
1330{
1331 isn_T *isn;
1332
Bram Moolenaar080457c2020-03-03 21:53:32 +01001333 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001334 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
1335 return FAIL;
1336 if (name != NULL)
1337 isn->isn_arg.string = vim_strsave(name);
1338 else
1339 isn->isn_arg.number = idx;
1340
1341 return OK;
1342}
1343
1344/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001345 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001346 */
1347 static int
1348generate_LOADV(
1349 cctx_T *cctx,
1350 char_u *name,
1351 int error)
1352{
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001353 int di_flags;
1354 int vidx = find_vim_var(name, &di_flags);
1355 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001356
Bram Moolenaar080457c2020-03-03 21:53:32 +01001357 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001358 if (vidx < 0)
1359 {
1360 if (error)
1361 semsg(_(e_var_notfound), name);
1362 return FAIL;
1363 }
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02001364 type = typval2type_vimvar(get_vim_var_tv(vidx), cctx->ctx_type_list);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001365
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001366 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001367}
1368
1369/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001370 * Generate an ISN_UNLET instruction.
1371 */
1372 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001373generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001374{
1375 isn_T *isn;
1376
1377 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001378 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001379 return FAIL;
1380 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1381 isn->isn_arg.unlet.ul_forceit = forceit;
1382
1383 return OK;
1384}
1385
1386/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001387 * Generate an ISN_LOADS instruction.
1388 */
1389 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001390generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001391 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001392 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001393 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001394 int sid,
1395 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001396{
1397 isn_T *isn;
1398
Bram Moolenaar080457c2020-03-03 21:53:32 +01001399 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001400 if (isn_type == ISN_LOADS)
1401 isn = generate_instr_type(cctx, isn_type, type);
1402 else
1403 isn = generate_instr_drop(cctx, isn_type, 1);
1404 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001405 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001406 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1407 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001408
1409 return OK;
1410}
1411
1412/*
1413 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1414 */
1415 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001416generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001417 cctx_T *cctx,
1418 isntype_T isn_type,
1419 int sid,
1420 int idx,
1421 type_T *type)
1422{
1423 isn_T *isn;
1424
Bram Moolenaar080457c2020-03-03 21:53:32 +01001425 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001426 if (isn_type == ISN_LOADSCRIPT)
1427 isn = generate_instr_type(cctx, isn_type, type);
1428 else
1429 isn = generate_instr_drop(cctx, isn_type, 1);
1430 if (isn == NULL)
1431 return FAIL;
1432 isn->isn_arg.script.script_sid = sid;
1433 isn->isn_arg.script.script_idx = idx;
1434 return OK;
1435}
1436
1437/*
1438 * Generate an ISN_NEWLIST instruction.
1439 */
1440 static int
1441generate_NEWLIST(cctx_T *cctx, int count)
1442{
1443 isn_T *isn;
1444 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001445 type_T *type;
1446 type_T *member;
1447
Bram Moolenaar080457c2020-03-03 21:53:32 +01001448 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001449 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1450 return FAIL;
1451 isn->isn_arg.number = count;
1452
1453 // drop the value types
1454 stack->ga_len -= count;
1455
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001456 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001457 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001458 if (count > 0)
1459 member = ((type_T **)stack->ga_data)[stack->ga_len];
1460 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001461 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001462 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001463
1464 // add the list type to the type stack
1465 if (ga_grow(stack, 1) == FAIL)
1466 return FAIL;
1467 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1468 ++stack->ga_len;
1469
1470 return OK;
1471}
1472
1473/*
1474 * Generate an ISN_NEWDICT instruction.
1475 */
1476 static int
1477generate_NEWDICT(cctx_T *cctx, int count)
1478{
1479 isn_T *isn;
1480 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001481 type_T *type;
1482 type_T *member;
1483
Bram Moolenaar080457c2020-03-03 21:53:32 +01001484 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001485 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1486 return FAIL;
1487 isn->isn_arg.number = count;
1488
1489 // drop the key and value types
1490 stack->ga_len -= 2 * count;
1491
Bram Moolenaar436472f2020-02-20 22:54:43 +01001492 // Use the first value type for the list member type. Use "void" for an
1493 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001494 if (count > 0)
1495 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1496 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001497 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001498 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001499
1500 // add the dict type to the type stack
1501 if (ga_grow(stack, 1) == FAIL)
1502 return FAIL;
1503 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1504 ++stack->ga_len;
1505
1506 return OK;
1507}
1508
1509/*
1510 * Generate an ISN_FUNCREF instruction.
1511 */
1512 static int
1513generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1514{
1515 isn_T *isn;
1516 garray_T *stack = &cctx->ctx_type_stack;
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_FUNCREF)) == NULL)
1520 return FAIL;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001521 isn->isn_arg.funcref.fr_func = dfunc_idx;
1522 isn->isn_arg.funcref.fr_var_idx = cctx->ctx_closure_count++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001523
1524 if (ga_grow(stack, 1) == FAIL)
1525 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001526 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001527 // TODO: argument and return types
1528 ++stack->ga_len;
1529
1530 return OK;
1531}
1532
1533/*
Bram Moolenaar38ddf332020-07-31 22:05:04 +02001534 * Generate an ISN_NEWFUNC instruction.
1535 */
1536 static int
1537generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
1538{
1539 isn_T *isn;
1540 char_u *name;
1541
1542 RETURN_OK_IF_SKIP(cctx);
1543 name = vim_strsave(lambda_name);
1544 if (name == NULL)
1545 return FAIL;
1546 if ((isn = generate_instr(cctx, ISN_NEWFUNC)) == NULL)
1547 return FAIL;
1548 isn->isn_arg.newfunc.nf_lambda = name;
1549 isn->isn_arg.newfunc.nf_global = func_name;
1550
1551 return OK;
1552}
1553
1554/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001555 * Generate an ISN_JUMP instruction.
1556 */
1557 static int
1558generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1559{
1560 isn_T *isn;
1561 garray_T *stack = &cctx->ctx_type_stack;
1562
Bram Moolenaar080457c2020-03-03 21:53:32 +01001563 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001564 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1565 return FAIL;
1566 isn->isn_arg.jump.jump_when = when;
1567 isn->isn_arg.jump.jump_where = where;
1568
1569 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1570 --stack->ga_len;
1571
1572 return OK;
1573}
1574
1575 static int
1576generate_FOR(cctx_T *cctx, int loop_idx)
1577{
1578 isn_T *isn;
1579 garray_T *stack = &cctx->ctx_type_stack;
1580
Bram Moolenaar080457c2020-03-03 21:53:32 +01001581 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001582 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1583 return FAIL;
1584 isn->isn_arg.forloop.for_idx = loop_idx;
1585
1586 if (ga_grow(stack, 1) == FAIL)
1587 return FAIL;
1588 // type doesn't matter, will be stored next
1589 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1590 ++stack->ga_len;
1591
1592 return OK;
1593}
1594
1595/*
1596 * Generate an ISN_BCALL instruction.
Bram Moolenaar389df252020-07-09 21:20:47 +02001597 * "method_call" is TRUE for "value->method()"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001598 * Return FAIL if the number of arguments is wrong.
1599 */
1600 static int
Bram Moolenaar389df252020-07-09 21:20:47 +02001601generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001602{
1603 isn_T *isn;
1604 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar389df252020-07-09 21:20:47 +02001605 int argoff;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001606 type_T *argtypes[MAX_FUNC_ARGS];
1607 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001608
Bram Moolenaar080457c2020-03-03 21:53:32 +01001609 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar389df252020-07-09 21:20:47 +02001610 argoff = check_internal_func(func_idx, argcount);
1611 if (argoff < 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001612 return FAIL;
1613
Bram Moolenaar389df252020-07-09 21:20:47 +02001614 if (method_call && argoff > 1)
1615 {
1616 if ((isn = generate_instr(cctx, ISN_SHUFFLE)) == NULL)
1617 return FAIL;
1618 isn->isn_arg.shuffle.shfl_item = argcount;
1619 isn->isn_arg.shuffle.shfl_up = argoff - 1;
1620 }
1621
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001622 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1623 return FAIL;
1624 isn->isn_arg.bfunc.cbf_idx = func_idx;
1625 isn->isn_arg.bfunc.cbf_argcount = argcount;
1626
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001627 for (i = 0; i < argcount; ++i)
1628 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1629
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001630 stack->ga_len -= argcount; // drop the arguments
1631 if (ga_grow(stack, 1) == FAIL)
1632 return FAIL;
1633 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001634 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001635 ++stack->ga_len; // add return value
1636
1637 return OK;
1638}
1639
1640/*
1641 * Generate an ISN_DCALL or ISN_UCALL instruction.
1642 * Return FAIL if the number of arguments is wrong.
1643 */
1644 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001645generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001646{
1647 isn_T *isn;
1648 garray_T *stack = &cctx->ctx_type_stack;
1649 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001650 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001651
Bram Moolenaar080457c2020-03-03 21:53:32 +01001652 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001653 if (argcount > regular_args && !has_varargs(ufunc))
1654 {
1655 semsg(_(e_toomanyarg), ufunc->uf_name);
1656 return FAIL;
1657 }
1658 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1659 {
1660 semsg(_(e_toofewarg), ufunc->uf_name);
1661 return FAIL;
1662 }
1663
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001664 if (ufunc->uf_def_status != UF_NOT_COMPILED)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001665 {
1666 int i;
1667
1668 for (i = 0; i < argcount; ++i)
1669 {
1670 type_T *expected;
1671 type_T *actual;
1672
1673 if (i < regular_args)
1674 {
1675 if (ufunc->uf_arg_types == NULL)
1676 continue;
1677 expected = ufunc->uf_arg_types[i];
1678 }
1679 else
1680 expected = ufunc->uf_va_type->tt_member;
1681 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02001682 if (need_type(actual, expected, -argcount + i, cctx, TRUE) == FAIL)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001683 {
1684 arg_type_mismatch(expected, actual, i + 1);
1685 return FAIL;
1686 }
1687 }
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001688 if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
Bram Moolenaar45a15082020-05-25 00:28:33 +02001689 if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
Bram Moolenaar822ba242020-05-24 23:00:18 +02001690 return FAIL;
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001691 }
1692
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001693 if ((isn = generate_instr(cctx,
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001694 ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
Bram Moolenaar822ba242020-05-24 23:00:18 +02001695 : ISN_UCALL)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001696 return FAIL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02001697 if (ufunc->uf_def_status != UF_NOT_COMPILED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001698 {
1699 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1700 isn->isn_arg.dfunc.cdf_argcount = argcount;
1701 }
1702 else
1703 {
1704 // A user function may be deleted and redefined later, can't use the
1705 // ufunc pointer, need to look it up again at runtime.
1706 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1707 isn->isn_arg.ufunc.cuf_argcount = argcount;
1708 }
1709
1710 stack->ga_len -= argcount; // drop the arguments
1711 if (ga_grow(stack, 1) == FAIL)
1712 return FAIL;
1713 // add return value
1714 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1715 ++stack->ga_len;
1716
1717 return OK;
1718}
1719
1720/*
1721 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1722 */
1723 static int
1724generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1725{
1726 isn_T *isn;
1727 garray_T *stack = &cctx->ctx_type_stack;
1728
Bram Moolenaar080457c2020-03-03 21:53:32 +01001729 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001730 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1731 return FAIL;
1732 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1733 isn->isn_arg.ufunc.cuf_argcount = argcount;
1734
1735 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001736 if (ga_grow(stack, 1) == FAIL)
1737 return FAIL;
1738 // add return value
1739 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1740 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001741
1742 return OK;
1743}
1744
1745/*
1746 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001747 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001748 */
1749 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001750generate_PCALL(
1751 cctx_T *cctx,
1752 int argcount,
1753 char_u *name,
1754 type_T *type,
1755 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001756{
1757 isn_T *isn;
1758 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001759 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001760
Bram Moolenaar080457c2020-03-03 21:53:32 +01001761 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001762
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001763 if (type->tt_type == VAR_ANY)
1764 ret_type = &t_any;
1765 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001766 {
1767 if (type->tt_argcount != -1)
1768 {
1769 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
1770
1771 if (argcount < type->tt_min_argcount - varargs)
1772 {
1773 semsg(_(e_toofewarg), "[reference]");
1774 return FAIL;
1775 }
1776 if (!varargs && argcount > type->tt_argcount)
1777 {
1778 semsg(_(e_toomanyarg), "[reference]");
1779 return FAIL;
1780 }
1781 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001782 ret_type = type->tt_member;
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001783 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001784 else
1785 {
1786 semsg(_("E1085: Not a callable type: %s"), name);
1787 return FAIL;
1788 }
1789
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001790 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1791 return FAIL;
1792 isn->isn_arg.pfunc.cpf_top = at_top;
1793 isn->isn_arg.pfunc.cpf_argcount = argcount;
1794
1795 stack->ga_len -= argcount; // drop the arguments
1796
1797 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001798 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001799
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001800 // If partial is above the arguments it must be cleared and replaced with
1801 // the return value.
1802 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1803 return FAIL;
1804
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001805 return OK;
1806}
1807
1808/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001809 * Generate an ISN_STRINGMEMBER instruction.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001810 */
1811 static int
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001812generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001813{
1814 isn_T *isn;
1815 garray_T *stack = &cctx->ctx_type_stack;
1816 type_T *type;
1817
Bram Moolenaar080457c2020-03-03 21:53:32 +01001818 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001819 if ((isn = generate_instr(cctx, ISN_STRINGMEMBER)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001820 return FAIL;
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001821 isn->isn_arg.string = vim_strnsave(name, len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001822
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001823 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001824 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001825 if (type->tt_type != VAR_DICT && type != &t_any)
1826 {
1827 emsg(_(e_dictreq));
1828 return FAIL;
1829 }
1830 // change dict type to dict member type
1831 if (type->tt_type == VAR_DICT)
1832 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001833
1834 return OK;
1835}
1836
1837/*
1838 * Generate an ISN_ECHO instruction.
1839 */
1840 static int
1841generate_ECHO(cctx_T *cctx, int with_white, int count)
1842{
1843 isn_T *isn;
1844
Bram Moolenaar080457c2020-03-03 21:53:32 +01001845 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001846 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1847 return FAIL;
1848 isn->isn_arg.echo.echo_with_white = with_white;
1849 isn->isn_arg.echo.echo_count = count;
1850
1851 return OK;
1852}
1853
Bram Moolenaarad39c092020-02-26 18:23:43 +01001854/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001855 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001856 */
1857 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001858generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001859{
1860 isn_T *isn;
1861
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001862 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001863 return FAIL;
1864 isn->isn_arg.number = count;
1865
1866 return OK;
1867}
1868
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001869 static int
1870generate_EXEC(cctx_T *cctx, char_u *line)
1871{
1872 isn_T *isn;
1873
Bram Moolenaar080457c2020-03-03 21:53:32 +01001874 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001875 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1876 return FAIL;
1877 isn->isn_arg.string = vim_strsave(line);
1878 return OK;
1879}
1880
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001881 static int
1882generate_EXECCONCAT(cctx_T *cctx, int count)
1883{
1884 isn_T *isn;
1885
1886 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1887 return FAIL;
1888 isn->isn_arg.number = count;
1889 return OK;
1890}
1891
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001892/*
1893 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001894 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001895 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001896 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001897reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1898{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001899 lvar_T *lvar;
1900
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001901 if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001902 {
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02001903 emsg_namelen(_(e_used_as_arg), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001904 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001905 }
1906
1907 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001908 return NULL;
1909 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001910
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001911 // Every local variable uses the next entry on the stack. We could re-use
1912 // the last ones when leaving a scope, but then variables used in a closure
1913 // might get overwritten. To keep things simple do not re-use stack
1914 // entries. This is less efficient, but memory is cheap these days.
1915 lvar->lv_idx = cctx->ctx_locals_count++;
1916
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001917 lvar->lv_name = vim_strnsave(name, len == 0 ? STRLEN(name) : len);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001918 lvar->lv_const = isConst;
1919 lvar->lv_type = type;
1920
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001921 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001922}
1923
1924/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001925 * Remove local variables above "new_top".
1926 */
1927 static void
1928unwind_locals(cctx_T *cctx, int new_top)
1929{
1930 if (cctx->ctx_locals.ga_len > new_top)
1931 {
1932 int idx;
1933 lvar_T *lvar;
1934
1935 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1936 {
1937 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1938 vim_free(lvar->lv_name);
1939 }
1940 }
1941 cctx->ctx_locals.ga_len = new_top;
1942}
1943
1944/*
1945 * Free all local variables.
1946 */
1947 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001948free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01001949{
1950 unwind_locals(cctx, 0);
1951 ga_clear(&cctx->ctx_locals);
1952}
1953
1954/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001955 * Skip over a type definition and return a pointer to just after it.
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001956 * When "optional" is TRUE then a leading "?" is accepted.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001957 */
1958 char_u *
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001959skip_type(char_u *start, int optional)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001960{
1961 char_u *p = start;
1962
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001963 if (optional && *p == '?')
1964 ++p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001965 while (ASCII_ISALNUM(*p) || *p == '_')
1966 ++p;
1967
1968 // Skip over "<type>"; this is permissive about white space.
1969 if (*skipwhite(p) == '<')
1970 {
1971 p = skipwhite(p);
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001972 p = skip_type(skipwhite(p + 1), FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001973 p = skipwhite(p);
1974 if (*p == '>')
1975 ++p;
1976 }
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001977 else if ((*p == '(' || (*p == ':' && VIM_ISWHITE(p[1])))
1978 && STRNCMP("func", start, 4) == 0)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001979 {
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001980 if (*p == '(')
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001981 {
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001982 // handle func(args): type
1983 ++p;
1984 while (*p != ')' && *p != NUL)
1985 {
1986 char_u *sp = p;
Bram Moolenaar1c0d44f2020-05-02 19:04:58 +02001987
Bram Moolenaarace61322020-07-26 18:16:58 +02001988 if (STRNCMP(p, "...", 3) == 0)
1989 p += 3;
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001990 p = skip_type(p, TRUE);
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02001991 if (p == sp)
1992 return p; // syntax error
1993 if (*p == ',')
1994 p = skipwhite(p + 1);
1995 }
1996 if (*p == ')')
1997 {
1998 if (p[1] == ':')
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02001999 p = skip_type(skipwhite(p + 2), FALSE);
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02002000 else
Bram Moolenaarbfba8652020-07-23 20:09:10 +02002001 ++p;
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02002002 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002003 }
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02002004 else
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02002005 {
Bram Moolenaar2f1980f2020-07-22 19:30:06 +02002006 // handle func: return_type
Bram Moolenaar4fc224c2020-07-26 17:56:25 +02002007 p = skip_type(skipwhite(p + 1), FALSE);
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02002008 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002009 }
2010
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002011 return p;
2012}
2013
2014/*
2015 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02002016 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002017 * Returns NULL in case of failure.
2018 */
2019 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02002020parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002021{
2022 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002023 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002024
2025 if (**arg != '<')
2026 {
2027 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02002028 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002029 else
2030 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01002031 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002032 }
2033 *arg = skipwhite(*arg + 1);
2034
Bram Moolenaard77a8522020-04-03 21:59:57 +02002035 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002036
2037 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002038 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002039 {
2040 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01002041 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002042 }
2043 ++*arg;
2044
2045 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02002046 return get_list_type(member_type, type_gap);
2047 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002048}
2049
2050/*
2051 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02002052 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002053 */
2054 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02002055parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002056{
2057 char_u *p = *arg;
2058 size_t len;
2059
2060 // skip over the first word
2061 while (ASCII_ISALNUM(*p) || *p == '_')
2062 ++p;
2063 len = p - *arg;
2064
2065 switch (**arg)
2066 {
2067 case 'a':
2068 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
2069 {
2070 *arg += len;
2071 return &t_any;
2072 }
2073 break;
2074 case 'b':
2075 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
2076 {
2077 *arg += len;
2078 return &t_bool;
2079 }
2080 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
2081 {
2082 *arg += len;
2083 return &t_blob;
2084 }
2085 break;
2086 case 'c':
2087 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
2088 {
2089 *arg += len;
2090 return &t_channel;
2091 }
2092 break;
2093 case 'd':
2094 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
2095 {
2096 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002097 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002098 }
2099 break;
2100 case 'f':
2101 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
2102 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01002103#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002104 *arg += len;
2105 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01002106#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002107 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01002108 return &t_any;
2109#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002110 }
2111 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
2112 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002113 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002114 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002115 int argcount = -1;
2116 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002117 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002118 type_T *arg_type[MAX_FUNC_ARGS + 1];
2119
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002120 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002121 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002122 if (**arg == '(')
2123 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002124 // "func" may or may not return a value, "func()" does
2125 // not return a value.
2126 ret_type = &t_void;
2127
Bram Moolenaard77a8522020-04-03 21:59:57 +02002128 p = ++*arg;
2129 argcount = 0;
2130 while (*p != NUL && *p != ')')
2131 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002132 if (*p == '?')
2133 {
2134 if (first_optional == -1)
2135 first_optional = argcount;
2136 ++p;
2137 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002138 else if (STRNCMP(p, "...", 3) == 0)
2139 {
2140 flags |= TTFLAG_VARARGS;
2141 p += 3;
2142 }
Bram Moolenaar01865ad2020-07-26 18:33:09 +02002143 else if (first_optional != -1)
2144 {
2145 emsg(_("E1007: mandatory argument after optional argument"));
2146 return &t_any;
2147 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002148
2149 arg_type[argcount++] = parse_type(&p, type_gap);
2150
2151 // Nothing comes after "...{type}".
2152 if (flags & TTFLAG_VARARGS)
2153 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002154
Bram Moolenaard77a8522020-04-03 21:59:57 +02002155 if (*p != ',' && *skipwhite(p) == ',')
2156 {
2157 semsg(_(e_no_white_before), ",");
2158 return &t_any;
2159 }
2160 if (*p == ',')
2161 {
2162 ++p;
2163 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002164 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002165 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002166 return &t_any;
2167 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02002168 }
2169 p = skipwhite(p);
2170 if (argcount == MAX_FUNC_ARGS)
2171 {
2172 emsg(_("E740: Too many argument types"));
2173 return &t_any;
2174 }
2175 }
2176
2177 p = skipwhite(p);
2178 if (*p != ')')
2179 {
2180 emsg(_(e_missing_close));
2181 return &t_any;
2182 }
2183 *arg = p + 1;
2184 }
2185 if (**arg == ':')
2186 {
2187 // parse return type
2188 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002189 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002190 semsg(_(e_white_after), ":");
2191 *arg = skipwhite(*arg);
2192 ret_type = parse_type(arg, type_gap);
2193 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002194 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002195 type = get_func_type(ret_type, argcount, type_gap);
2196 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02002197 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002198 type = alloc_func_type(ret_type, argcount, type_gap);
2199 type->tt_flags = flags;
2200 if (argcount > 0)
2201 {
2202 type->tt_argcount = argcount;
2203 type->tt_min_argcount = first_optional == -1
2204 ? argcount : first_optional;
2205 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002206 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002207 return &t_any;
2208 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02002209 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002210 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02002211 }
2212 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002213 }
2214 break;
2215 case 'j':
2216 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
2217 {
2218 *arg += len;
2219 return &t_job;
2220 }
2221 break;
2222 case 'l':
2223 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
2224 {
2225 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02002226 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002227 }
2228 break;
2229 case 'n':
2230 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
2231 {
2232 *arg += len;
2233 return &t_number;
2234 }
2235 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002236 case 's':
2237 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
2238 {
2239 *arg += len;
2240 return &t_string;
2241 }
2242 break;
2243 case 'v':
2244 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
2245 {
2246 *arg += len;
2247 return &t_void;
2248 }
2249 break;
2250 }
2251
2252 semsg(_("E1010: Type not recognized: %s"), *arg);
2253 return &t_any;
2254}
2255
2256/*
2257 * Check if "type1" and "type2" are exactly the same.
2258 */
2259 static int
2260equal_type(type_T *type1, type_T *type2)
2261{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002262 int i;
2263
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002264 if (type1->tt_type != type2->tt_type)
2265 return FALSE;
2266 switch (type1->tt_type)
2267 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002268 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02002269 case VAR_ANY:
2270 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002271 case VAR_SPECIAL:
2272 case VAR_BOOL:
2273 case VAR_NUMBER:
2274 case VAR_FLOAT:
2275 case VAR_STRING:
2276 case VAR_BLOB:
2277 case VAR_JOB:
2278 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002279 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002280 case VAR_LIST:
2281 case VAR_DICT:
2282 return equal_type(type1->tt_member, type2->tt_member);
2283 case VAR_FUNC:
2284 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002285 if (!equal_type(type1->tt_member, type2->tt_member)
2286 || type1->tt_argcount != type2->tt_argcount)
2287 return FALSE;
2288 if (type1->tt_argcount < 0
2289 || type1->tt_args == NULL || type2->tt_args == NULL)
2290 return TRUE;
2291 for (i = 0; i < type1->tt_argcount; ++i)
2292 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
2293 return FALSE;
2294 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002295 }
2296 return TRUE;
2297}
2298
2299/*
2300 * Find the common type of "type1" and "type2" and put it in "dest".
2301 * "type2" and "dest" may be the same.
2302 */
2303 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02002304common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002305{
2306 if (equal_type(type1, type2))
2307 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002308 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002309 return;
2310 }
2311
2312 if (type1->tt_type == type2->tt_type)
2313 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002314 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
2315 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002316 type_T *common;
2317
Bram Moolenaard77a8522020-04-03 21:59:57 +02002318 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002319 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02002320 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002321 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02002322 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002323 return;
2324 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002325 if (type1->tt_type == VAR_FUNC)
2326 {
2327 type_T *common;
2328
2329 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
2330 if (type1->tt_argcount == type2->tt_argcount
2331 && type1->tt_argcount >= 0)
2332 {
2333 int argcount = type1->tt_argcount;
2334 int i;
2335
2336 *dest = alloc_func_type(common, argcount, type_gap);
2337 if (type1->tt_args != NULL && type2->tt_args != NULL)
2338 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02002339 if (func_type_add_arg_types(*dest, argcount,
2340 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002341 for (i = 0; i < argcount; ++i)
2342 common_type(type1->tt_args[i], type2->tt_args[i],
2343 &(*dest)->tt_args[i], type_gap);
2344 }
2345 }
2346 else
2347 *dest = alloc_func_type(common, -1, type_gap);
2348 return;
2349 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002350 }
2351
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002352 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002353}
2354
2355 char *
2356vartype_name(vartype_T type)
2357{
2358 switch (type)
2359 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002360 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002361 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002362 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002363 case VAR_SPECIAL: return "special";
2364 case VAR_BOOL: return "bool";
2365 case VAR_NUMBER: return "number";
2366 case VAR_FLOAT: return "float";
2367 case VAR_STRING: return "string";
2368 case VAR_BLOB: return "blob";
2369 case VAR_JOB: return "job";
2370 case VAR_CHANNEL: return "channel";
2371 case VAR_LIST: return "list";
2372 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002373
2374 case VAR_FUNC:
2375 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002376 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02002377 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002378}
2379
2380/*
2381 * Return the name of a type.
2382 * The result may be in allocated memory, in which case "tofree" is set.
2383 */
2384 char *
2385type_name(type_T *type, char **tofree)
2386{
2387 char *name = vartype_name(type->tt_type);
2388
2389 *tofree = NULL;
2390 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
2391 {
2392 char *member_free;
2393 char *member_name = type_name(type->tt_member, &member_free);
2394 size_t len;
2395
2396 len = STRLEN(name) + STRLEN(member_name) + 3;
2397 *tofree = alloc(len);
2398 if (*tofree != NULL)
2399 {
2400 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
2401 vim_free(member_free);
2402 return *tofree;
2403 }
2404 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002405 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002406 {
2407 garray_T ga;
2408 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002409 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002410
2411 ga_init2(&ga, 1, 100);
2412 if (ga_grow(&ga, 20) == FAIL)
2413 return "[unknown]";
2414 *tofree = ga.ga_data;
2415 STRCPY(ga.ga_data, "func(");
2416 ga.ga_len += 5;
2417
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002418 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002419 {
2420 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002421 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002422 int len;
2423
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002424 if (type->tt_args == NULL)
2425 arg_type = "[unknown]";
2426 else
2427 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002428 if (i > 0)
2429 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002430 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002431 ga.ga_len += 2;
2432 }
2433 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002434 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002435 {
2436 vim_free(arg_free);
2437 return "[unknown]";
2438 }
2439 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002440 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002441 {
2442 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
2443 ga.ga_len += 3;
2444 }
2445 else if (i >= type->tt_min_argcount)
2446 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002447 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002448 ga.ga_len += len;
2449 vim_free(arg_free);
2450 }
2451
2452 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002453 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002454 else
2455 {
2456 char *ret_free;
2457 char *ret_name = type_name(type->tt_member, &ret_free);
2458 int len;
2459
2460 len = (int)STRLEN(ret_name) + 4;
2461 if (ga_grow(&ga, len) == FAIL)
2462 {
2463 vim_free(ret_free);
2464 return "[unknown]";
2465 }
2466 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002467 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
2468 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002469 vim_free(ret_free);
2470 }
2471 return ga.ga_data;
2472 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002473
2474 return name;
2475}
2476
2477/*
2478 * Find "name" in script-local items of script "sid".
2479 * Returns the index in "sn_var_vals" if found.
2480 * If found but not in "sn_var_vals" returns -1.
2481 * If not found returns -2.
2482 */
2483 int
2484get_script_item_idx(int sid, char_u *name, int check_writable)
2485{
2486 hashtab_T *ht;
2487 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002488 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002489 int idx;
2490
2491 // First look the name up in the hashtable.
2492 if (sid <= 0 || sid > script_items.ga_len)
2493 return -1;
2494 ht = &SCRIPT_VARS(sid);
2495 di = find_var_in_ht(ht, 0, name, TRUE);
2496 if (di == NULL)
2497 return -2;
2498
2499 // Now find the svar_T index in sn_var_vals.
2500 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2501 {
2502 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2503
2504 if (sv->sv_tv == &di->di_tv)
2505 {
2506 if (check_writable && sv->sv_const)
2507 semsg(_(e_readonlyvar), name);
2508 return idx;
2509 }
2510 }
2511 return -1;
2512}
2513
2514/*
Bram Moolenaarc82a5b52020-06-13 18:09:19 +02002515 * Find "name" in imported items of the current script or in "cctx" if not
2516 * NULL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002517 */
2518 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002519find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002520{
Bram Moolenaar086eb182020-07-01 16:00:44 +02002521 scriptitem_T *si;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002522 int idx;
2523
Bram Moolenaar8e6cbb72020-07-01 14:38:12 +02002524 if (current_sctx.sc_sid <= 0)
2525 return NULL;
2526 si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002527 if (cctx != NULL)
2528 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2529 {
2530 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2531 + idx;
2532
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002533 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2534 : STRLEN(import->imp_name) == len
2535 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002536 return import;
2537 }
2538
2539 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2540 {
2541 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2542
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002543 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2544 : STRLEN(import->imp_name) == len
2545 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002546 return import;
2547 }
2548 return NULL;
2549}
2550
2551/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002552 * Free all imported variables.
2553 */
2554 static void
2555free_imported(cctx_T *cctx)
2556{
2557 int idx;
2558
2559 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2560 {
2561 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2562
2563 vim_free(import->imp_name);
2564 }
2565 ga_clear(&cctx->ctx_imports);
2566}
2567
2568/*
Bram Moolenaar23c55272020-06-21 16:58:13 +02002569 * Return TRUE if "p" points at a "#" but not at "#{".
2570 */
Bram Moolenaar75783bd2020-07-19 14:41:58 +02002571 int
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002572vim9_comment_start(char_u *p)
Bram Moolenaar23c55272020-06-21 16:58:13 +02002573{
2574 return p[0] == '#' && p[1] != '{';
2575}
2576
2577/*
2578 * Return a pointer to the next line that isn't empty or only contains a
2579 * comment. Skips over white space.
2580 * Returns NULL if there is none.
2581 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002582 char_u *
2583peek_next_line_from_context(cctx_T *cctx)
Bram Moolenaar23c55272020-06-21 16:58:13 +02002584{
2585 int lnum = cctx->ctx_lnum;
2586
2587 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
2588 {
2589 char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum];
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002590 char_u *p;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002591
Bram Moolenaaracd4c5e2020-06-22 19:39:03 +02002592 if (line == NULL)
2593 break;
2594 p = skipwhite(line);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002595 if (*p != NUL && !vim9_comment_start(p))
Bram Moolenaar23c55272020-06-21 16:58:13 +02002596 return p;
2597 }
2598 return NULL;
2599}
2600
2601/*
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002602 * Called when checking for a following operator at "arg". When the rest of
2603 * the line is empty or only a comment, peek the next line. If there is a next
2604 * line return a pointer to it and set "nextp".
2605 * Otherwise skip over white space.
2606 */
2607 static char_u *
2608may_peek_next_line(cctx_T *cctx, char_u *arg, char_u **nextp)
2609{
2610 char_u *p = skipwhite(arg);
2611
2612 *nextp = NULL;
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002613 if (*p == NUL || (VIM_ISWHITE(*arg) && vim9_comment_start(p)))
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002614 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002615 *nextp = peek_next_line_from_context(cctx);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02002616 if (*nextp != NULL)
2617 return *nextp;
2618 }
2619 return p;
2620}
2621
2622/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002623 * Get the next line of the function from "cctx".
Bram Moolenaar23c55272020-06-21 16:58:13 +02002624 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
Bram Moolenaare6085c52020-04-12 20:19:16 +02002625 * Returns NULL when at the end.
2626 */
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02002627 char_u *
Bram Moolenaar23c55272020-06-21 16:58:13 +02002628next_line_from_context(cctx_T *cctx, int skip_comment)
Bram Moolenaare6085c52020-04-12 20:19:16 +02002629{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002630 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002631
2632 do
2633 {
2634 ++cctx->ctx_lnum;
2635 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002636 {
2637 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002638 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002639 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002640 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002641 cctx->ctx_line_start = line;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02002642 SOURCING_LNUM = cctx->ctx_lnum + 1;
Bram Moolenaar23c55272020-06-21 16:58:13 +02002643 } while (line == NULL || *skipwhite(line) == NUL
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002644 || (skip_comment && vim9_comment_start(skipwhite(line))));
Bram Moolenaare6085c52020-04-12 20:19:16 +02002645 return line;
2646}
2647
2648/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002649 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002650 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002651 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2652 */
2653 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002654may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002655{
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02002656 if (**arg == NUL || (VIM_ISWHITE(*whitep) && vim9_comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002657 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02002658 char_u *next = next_line_from_context(cctx, TRUE);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002659
2660 if (next == NULL)
2661 return FAIL;
2662 *arg = skipwhite(next);
2663 }
2664 return OK;
2665}
2666
Bram Moolenaara7eedf32020-07-10 21:50:41 +02002667/*
2668 * Idem, and give an error when failed.
2669 */
2670 static int
2671may_get_next_line_error(char_u *whitep, char_u **arg, cctx_T *cctx)
2672{
2673 if (may_get_next_line(whitep, arg, cctx) == FAIL)
2674 {
2675 emsg(_("E1097: line incomplete"));
2676 return FAIL;
2677 }
2678 return OK;
2679}
2680
2681
Bram Moolenaara5565e42020-05-09 15:44:01 +02002682// Structure passed between the compile_expr* functions to keep track of
2683// constants that have been parsed but for which no code was produced yet. If
2684// possible expressions on these constants are applied at compile time. If
2685// that is not possible, the code to push the constants needs to be generated
2686// before other instructions.
Bram Moolenaar1c747212020-05-09 18:28:34 +02002687// Using 50 should be more than enough of 5 levels of ().
2688#define PPSIZE 50
Bram Moolenaara5565e42020-05-09 15:44:01 +02002689typedef struct {
Bram Moolenaar1c747212020-05-09 18:28:34 +02002690 typval_T pp_tv[PPSIZE]; // stack of ppconst constants
Bram Moolenaara5565e42020-05-09 15:44:01 +02002691 int pp_used; // active entries in pp_tv[]
2692} ppconst_T;
2693
Bram Moolenaar1c747212020-05-09 18:28:34 +02002694static int compile_expr0(char_u **arg, cctx_T *cctx);
2695static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2696
Bram Moolenaara5565e42020-05-09 15:44:01 +02002697/*
2698 * Generate a PUSH instruction for "tv".
2699 * "tv" will be consumed or cleared.
2700 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
2701 */
2702 static int
2703generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
2704{
2705 if (tv != NULL)
2706 {
2707 switch (tv->v_type)
2708 {
2709 case VAR_UNKNOWN:
2710 break;
2711 case VAR_BOOL:
2712 generate_PUSHBOOL(cctx, tv->vval.v_number);
2713 break;
2714 case VAR_SPECIAL:
2715 generate_PUSHSPEC(cctx, tv->vval.v_number);
2716 break;
2717 case VAR_NUMBER:
2718 generate_PUSHNR(cctx, tv->vval.v_number);
2719 break;
2720#ifdef FEAT_FLOAT
2721 case VAR_FLOAT:
2722 generate_PUSHF(cctx, tv->vval.v_float);
2723 break;
2724#endif
2725 case VAR_BLOB:
2726 generate_PUSHBLOB(cctx, tv->vval.v_blob);
2727 tv->vval.v_blob = NULL;
2728 break;
2729 case VAR_STRING:
2730 generate_PUSHS(cctx, tv->vval.v_string);
2731 tv->vval.v_string = NULL;
2732 break;
2733 default:
2734 iemsg("constant type not supported");
2735 clear_tv(tv);
2736 return FAIL;
2737 }
2738 tv->v_type = VAR_UNKNOWN;
2739 }
2740 return OK;
2741}
2742
2743/*
2744 * Generate code for any ppconst entries.
2745 */
2746 static int
2747generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
2748{
2749 int i;
2750 int ret = OK;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002751 int save_skip = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002752
Bram Moolenaar9b68c822020-06-18 19:31:08 +02002753 cctx->ctx_skip = SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002754 for (i = 0; i < ppconst->pp_used; ++i)
2755 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
2756 ret = FAIL;
2757 ppconst->pp_used = 0;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002758 cctx->ctx_skip = save_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002759 return ret;
2760}
2761
2762/*
2763 * Clear ppconst constants. Used when failing.
2764 */
2765 static void
2766clear_ppconst(ppconst_T *ppconst)
2767{
2768 int i;
2769
2770 for (i = 0; i < ppconst->pp_used; ++i)
2771 clear_tv(&ppconst->pp_tv[i]);
2772 ppconst->pp_used = 0;
2773}
2774
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002775/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002776 * Generate an instruction to load script-local variable "name", without the
2777 * leading "s:".
2778 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002779 */
2780 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002781compile_load_scriptvar(
2782 cctx_T *cctx,
2783 char_u *name, // variable NUL terminated
2784 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002785 char_u **end, // end of variable
2786 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002787{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002788 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002789 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2790 imported_T *import;
2791
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002792 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002793 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002794 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002795 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2796 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002797 }
2798 if (idx >= 0)
2799 {
2800 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2801
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002802 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002803 current_sctx.sc_sid, idx, sv->sv_type);
2804 return OK;
2805 }
2806
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002807 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002808 if (import != NULL)
2809 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002810 if (import->imp_all)
2811 {
2812 char_u *p = skipwhite(*end);
Bram Moolenaar1c991142020-07-04 13:15:31 +02002813 char_u *exp_name;
2814 int cc;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002815 ufunc_T *ufunc;
2816 type_T *type;
2817
2818 // Used "import * as Name", need to lookup the member.
2819 if (*p != '.')
2820 {
2821 semsg(_("E1060: expected dot after name: %s"), start);
2822 return FAIL;
2823 }
2824 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002825 if (VIM_ISWHITE(*p))
2826 {
2827 emsg(_("E1074: no white space allowed after dot"));
2828 return FAIL;
2829 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002830
Bram Moolenaar1c991142020-07-04 13:15:31 +02002831 // isolate one name
2832 exp_name = p;
2833 while (eval_isnamec(*p))
2834 ++p;
2835 cc = *p;
2836 *p = NUL;
2837
2838 idx = find_exported(import->imp_sid, exp_name, &ufunc, &type);
2839 *p = cc;
2840 p = skipwhite(p);
2841
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002842 // TODO: what if it is a function?
2843 if (idx < 0)
2844 return FAIL;
2845 *end = p;
2846
2847 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2848 import->imp_sid,
2849 idx,
2850 type);
2851 }
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002852 else if (import->imp_funcname != NULL)
2853 generate_PUSHFUNC(cctx, import->imp_funcname, import->imp_type);
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002854 else
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002855 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2856 import->imp_sid,
2857 import->imp_var_vals_idx,
2858 import->imp_type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002859 return OK;
2860 }
2861
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002862 if (error)
2863 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002864 return FAIL;
2865}
2866
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002867 static int
2868generate_funcref(cctx_T *cctx, char_u *name)
2869{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002870 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002871
2872 if (ufunc == NULL)
2873 return FAIL;
2874
Bram Moolenaarb8070e32020-07-23 20:56:04 +02002875 // Need to compile any default values to get the argument types.
2876 if (ufunc->uf_def_status == UF_TO_BE_COMPILED)
2877 if (compile_def_function(ufunc, TRUE, NULL) == FAIL)
2878 return FAIL;
Bram Moolenaar40f4f7a2020-07-23 22:41:43 +02002879 return generate_PUSHFUNC(cctx, ufunc->uf_name, ufunc->uf_func_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002880}
2881
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002882/*
2883 * Compile a variable name into a load instruction.
2884 * "end" points to just after the name.
2885 * When "error" is FALSE do not give an error when not found.
2886 */
2887 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002888compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002889{
2890 type_T *type;
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002891 char_u *name = NULL;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002892 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002893 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002894 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002895
2896 if (*(*arg + 1) == ':')
2897 {
2898 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002899 if (end <= *arg + 2)
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002900 {
2901 isntype_T isn_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002902
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002903 switch (**arg)
2904 {
2905 case 'g': isn_type = ISN_LOADGDICT; break;
2906 case 'w': isn_type = ISN_LOADWDICT; break;
2907 case 't': isn_type = ISN_LOADTDICT; break;
2908 case 'b': isn_type = ISN_LOADBDICT; break;
2909 default:
2910 semsg(_(e_namespace), *arg);
2911 goto theend;
2912 }
2913 if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
2914 goto theend;
2915 res = OK;
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002916 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002917 else
2918 {
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02002919 isntype_T isn_type = ISN_DROP;
2920
2921 name = vim_strnsave(*arg + 2, end - (*arg + 2));
2922 if (name == NULL)
2923 return FAIL;
2924
2925 switch (**arg)
2926 {
2927 case 'v': res = generate_LOADV(cctx, name, error);
2928 break;
2929 case 's': res = compile_load_scriptvar(cctx, name,
2930 NULL, NULL, error);
2931 break;
2932 case 'g': isn_type = ISN_LOADG; break;
2933 case 'w': isn_type = ISN_LOADW; break;
2934 case 't': isn_type = ISN_LOADT; break;
2935 case 'b': isn_type = ISN_LOADB; break;
2936 default: semsg(_(e_namespace), *arg);
2937 goto theend;
2938 }
2939 if (isn_type != ISN_DROP)
2940 {
2941 // Global, Buffer-local, Window-local and Tabpage-local
2942 // variables can be defined later, thus we don't check if it
2943 // exists, give error at runtime.
2944 res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
2945 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002946 }
2947 }
2948 else
2949 {
2950 size_t len = end - *arg;
2951 int idx;
2952 int gen_load = FALSE;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002953 int gen_load_outer = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002954
2955 name = vim_strnsave(*arg, end - *arg);
2956 if (name == NULL)
2957 return FAIL;
2958
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002959 if (lookup_arg(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002960 {
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002961 if (!gen_load_outer)
2962 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002963 }
2964 else
2965 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002966 lvar_T *lvar = lookup_local(*arg, len, cctx);
2967
2968 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002969 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002970 type = lvar->lv_type;
2971 idx = lvar->lv_idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002972 if (lvar->lv_from_outer)
2973 gen_load_outer = TRUE;
2974 else
2975 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002976 }
2977 else
2978 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02002979 // "var" can be script-local even without using "s:" if it
2980 // already exists.
2981 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2982 == SCRIPT_VERSION_VIM9
2983 || lookup_script(*arg, len) == OK)
2984 res = compile_load_scriptvar(cctx, name, *arg, &end,
2985 FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002986
Bram Moolenaara5565e42020-05-09 15:44:01 +02002987 // When the name starts with an uppercase letter or "x:" it
2988 // can be a user defined function.
2989 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2990 res = generate_funcref(cctx, name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002991 }
2992 }
2993 if (gen_load)
2994 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002995 if (gen_load_outer)
2996 res = generate_LOAD(cctx, ISN_LOADOUTER, idx, NULL, type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002997 }
2998
2999 *arg = end;
3000
3001theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01003002 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003003 semsg(_(e_var_notfound), name);
3004 vim_free(name);
3005 return res;
3006}
3007
3008/*
3009 * Compile the argument expressions.
3010 * "arg" points to just after the "(" and is advanced to after the ")"
3011 */
3012 static int
3013compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
3014{
Bram Moolenaar2c330432020-04-13 14:41:35 +02003015 char_u *p = *arg;
3016 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003017
Bram Moolenaare6085c52020-04-12 20:19:16 +02003018 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003019 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003020 if (may_get_next_line(whitep, &p, cctx) == FAIL)
3021 goto failret;
Bram Moolenaare6085c52020-04-12 20:19:16 +02003022 if (*p == ')')
3023 {
3024 *arg = p + 1;
3025 return OK;
3026 }
3027
Bram Moolenaara5565e42020-05-09 15:44:01 +02003028 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003029 return FAIL;
3030 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003031
3032 if (*p != ',' && *skipwhite(p) == ',')
3033 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02003034 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003035 p = skipwhite(p);
3036 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003037 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003038 {
3039 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02003040 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02003041 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003042 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003043 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01003044 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003045 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003046failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02003047 emsg(_(e_missing_close));
3048 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003049}
3050
3051/*
3052 * Compile a function call: name(arg1, arg2)
3053 * "arg" points to "name", "arg + varlen" to the "(".
3054 * "argcount_init" is 1 for "value->method()"
3055 * Instructions:
3056 * EVAL arg1
3057 * EVAL arg2
3058 * BCALL / DCALL / UCALL
3059 */
3060 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003061compile_call(
3062 char_u **arg,
3063 size_t varlen,
3064 cctx_T *cctx,
3065 ppconst_T *ppconst,
3066 int argcount_init)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003067{
3068 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01003069 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003070 int argcount = argcount_init;
3071 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003072 char_u fname_buf[FLEN_FIXED + 1];
3073 char_u *tofree = NULL;
3074 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003075 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003076 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003077
Bram Moolenaara5565e42020-05-09 15:44:01 +02003078 // we can evaluate "has('name')" at compile time
3079 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
3080 {
3081 char_u *s = skipwhite(*arg + varlen + 1);
3082 typval_T argvars[2];
3083
3084 argvars[0].v_type = VAR_UNKNOWN;
3085 if (*s == '"')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003086 (void)eval_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003087 else if (*s == '\'')
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003088 (void)eval_lit_string(&s, &argvars[0], TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003089 s = skipwhite(s);
3090 if (*s == ')' && argvars[0].v_type == VAR_STRING)
3091 {
3092 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
3093
3094 *arg = s + 1;
3095 argvars[1].v_type = VAR_UNKNOWN;
3096 tv->v_type = VAR_NUMBER;
3097 tv->vval.v_number = 0;
3098 f_has(argvars, tv);
3099 clear_tv(&argvars[0]);
3100 ++ppconst->pp_used;
3101 return OK;
3102 }
Bram Moolenaar497f76b2020-05-09 16:44:22 +02003103 clear_tv(&argvars[0]);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003104 }
3105
3106 if (generate_ppconst(cctx, ppconst) == FAIL)
3107 return FAIL;
3108
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003109 if (varlen >= sizeof(namebuf))
3110 {
3111 semsg(_("E1011: name too long: %s"), name);
3112 return FAIL;
3113 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003114 vim_strncpy(namebuf, *arg, varlen);
3115 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003116
3117 *arg = skipwhite(*arg + varlen + 1);
3118 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003119 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003120
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003121 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003122 {
3123 int idx;
3124
3125 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003126 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003127 if (idx >= 0)
Bram Moolenaar389df252020-07-09 21:20:47 +02003128 res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003129 else
3130 semsg(_(e_unknownfunc), namebuf);
3131 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003132 }
3133
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003134 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02003135 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003136 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003137 {
3138 res = generate_CALL(cctx, ufunc, argcount);
3139 goto theend;
3140 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003141
3142 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02003143 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003144 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02003145 if (STRNCMP(namebuf, "g:", 2) != 0
3146 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003147 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003148 garray_T *stack = &cctx->ctx_type_stack;
3149 type_T *type;
3150
3151 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3152 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003153 goto theend;
3154 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003155
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003156 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003157 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02003158 if (STRNCMP(namebuf, "g:", 2) == 0)
3159 res = generate_UCALL(cctx, name, argcount);
3160 else
3161 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01003162
3163theend:
3164 vim_free(tofree);
3165 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003166}
3167
3168// like NAMESPACE_CHAR but with 'a' and 'l'.
3169#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
3170
3171/*
3172 * Find the end of a variable or function name. Unlike find_name_end() this
3173 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003174 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003175 * Return a pointer to just after the name. Equal to "arg" if there is no
3176 * valid name.
3177 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003178 static char_u *
3179to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003180{
3181 char_u *p;
3182
3183 // Quick check for valid starting character.
3184 if (!eval_isnamec1(*arg))
3185 return arg;
3186
3187 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
3188 // Include a namespace such as "s:var" and "v:var". But "n:" is not
3189 // and can be used in slice "[n:]".
3190 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003191 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003192 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
3193 break;
3194 return p;
3195}
3196
3197/*
3198 * Like to_name_end() but also skip over a list or dict constant.
Bram Moolenaar1c991142020-07-04 13:15:31 +02003199 * This intentionally does not handle line continuation.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003200 */
3201 char_u *
3202to_name_const_end(char_u *arg)
3203{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003204 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003205 typval_T rettv;
3206
3207 if (p == arg && *arg == '[')
3208 {
3209
3210 // Can be "[1, 2, 3]->Func()".
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003211 if (eval_list(&p, &rettv, NULL, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003212 p = arg;
3213 }
3214 else if (p == arg && *arg == '#' && arg[1] == '{')
3215 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01003216 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003217 ++p;
Bram Moolenaar8ea93902020-06-27 14:11:53 +02003218 if (eval_dict(&p, &rettv, NULL, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003219 p = arg;
3220 }
3221 else if (p == arg && *arg == '{')
3222 {
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003223 int ret = get_lambda_tv(&p, &rettv, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003224
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01003225 // Can be "{x -> ret}()".
3226 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003227 if (ret == NOTDONE)
Bram Moolenaar8ea93902020-06-27 14:11:53 +02003228 ret = eval_dict(&p, &rettv, NULL, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003229 if (ret != OK)
3230 p = arg;
3231 }
3232
3233 return p;
3234}
3235
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003236/*
3237 * parse a list: [expr, expr]
3238 * "*arg" points to the '['.
3239 */
3240 static int
3241compile_list(char_u **arg, cctx_T *cctx)
3242{
3243 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003244 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003245 int count = 0;
3246
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003247 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003248 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003249 if (may_get_next_line(whitep, &p, cctx) == FAIL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01003250 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003251 semsg(_(e_list_end), *arg);
3252 return FAIL;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003253 }
3254 if (*p == ']')
3255 {
3256 ++p;
3257 // Allow for following comment, after at least one space.
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003258 if (VIM_ISWHITE(*p) && *skipwhite(p) == '#')
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003259 p += STRLEN(p);
3260 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01003261 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02003262 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003263 break;
3264 ++count;
3265 if (*p == ',')
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003266 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003267 ++p;
Bram Moolenaar6b7a0a82020-07-08 18:38:08 +02003268 if (*p != ']' && !IS_WHITE_OR_NUL(*p))
3269 {
3270 semsg(_(e_white_after), ",");
3271 return FAIL;
3272 }
3273 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003274 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003275 p = skipwhite(p);
3276 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003277 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003278
3279 generate_NEWLIST(cctx, count);
3280 return OK;
3281}
3282
3283/*
3284 * parse a lambda: {arg, arg -> expr}
3285 * "*arg" points to the '{'.
3286 */
3287 static int
3288compile_lambda(char_u **arg, cctx_T *cctx)
3289{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003290 typval_T rettv;
3291 ufunc_T *ufunc;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003292 evalarg_T evalarg;
3293
3294 CLEAR_FIELD(evalarg);
3295 evalarg.eval_flags = EVAL_EVALUATE;
3296 evalarg.eval_cctx = cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003297
3298 // Get the funcref in "rettv".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003299 if (get_lambda_tv(arg, &rettv, &evalarg) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003300 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003301
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003302 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003303 ++ufunc->uf_refcount;
3304 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003305 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003306
3307 // The function will have one line: "return {expr}".
3308 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003309 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003310
Bram Moolenaar8e2730a2020-07-08 22:01:49 +02003311 clear_evalarg(&evalarg, NULL);
3312
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02003313 if (ufunc->uf_def_status == UF_COMPILED)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02003314 return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003315
3316 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003317 return FAIL;
3318}
3319
3320/*
3321 * Compile a lamda call: expr->{lambda}(args)
3322 * "arg" points to the "{".
3323 */
3324 static int
3325compile_lambda_call(char_u **arg, cctx_T *cctx)
3326{
3327 ufunc_T *ufunc;
3328 typval_T rettv;
3329 int argcount = 1;
3330 int ret = FAIL;
3331
3332 // Get the funcref in "rettv".
Bram Moolenaare40fbc22020-06-27 18:06:45 +02003333 if (get_lambda_tv(arg, &rettv, &EVALARG_EVALUATE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003334 return FAIL;
3335
3336 if (**arg != '(')
3337 {
3338 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01003339 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003340 else
3341 semsg(_(e_missing_paren), "lambda");
3342 clear_tv(&rettv);
3343 return FAIL;
3344 }
3345
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003346 ufunc = rettv.vval.v_partial->pt_func;
3347 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003348 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003349 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01003350
3351 // The function will have one line: "return {expr}".
3352 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003353 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003354
3355 // compile the arguments
3356 *arg = skipwhite(*arg + 1);
3357 if (compile_arguments(arg, cctx, &argcount) == OK)
3358 // call the compiled function
3359 ret = generate_CALL(cctx, ufunc, argcount);
3360
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003361 if (ret == FAIL)
3362 func_ptr_unref(ufunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003363 return ret;
3364}
3365
3366/*
3367 * parse a dict: {'key': val} or #{key: val}
3368 * "*arg" points to the '{'.
3369 */
3370 static int
3371compile_dict(char_u **arg, cctx_T *cctx, int literal)
3372{
3373 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaarf1a23682020-07-13 18:55:48 +02003374 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003375 int count = 0;
3376 dict_T *d = dict_alloc();
3377 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003378 char_u *whitep = *arg;
3379 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003380
3381 if (d == NULL)
3382 return FAIL;
3383 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003384 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003385 {
3386 char_u *key = NULL;
3387
Bram Moolenaar23c55272020-06-21 16:58:13 +02003388 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003389 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003390 *arg = NULL;
3391 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003392 }
3393
3394 if (**arg == '}')
3395 break;
3396
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003397 if (literal)
3398 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02003399 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003400
Bram Moolenaar2c330432020-04-13 14:41:35 +02003401 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003402 {
3403 semsg(_("E1014: Invalid key: %s"), *arg);
3404 return FAIL;
3405 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003406 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003407 if (generate_PUSHS(cctx, key) == FAIL)
3408 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003409 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003410 }
3411 else
3412 {
3413 isn_T *isn;
3414
Bram Moolenaara5565e42020-05-09 15:44:01 +02003415 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003416 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003417 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
3418 if (isn->isn_type == ISN_PUSHS)
3419 key = isn->isn_arg.string;
Bram Moolenaarf1a23682020-07-13 18:55:48 +02003420 else
3421 {
3422 type_T *keytype = ((type_T **)stack->ga_data)
3423 [stack->ga_len - 1];
3424 if (need_type(keytype, &t_string, -1, cctx, FALSE) == FAIL)
3425 return FAIL;
3426 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003427 }
3428
3429 // Check for duplicate keys, if using string keys.
3430 if (key != NULL)
3431 {
3432 item = dict_find(d, key, -1);
3433 if (item != NULL)
3434 {
3435 semsg(_(e_duplicate_key), key);
3436 goto failret;
3437 }
3438 item = dictitem_alloc(key);
3439 if (item != NULL)
3440 {
3441 item->di_tv.v_type = VAR_UNKNOWN;
3442 item->di_tv.v_lock = 0;
3443 if (dict_add(d, item) == FAIL)
3444 dictitem_free(item);
3445 }
3446 }
3447
3448 *arg = skipwhite(*arg);
3449 if (**arg != ':')
3450 {
3451 semsg(_(e_missing_dict_colon), *arg);
3452 return FAIL;
3453 }
3454
Bram Moolenaar2c330432020-04-13 14:41:35 +02003455 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003456 *arg = skipwhite(*arg + 1);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003457 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003458 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003459 *arg = NULL;
3460 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003461 }
3462
Bram Moolenaara5565e42020-05-09 15:44:01 +02003463 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003464 return FAIL;
3465 ++count;
3466
Bram Moolenaar2c330432020-04-13 14:41:35 +02003467 whitep = *arg;
Bram Moolenaar23c55272020-06-21 16:58:13 +02003468 *arg = skipwhite(*arg);
3469 if (may_get_next_line(whitep, arg, cctx) == FAIL)
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003470 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003471 *arg = NULL;
3472 goto failret;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003473 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003474 if (**arg == '}')
3475 break;
3476 if (**arg != ',')
3477 {
3478 semsg(_(e_missing_dict_comma), *arg);
3479 goto failret;
3480 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003481 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003482 *arg = skipwhite(*arg + 1);
3483 }
3484
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003485 *arg = *arg + 1;
3486
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003487 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02003488 p = skipwhite(*arg);
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003489 if (VIM_ISWHITE(**arg) && vim9_comment_start(p))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003490 *arg += STRLEN(*arg);
3491
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003492 dict_unref(d);
3493 return generate_NEWDICT(cctx, count);
3494
3495failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003496 if (*arg == NULL)
3497 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003498 dict_unref(d);
3499 return FAIL;
3500}
3501
3502/*
3503 * Compile "&option".
3504 */
3505 static int
3506compile_get_option(char_u **arg, cctx_T *cctx)
3507{
3508 typval_T rettv;
3509 char_u *start = *arg;
3510 int ret;
3511
3512 // parse the option and get the current value to get the type.
3513 rettv.v_type = VAR_UNKNOWN;
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003514 ret = eval_option(arg, &rettv, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003515 if (ret == OK)
3516 {
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003517 // include the '&' in the name, eval_option() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003518 char_u *name = vim_strnsave(start, *arg - start);
3519 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
3520
3521 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
3522 vim_free(name);
3523 }
3524 clear_tv(&rettv);
3525
3526 return ret;
3527}
3528
3529/*
3530 * Compile "$VAR".
3531 */
3532 static int
3533compile_get_env(char_u **arg, cctx_T *cctx)
3534{
3535 char_u *start = *arg;
3536 int len;
3537 int ret;
3538 char_u *name;
3539
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003540 ++*arg;
3541 len = get_env_len(arg);
3542 if (len == 0)
3543 {
3544 semsg(_(e_syntax_at), start - 1);
3545 return FAIL;
3546 }
3547
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02003548 // include the '$' in the name, eval_env_var() expects it.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003549 name = vim_strnsave(start, len + 1);
3550 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
3551 vim_free(name);
3552 return ret;
3553}
3554
3555/*
3556 * Compile "@r".
3557 */
3558 static int
3559compile_get_register(char_u **arg, cctx_T *cctx)
3560{
3561 int ret;
3562
3563 ++*arg;
3564 if (**arg == NUL)
3565 {
3566 semsg(_(e_syntax_at), *arg - 1);
3567 return FAIL;
3568 }
Bram Moolenaar7226e5b2020-08-02 17:33:26 +02003569 if (!valid_yank_reg(**arg, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003570 {
3571 emsg_invreg(**arg);
3572 return FAIL;
3573 }
3574 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3575 ++*arg;
3576 return ret;
3577}
3578
3579/*
3580 * Apply leading '!', '-' and '+' to constant "rettv".
3581 */
3582 static int
3583apply_leader(typval_T *rettv, char_u *start, char_u *end)
3584{
3585 char_u *p = end;
3586
3587 // this works from end to start
3588 while (p > start)
3589 {
3590 --p;
3591 if (*p == '-' || *p == '+')
3592 {
3593 // only '-' has an effect, for '+' we only check the type
3594#ifdef FEAT_FLOAT
3595 if (rettv->v_type == VAR_FLOAT)
3596 {
3597 if (*p == '-')
3598 rettv->vval.v_float = -rettv->vval.v_float;
3599 }
3600 else
3601#endif
3602 {
3603 varnumber_T val;
3604 int error = FALSE;
3605
3606 // tv_get_number_chk() accepts a string, but we don't want that
3607 // here
3608 if (check_not_string(rettv) == FAIL)
3609 return FAIL;
3610 val = tv_get_number_chk(rettv, &error);
3611 clear_tv(rettv);
3612 if (error)
3613 return FAIL;
3614 if (*p == '-')
3615 val = -val;
3616 rettv->v_type = VAR_NUMBER;
3617 rettv->vval.v_number = val;
3618 }
3619 }
3620 else
3621 {
3622 int v = tv2bool(rettv);
3623
3624 // '!' is permissive in the type.
3625 clear_tv(rettv);
3626 rettv->v_type = VAR_BOOL;
3627 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3628 }
3629 }
3630 return OK;
3631}
3632
3633/*
3634 * Recognize v: variables that are constants and set "rettv".
3635 */
3636 static void
3637get_vim_constant(char_u **arg, typval_T *rettv)
3638{
3639 if (STRNCMP(*arg, "v:true", 6) == 0)
3640 {
3641 rettv->v_type = VAR_BOOL;
3642 rettv->vval.v_number = VVAL_TRUE;
3643 *arg += 6;
3644 }
3645 else if (STRNCMP(*arg, "v:false", 7) == 0)
3646 {
3647 rettv->v_type = VAR_BOOL;
3648 rettv->vval.v_number = VVAL_FALSE;
3649 *arg += 7;
3650 }
3651 else if (STRNCMP(*arg, "v:null", 6) == 0)
3652 {
3653 rettv->v_type = VAR_SPECIAL;
3654 rettv->vval.v_number = VVAL_NULL;
3655 *arg += 6;
3656 }
3657 else if (STRNCMP(*arg, "v:none", 6) == 0)
3658 {
3659 rettv->v_type = VAR_SPECIAL;
3660 rettv->vval.v_number = VVAL_NONE;
3661 *arg += 6;
3662 }
3663}
3664
Bram Moolenaar696ba232020-07-29 21:20:41 +02003665 exptype_T
Bram Moolenaar61a89812020-05-07 16:58:17 +02003666get_compare_type(char_u *p, int *len, int *type_is)
3667{
3668 exptype_T type = EXPR_UNKNOWN;
3669 int i;
3670
3671 switch (p[0])
3672 {
3673 case '=': if (p[1] == '=')
3674 type = EXPR_EQUAL;
3675 else if (p[1] == '~')
3676 type = EXPR_MATCH;
3677 break;
3678 case '!': if (p[1] == '=')
3679 type = EXPR_NEQUAL;
3680 else if (p[1] == '~')
3681 type = EXPR_NOMATCH;
3682 break;
3683 case '>': if (p[1] != '=')
3684 {
3685 type = EXPR_GREATER;
3686 *len = 1;
3687 }
3688 else
3689 type = EXPR_GEQUAL;
3690 break;
3691 case '<': if (p[1] != '=')
3692 {
3693 type = EXPR_SMALLER;
3694 *len = 1;
3695 }
3696 else
3697 type = EXPR_SEQUAL;
3698 break;
3699 case 'i': if (p[1] == 's')
3700 {
3701 // "is" and "isnot"; but not a prefix of a name
3702 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3703 *len = 5;
3704 i = p[*len];
3705 if (!isalnum(i) && i != '_')
3706 {
3707 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3708 *type_is = TRUE;
3709 }
3710 }
3711 break;
3712 }
3713 return type;
3714}
3715
3716/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003717 * Compile code to apply '-', '+' and '!'.
3718 */
3719 static int
3720compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3721{
3722 char_u *p = end;
3723
3724 // this works from end to start
3725 while (p > start)
3726 {
3727 --p;
3728 if (*p == '-' || *p == '+')
3729 {
3730 int negate = *p == '-';
3731 isn_T *isn;
3732
3733 // TODO: check type
3734 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3735 {
3736 --p;
3737 if (*p == '-')
3738 negate = !negate;
3739 }
3740 // only '-' has an effect, for '+' we only check the type
3741 if (negate)
3742 isn = generate_instr(cctx, ISN_NEGATENR);
3743 else
3744 isn = generate_instr(cctx, ISN_CHECKNR);
3745 if (isn == NULL)
3746 return FAIL;
3747 }
3748 else
3749 {
3750 int invert = TRUE;
3751
3752 while (p > start && p[-1] == '!')
3753 {
3754 --p;
3755 invert = !invert;
3756 }
3757 if (generate_2BOOL(cctx, invert) == FAIL)
3758 return FAIL;
3759 }
3760 }
3761 return OK;
3762}
3763
3764/*
3765 * Compile whatever comes after "name" or "name()".
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003766 * Advances "*arg" only when something was recognized.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003767 */
3768 static int
3769compile_subscript(
3770 char_u **arg,
3771 cctx_T *cctx,
3772 char_u **start_leader,
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003773 char_u *end_leader,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003774 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003775{
3776 for (;;)
3777 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02003778 char_u *p = skipwhite(*arg);
3779
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02003780 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p)))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003781 {
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003782 char_u *next = peek_next_line_from_context(cctx);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003783
3784 // If a following line starts with "->{" or "->X" advance to that
3785 // line, so that a line break before "->" is allowed.
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003786 // Also if a following line starts with ".x".
3787 if (next != NULL &&
3788 ((next[0] == '-' && next[1] == '>'
3789 && (next[2] == '{' || ASCII_ISALPHA(next[2])))
Bram Moolenaarb13ab992020-07-27 21:43:28 +02003790 || (next[0] == '.' && eval_isdictc(next[1]))))
Bram Moolenaar23c55272020-06-21 16:58:13 +02003791 {
3792 next = next_line_from_context(cctx, TRUE);
3793 if (next == NULL)
3794 return FAIL;
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003795 *arg = next;
3796 p = skipwhite(*arg);
Bram Moolenaar23c55272020-06-21 16:58:13 +02003797 }
3798 }
3799
Bram Moolenaar2d6b20d2020-07-25 19:30:59 +02003800 // Do not skip over white space to find the "(", "exeucte 'x' ()" is
3801 // not a function call.
3802 if (**arg == '(')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003803 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003804 garray_T *stack = &cctx->ctx_type_stack;
3805 type_T *type;
3806 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003807
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003808 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003809 return FAIL;
3810
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003811 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003812 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3813
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003814 *arg = skipwhite(p + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003815 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3816 return FAIL;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003817 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003818 return FAIL;
3819 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003820 else if (*p == '-' && p[1] == '>')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003821 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02003822 char_u *pstart = p;
3823
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003824 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003825 return FAIL;
3826
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003827 // something->method()
3828 // Apply the '!', '-' and '+' first:
3829 // -1.0->func() works like (-1.0)->func()
3830 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3831 return FAIL;
3832 *start_leader = end_leader; // don't apply again later
3833
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003834 p += 2;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003835 *arg = skipwhite(p);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003836 // No line break supported right after "->".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003837 if (**arg == '{')
3838 {
3839 // lambda call: list->{lambda}
3840 if (compile_lambda_call(arg, cctx) == FAIL)
3841 return FAIL;
3842 }
3843 else
3844 {
3845 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003846 p = *arg;
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003847 if (!eval_isnamec1(*p))
3848 {
Bram Moolenaar637cd7d2020-07-23 19:06:23 +02003849 semsg(_(e_trailing_arg), pstart);
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02003850 return FAIL;
3851 }
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003852 if (ASCII_ISALPHA(*p) && p[1] == ':')
3853 p += 2;
3854 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003855 ;
3856 if (*p != '(')
3857 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003858 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003859 return FAIL;
3860 }
3861 // TODO: base value may not be the first argument
Bram Moolenaara5565e42020-05-09 15:44:01 +02003862 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003863 return FAIL;
3864 }
3865 }
Bram Moolenaarbadd8482020-07-31 22:38:17 +02003866 else if (**arg == '[')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003867 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003868 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003869 type_T **typep;
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003870 vartype_T vtype;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003871
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003872 // list index: list[123]
Bram Moolenaara6e67e42020-05-15 23:36:40 +02003873 // dict member: dict[key]
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003874 // string index: text[123]
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003875 // TODO: blob index
3876 // TODO: more arguments
3877 // TODO: recognize list or dict at runtime
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003878 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003879 return FAIL;
3880
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003881 ++p;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003882 *arg = skipwhite(p);
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003883 if (may_get_next_line_error(p, arg, cctx) == FAIL)
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003884 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02003885 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003886 return FAIL;
3887
Bram Moolenaara7eedf32020-07-10 21:50:41 +02003888 if (may_get_next_line_error(p, arg, cctx) == FAIL)
3889 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003890 if (**arg != ']')
3891 {
3892 emsg(_(e_missbrac));
3893 return FAIL;
3894 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003895 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003896
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003897 // We can index a list and a dict. If we don't know the type
3898 // we can use the index value type.
3899 // TODO: If we don't know use an instruction to figure it out at
3900 // runtime.
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003901 typep = ((type_T **)stack->ga_data) + stack->ga_len - 2;
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003902 vtype = (*typep)->tt_type;
3903 if (*typep == &t_any)
3904 {
3905 type_T *valtype = ((type_T **)stack->ga_data)
3906 [stack->ga_len - 1];
3907 if (valtype == &t_string)
3908 vtype = VAR_DICT;
3909 }
3910 if (vtype == VAR_DICT)
3911 {
3912 if ((*typep)->tt_type == VAR_DICT)
3913 *typep = (*typep)->tt_member;
Bram Moolenaar7892b952020-07-20 22:09:34 +02003914 else
3915 {
3916 if (need_type(*typep, &t_dict_any, -2, cctx, FALSE) == FAIL)
3917 return FAIL;
3918 *typep = &t_any;
3919 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003920 if (may_generate_2STRING(-1, cctx) == FAIL)
3921 return FAIL;
3922 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
3923 return FAIL;
3924 }
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003925 else if (vtype == VAR_STRING)
3926 {
3927 *typep = &t_number;
3928 if (generate_instr_drop(cctx, ISN_STRINDEX, 1) == FAIL)
3929 return FAIL;
3930 }
Bram Moolenaar6802cce2020-07-19 15:49:49 +02003931 else if (vtype == VAR_LIST || *typep == &t_any)
Bram Moolenaarb13af502020-02-17 21:12:08 +01003932 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003933 if ((*typep)->tt_type == VAR_LIST)
3934 *typep = (*typep)->tt_member;
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02003935 if (generate_instr_drop(cctx, ISN_LISTINDEX, 1) == FAIL)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003936 return FAIL;
3937 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003938 else
3939 {
3940 emsg(_(e_listdictblobreq));
Bram Moolenaarb13af502020-02-17 21:12:08 +01003941 return FAIL;
3942 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003943 }
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003944 else if (*p == '.' && p[1] != '.')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003945 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003946 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003947 return FAIL;
3948
Bram Moolenaar7a4b8982020-07-08 17:36:21 +02003949 *arg = p + 1;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003950 if (may_get_next_line(*arg, arg, cctx) == FAIL)
3951 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003952 // dictionary member: dict.name
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02003953 p = *arg;
Bram Moolenaarb13ab992020-07-27 21:43:28 +02003954 if (eval_isdictc(*p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003955 while (eval_isnamec(*p))
3956 MB_PTR_ADV(p);
3957 if (p == *arg)
3958 {
3959 semsg(_(e_syntax_at), *arg);
3960 return FAIL;
3961 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003962 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003963 return FAIL;
3964 *arg = p;
3965 }
3966 else
3967 break;
3968 }
3969
3970 // TODO - see handle_subscript():
3971 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3972 // Don't do this when "Func" is already a partial that was bound
3973 // explicitly (pt_auto is FALSE).
3974
3975 return OK;
3976}
3977
3978/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003979 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
3980 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003981 *
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003982 * If the value is a constant "ppconst->pp_ret" will be set.
3983 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003984 *
3985 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003986 */
3987
3988/*
3989 * number number constant
3990 * 0zFFFFFFFF Blob constant
3991 * "string" string constant
3992 * 'string' literal string constant
3993 * &option-name option value
3994 * @r register contents
3995 * identifier variable value
3996 * function() function call
3997 * $VAR environment variable
3998 * (expression) nested expression
3999 * [expr, expr] List
4000 * {key: val, key: val} Dictionary
4001 * #{key: val, key: val} Dictionary with literal keys
4002 *
4003 * Also handle:
4004 * ! in front logical NOT
4005 * - in front unary minus
4006 * + in front unary plus (ignored)
4007 * trailing (arg) funcref/partial call
4008 * trailing [] subscript in String or List
4009 * trailing .name entry in Dictionary
4010 * trailing ->name() method call
4011 */
4012 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004013compile_expr7(
4014 char_u **arg,
4015 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004016 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004017{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004018 char_u *start_leader, *end_leader;
4019 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004020 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02004021 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004022
4023 /*
4024 * Skip '!', '-' and '+' characters. They are handled later.
4025 */
4026 start_leader = *arg;
4027 while (**arg == '!' || **arg == '-' || **arg == '+')
4028 *arg = skipwhite(*arg + 1);
4029 end_leader = *arg;
4030
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004031 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004032 switch (**arg)
4033 {
4034 /*
4035 * Number constant.
4036 */
4037 case '0': // also for blob starting with 0z
4038 case '1':
4039 case '2':
4040 case '3':
4041 case '4':
4042 case '5':
4043 case '6':
4044 case '7':
4045 case '8':
4046 case '9':
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004047 case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004048 return FAIL;
4049 break;
4050
4051 /*
4052 * String constant: "string".
4053 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004054 case '"': if (eval_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004055 return FAIL;
4056 break;
4057
4058 /*
4059 * Literal string constant: 'str''ing'.
4060 */
Bram Moolenaar9a78e6d2020-07-01 18:29:55 +02004061 case '\'': if (eval_lit_string(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004062 return FAIL;
4063 break;
4064
4065 /*
4066 * Constant Vim variable.
4067 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004068 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004069 ret = NOTDONE;
4070 break;
4071
4072 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004073 * "true" constant
4074 */
4075 case 't': if (STRNCMP(*arg, "true", 4) == 0
4076 && !eval_isnamec((*arg)[4]))
4077 {
4078 *arg += 4;
4079 rettv->v_type = VAR_BOOL;
4080 rettv->vval.v_number = VVAL_TRUE;
4081 }
4082 else
4083 ret = NOTDONE;
4084 break;
4085
4086 /*
4087 * "false" constant
4088 */
4089 case 'f': if (STRNCMP(*arg, "false", 5) == 0
4090 && !eval_isnamec((*arg)[5]))
4091 {
4092 *arg += 5;
4093 rettv->v_type = VAR_BOOL;
4094 rettv->vval.v_number = VVAL_FALSE;
4095 }
4096 else
4097 ret = NOTDONE;
4098 break;
4099
4100 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004101 * List: [expr, expr]
4102 */
4103 case '[': ret = compile_list(arg, cctx);
4104 break;
4105
4106 /*
4107 * Dictionary: #{key: val, key: val}
4108 */
4109 case '#': if ((*arg)[1] == '{')
4110 {
4111 ++*arg;
4112 ret = compile_dict(arg, cctx, TRUE);
4113 }
4114 else
4115 ret = NOTDONE;
4116 break;
4117
4118 /*
4119 * Lambda: {arg, arg -> expr}
4120 * Dictionary: {'key': val, 'key': val}
4121 */
4122 case '{': {
4123 char_u *start = skipwhite(*arg + 1);
4124
4125 // Find out what comes after the arguments.
4126 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02004127 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004128 if (ret != FAIL && *start == '>')
4129 ret = compile_lambda(arg, cctx);
4130 else
4131 ret = compile_dict(arg, cctx, FALSE);
4132 }
4133 break;
4134
4135 /*
4136 * Option value: &name
4137 */
4138 case '&': ret = compile_get_option(arg, cctx);
4139 break;
4140
4141 /*
4142 * Environment variable: $VAR.
4143 */
4144 case '$': ret = compile_get_env(arg, cctx);
4145 break;
4146
4147 /*
4148 * Register contents: @r.
4149 */
4150 case '@': ret = compile_get_register(arg, cctx);
4151 break;
4152 /*
4153 * nested expression: (expression).
4154 */
4155 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaar1c747212020-05-09 18:28:34 +02004156
4157 // recursive!
4158 if (ppconst->pp_used <= PPSIZE - 10)
4159 {
4160 ret = compile_expr1(arg, cctx, ppconst);
4161 }
4162 else
4163 {
4164 // Not enough space in ppconst, flush constants.
4165 if (generate_ppconst(cctx, ppconst) == FAIL)
4166 return FAIL;
4167 ret = compile_expr0(arg, cctx);
4168 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004169 *arg = skipwhite(*arg);
4170 if (**arg == ')')
4171 ++*arg;
4172 else if (ret == OK)
4173 {
4174 emsg(_(e_missing_close));
4175 ret = FAIL;
4176 }
4177 break;
4178
4179 default: ret = NOTDONE;
4180 break;
4181 }
4182 if (ret == FAIL)
4183 return FAIL;
4184
Bram Moolenaar1c747212020-05-09 18:28:34 +02004185 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004186 {
4187 // apply the '!', '-' and '+' before the constant
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004188 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004189 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004190 clear_tv(rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004191 return FAIL;
4192 }
4193 start_leader = end_leader; // don't apply again below
4194
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004195 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004196 clear_tv(rettv);
4197 else
4198 // A constant expression can possibly be handled compile time,
4199 // return the value instead of generating code.
4200 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004201 }
4202 else if (ret == NOTDONE)
4203 {
4204 char_u *p;
4205 int r;
4206
4207 if (!eval_isnamec1(**arg))
4208 {
4209 semsg(_("E1015: Name expected: %s"), *arg);
4210 return FAIL;
4211 }
4212
4213 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01004214 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004215 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02004216 {
4217 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
4218 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004219 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02004220 {
4221 if (generate_ppconst(cctx, ppconst) == FAIL)
4222 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004223 r = compile_load(arg, p, cctx, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004224 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004225 if (r == FAIL)
4226 return FAIL;
4227 }
4228
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004229 // Handle following "[]", ".member", etc.
4230 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004231 if (compile_subscript(arg, cctx, &start_leader, end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02004232 ppconst) == FAIL)
4233 return FAIL;
4234 if (ppconst->pp_used > 0)
4235 {
4236 // apply the '!', '-' and '+' before the constant
4237 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
4238 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
4239 return FAIL;
4240 return OK;
4241 }
4242 if (compile_leader(cctx, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004243 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02004244 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004245}
4246
4247/*
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004248 * Give the "white on both sides" error, taking the operator from "p[len]".
4249 */
4250 void
4251error_white_both(char_u *op, int len)
4252{
4253 char_u buf[10];
4254
4255 vim_strncpy(buf, op, len);
4256 semsg(_(e_white_both), buf);
4257}
4258
4259/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004260 * * number multiplication
4261 * / number division
4262 * % number modulo
4263 */
4264 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004265compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004266{
4267 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004268 char_u *next;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004269 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004270
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004271 // get the first expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004272 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004273 return FAIL;
4274
4275 /*
4276 * Repeat computing, until no "*", "/" or "%" is following.
4277 */
4278 for (;;)
4279 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004280 op = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004281 if (*op != '*' && *op != '/' && *op != '%')
4282 break;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004283 if (next != NULL)
4284 {
4285 *arg = next_line_from_context(cctx, TRUE);
4286 op = skipwhite(*arg);
4287 }
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004288
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004289 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004290 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004291 error_white_both(op, 1);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004292 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004293 }
4294 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004295 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004296 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004297
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004298 // get the second expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004299 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004300 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004301
4302 if (ppconst->pp_used == ppconst_used + 2
4303 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4304 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004305 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004306 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4307 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004308 varnumber_T res = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004309
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004310 // both are numbers: compute the result
4311 switch (*op)
4312 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004313 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004314 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004315 case '/': res = tv1->vval.v_number / tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004316 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004317 case '%': res = tv1->vval.v_number % tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004318 break;
4319 }
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004320 tv1->vval.v_number = res;
4321 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004322 }
4323 else
4324 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004325 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004326 generate_two_op(cctx, op);
4327 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004328 }
4329
4330 return OK;
4331}
4332
4333/*
4334 * + number addition
4335 * - number subtraction
4336 * .. string concatenation
4337 */
4338 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004339compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004340{
4341 char_u *op;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004342 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004343 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004344 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004345
4346 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004347 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004348 return FAIL;
4349
4350 /*
4351 * Repeat computing, until no "+", "-" or ".." is following.
4352 */
4353 for (;;)
4354 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004355 op = may_peek_next_line(cctx, *arg, &next);
4356 if (*op != '+' && *op != '-' && !(*op == '.' && *(op + 1) == '.'))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004357 break;
4358 oplen = (*op == '.' ? 2 : 1);
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004359 if (next != NULL)
4360 {
4361 *arg = next_line_from_context(cctx, TRUE);
4362 op = skipwhite(*arg);
4363 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004364
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004365 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004366 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004367 error_white_both(op, oplen);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004368 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004369 }
4370
4371 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004372 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004373 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004374
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004375 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004376 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004377 return FAIL;
4378
Bram Moolenaara5565e42020-05-09 15:44:01 +02004379 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004380 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02004381 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
4382 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
4383 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
4384 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004385 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004386 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
4387 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004388
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004389 // concat/subtract/add constant numbers
4390 if (*op == '+')
4391 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
4392 else if (*op == '-')
4393 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
4394 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004395 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004396 // concatenate constant strings
4397 char_u *s1 = tv1->vval.v_string;
4398 char_u *s2 = tv2->vval.v_string;
4399 size_t len1 = STRLEN(s1);
4400
4401 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
4402 if (tv1->vval.v_string == NULL)
4403 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004404 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02004405 return FAIL;
4406 }
4407 mch_memmove(tv1->vval.v_string, s1, len1);
4408 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004409 vim_free(s1);
4410 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004411 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004412 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004413 }
4414 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004415 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02004416 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02004417 if (*op == '.')
4418 {
4419 if (may_generate_2STRING(-2, cctx) == FAIL
4420 || may_generate_2STRING(-1, cctx) == FAIL)
4421 return FAIL;
4422 generate_instr_drop(cctx, ISN_CONCAT, 1);
4423 }
4424 else
4425 generate_two_op(cctx, op);
4426 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004427 }
4428
4429 return OK;
4430}
4431
4432/*
4433 * expr5a == expr5b
4434 * expr5a =~ expr5b
4435 * expr5a != expr5b
4436 * expr5a !~ expr5b
4437 * expr5a > expr5b
4438 * expr5a >= expr5b
4439 * expr5a < expr5b
4440 * expr5a <= expr5b
4441 * expr5a is expr5b
4442 * expr5a isnot expr5b
4443 *
4444 * Produces instructions:
4445 * EVAL expr5a Push result of "expr5a"
4446 * EVAL expr5b Push result of "expr5b"
4447 * COMPARE one of the compare instructions
4448 */
4449 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004450compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004451{
4452 exptype_T type = EXPR_UNKNOWN;
4453 char_u *p;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004454 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004455 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004456 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004457 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004458
4459 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004460 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004461 return FAIL;
4462
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004463 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004464 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004465
4466 /*
4467 * If there is a comparative operator, use it.
4468 */
4469 if (type != EXPR_UNKNOWN)
4470 {
4471 int ic = FALSE; // Default: do not ignore case
4472
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004473 if (next != NULL)
4474 {
4475 *arg = next_line_from_context(cctx, TRUE);
4476 p = skipwhite(*arg);
4477 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004478 if (type_is && (p[len] == '?' || p[len] == '#'))
4479 {
4480 semsg(_(e_invexpr2), *arg);
4481 return FAIL;
4482 }
4483 // extra question mark appended: ignore case
4484 if (p[len] == '?')
4485 {
4486 ic = TRUE;
4487 ++len;
4488 }
4489 // extra '#' appended: match case (ignored)
4490 else if (p[len] == '#')
4491 ++len;
4492 // nothing appended: match case
4493
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004494 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004495 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02004496 error_white_both(p, len);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004497 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004498 }
4499
4500 // get the second variable
4501 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004502 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004503 return FAIL;
4504
Bram Moolenaara5565e42020-05-09 15:44:01 +02004505 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004506 return FAIL;
4507
Bram Moolenaara5565e42020-05-09 15:44:01 +02004508 if (ppconst->pp_used == ppconst_used + 2)
4509 {
4510 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
4511 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
4512 int ret;
4513
4514 // Both sides are a constant, compute the result now.
4515 // First check for a valid combination of types, this is more
4516 // strict than typval_compare().
Bram Moolenaar543e6f32020-07-10 22:45:38 +02004517 if (check_compare_types(type, tv1, tv2) == FAIL)
Bram Moolenaara5565e42020-05-09 15:44:01 +02004518 ret = FAIL;
4519 else
4520 {
4521 ret = typval_compare(tv1, tv2, type, ic);
4522 tv1->v_type = VAR_BOOL;
4523 tv1->vval.v_number = tv1->vval.v_number
4524 ? VVAL_TRUE : VVAL_FALSE;
4525 clear_tv(tv2);
4526 --ppconst->pp_used;
4527 }
4528 return ret;
4529 }
4530
4531 generate_ppconst(cctx, ppconst);
4532 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004533 }
4534
4535 return OK;
4536}
4537
Bram Moolenaar7f141552020-05-09 17:35:53 +02004538static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
4539
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004540/*
4541 * Compile || or &&.
4542 */
4543 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004544compile_and_or(
4545 char_u **arg,
4546 cctx_T *cctx,
4547 char *op,
4548 ppconst_T *ppconst,
4549 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004550{
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004551 char_u *next;
4552 char_u *p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004553 int opchar = *op;
4554
4555 if (p[0] == opchar && p[1] == opchar)
4556 {
4557 garray_T *instr = &cctx->ctx_instr;
4558 garray_T end_ga;
4559
4560 /*
4561 * Repeat until there is no following "||" or "&&"
4562 */
4563 ga_init2(&end_ga, sizeof(int), 10);
4564 while (p[0] == opchar && p[1] == opchar)
4565 {
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004566 if (next != NULL)
4567 {
4568 *arg = next_line_from_context(cctx, TRUE);
4569 p = skipwhite(*arg);
4570 }
4571
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004572 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
4573 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004574 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004575 return FAIL;
4576 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004577
Bram Moolenaara5565e42020-05-09 15:44:01 +02004578 // TODO: use ppconst if the value is a constant
4579 generate_ppconst(cctx, ppconst);
4580
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004581 if (ga_grow(&end_ga, 1) == FAIL)
4582 {
4583 ga_clear(&end_ga);
4584 return FAIL;
4585 }
4586 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
4587 ++end_ga.ga_len;
4588 generate_JUMP(cctx, opchar == '|'
4589 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
4590
4591 // eval the next expression
4592 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004593 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004594 return FAIL;
4595
Bram Moolenaara5565e42020-05-09 15:44:01 +02004596 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
4597 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004598 {
4599 ga_clear(&end_ga);
4600 return FAIL;
4601 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004602
4603 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004604 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004605 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004606
4607 // Fill in the end label in all jumps.
4608 while (end_ga.ga_len > 0)
4609 {
4610 isn_T *isn;
4611
4612 --end_ga.ga_len;
4613 isn = ((isn_T *)instr->ga_data)
4614 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
4615 isn->isn_arg.jump.jump_where = instr->ga_len;
4616 }
4617 ga_clear(&end_ga);
4618 }
4619
4620 return OK;
4621}
4622
4623/*
4624 * expr4a && expr4a && expr4a logical AND
4625 *
4626 * Produces instructions:
4627 * EVAL expr4a Push result of "expr4a"
4628 * JUMP_AND_KEEP_IF_FALSE end
4629 * EVAL expr4b Push result of "expr4b"
4630 * JUMP_AND_KEEP_IF_FALSE end
4631 * EVAL expr4c Push result of "expr4c"
4632 * end:
4633 */
4634 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004635compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004636{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004637 int ppconst_used = ppconst->pp_used;
4638
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004639 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004640 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004641 return FAIL;
4642
4643 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004644 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004645}
4646
4647/*
4648 * expr3a || expr3b || expr3c logical OR
4649 *
4650 * Produces instructions:
4651 * EVAL expr3a Push result of "expr3a"
4652 * JUMP_AND_KEEP_IF_TRUE end
4653 * EVAL expr3b Push result of "expr3b"
4654 * JUMP_AND_KEEP_IF_TRUE end
4655 * EVAL expr3c Push result of "expr3c"
4656 * end:
4657 */
4658 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004659compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004660{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004661 int ppconst_used = ppconst->pp_used;
4662
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004663 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004664 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004665 return FAIL;
4666
4667 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004668 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004669}
4670
4671/*
4672 * Toplevel expression: expr2 ? expr1a : expr1b
4673 *
4674 * Produces instructions:
4675 * EVAL expr2 Push result of "expr"
4676 * JUMP_IF_FALSE alt jump if false
4677 * EVAL expr1a
4678 * JUMP_ALWAYS end
4679 * alt: EVAL expr1b
4680 * end:
4681 */
4682 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004683compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004684{
4685 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004686 int ppconst_used = ppconst->pp_used;
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004687 char_u *next;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004688
Bram Moolenaar61a89812020-05-07 16:58:17 +02004689 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02004690 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004691 return FAIL;
4692
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004693 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004694 if (*p == '?')
4695 {
4696 garray_T *instr = &cctx->ctx_instr;
4697 garray_T *stack = &cctx->ctx_type_stack;
4698 int alt_idx = instr->ga_len;
Bram Moolenaar38041da2020-06-21 22:17:18 +02004699 int end_idx = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004700 isn_T *isn;
Bram Moolenaar38041da2020-06-21 22:17:18 +02004701 type_T *type1 = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004702 type_T *type2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004703 int has_const_expr = FALSE;
4704 int const_value = FALSE;
4705 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004706
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004707 if (next != NULL)
4708 {
4709 *arg = next_line_from_context(cctx, TRUE);
4710 p = skipwhite(*arg);
4711 }
4712
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004713 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4714 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004715 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004716 return FAIL;
4717 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004718
Bram Moolenaara5565e42020-05-09 15:44:01 +02004719 if (ppconst->pp_used == ppconst_used + 1)
4720 {
4721 // the condition is a constant, we know whether the ? or the :
4722 // expression is to be evaluated.
4723 has_const_expr = TRUE;
4724 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
4725 clear_tv(&ppconst->pp_tv[ppconst_used]);
4726 --ppconst->pp_used;
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004727 cctx->ctx_skip = save_skip == SKIP_YES || !const_value
4728 ? SKIP_YES : SKIP_NOT;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004729 }
4730 else
4731 {
4732 generate_ppconst(cctx, ppconst);
4733 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4734 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004735
4736 // evaluate the second expression; any type is accepted
4737 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004738 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004739 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004740 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004741 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004742
Bram Moolenaara5565e42020-05-09 15:44:01 +02004743 if (!has_const_expr)
4744 {
4745 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004746
Bram Moolenaara5565e42020-05-09 15:44:01 +02004747 // remember the type and drop it
4748 --stack->ga_len;
4749 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004750
Bram Moolenaara5565e42020-05-09 15:44:01 +02004751 end_idx = instr->ga_len;
4752 generate_JUMP(cctx, JUMP_ALWAYS, 0);
4753
4754 // jump here from JUMP_IF_FALSE
4755 isn = ((isn_T *)instr->ga_data) + alt_idx;
4756 isn->isn_arg.jump.jump_where = instr->ga_len;
4757 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004758
4759 // Check for the ":".
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004760 p = may_peek_next_line(cctx, *arg, &next);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004761 if (*p != ':')
4762 {
4763 emsg(_(e_missing_colon));
4764 return FAIL;
4765 }
Bram Moolenaar67fbdfe2020-06-23 22:26:05 +02004766 if (next != NULL)
4767 {
4768 *arg = next_line_from_context(cctx, TRUE);
4769 p = skipwhite(*arg);
4770 }
4771
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004772 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4773 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004774 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004775 return FAIL;
4776 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004777
4778 // evaluate the third expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004779 if (has_const_expr)
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004780 cctx->ctx_skip = save_skip == SKIP_YES || const_value
4781 ? SKIP_YES : SKIP_NOT;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004782 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004783 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004784 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004785 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004786 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004787
Bram Moolenaara5565e42020-05-09 15:44:01 +02004788 if (!has_const_expr)
4789 {
4790 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004791
Bram Moolenaara5565e42020-05-09 15:44:01 +02004792 // If the types differ, the result has a more generic type.
4793 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4794 common_type(type1, type2, &type2, cctx->ctx_type_list);
4795
4796 // jump here from JUMP_ALWAYS
4797 isn = ((isn_T *)instr->ga_data) + end_idx;
4798 isn->isn_arg.jump.jump_where = instr->ga_len;
4799 }
4800
4801 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004802 }
4803 return OK;
4804}
4805
4806/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004807 * Toplevel expression.
4808 */
4809 static int
4810compile_expr0(char_u **arg, cctx_T *cctx)
4811{
4812 ppconst_T ppconst;
4813
4814 CLEAR_FIELD(ppconst);
4815 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
4816 {
4817 clear_ppconst(&ppconst);
4818 return FAIL;
4819 }
4820 if (generate_ppconst(cctx, &ppconst) == FAIL)
4821 return FAIL;
4822 return OK;
4823}
4824
4825/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004826 * compile "return [expr]"
4827 */
4828 static char_u *
4829compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
4830{
4831 char_u *p = arg;
4832 garray_T *stack = &cctx->ctx_type_stack;
4833 type_T *stack_type;
4834
4835 if (*p != NUL && *p != '|' && *p != '\n')
4836 {
4837 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02004838 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004839 return NULL;
4840
4841 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4842 if (set_return_type)
4843 cctx->ctx_ufunc->uf_ret_type = stack_type;
Bram Moolenaar05a55512020-07-05 15:52:19 +02004844 else
4845 {
4846 if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
4847 && stack_type->tt_type != VAR_VOID
4848 && stack_type->tt_type != VAR_UNKNOWN)
4849 {
4850 emsg(_("E1096: Returning a value in a function without a return type"));
4851 return NULL;
4852 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02004853 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
4854 cctx, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004855 return NULL;
Bram Moolenaar05a55512020-07-05 15:52:19 +02004856 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004857 }
4858 else
4859 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004860 // "set_return_type" cannot be TRUE, only used for a lambda which
4861 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02004862 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
4863 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004864 {
4865 emsg(_("E1003: Missing return value"));
4866 return NULL;
4867 }
4868
4869 // No argument, return zero.
4870 generate_PUSHNR(cctx, 0);
4871 }
4872
4873 if (generate_instr(cctx, ISN_RETURN) == NULL)
4874 return NULL;
4875
4876 // "return val | endif" is possible
4877 return skipwhite(p);
4878}
4879
4880/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02004881 * Get a line from the compilation context, compatible with exarg_T getline().
4882 * Return a pointer to the line in allocated memory.
4883 * Return NULL for end-of-file or some error.
4884 */
4885 static char_u *
4886exarg_getline(
4887 int c UNUSED,
4888 void *cookie,
4889 int indent UNUSED,
4890 int do_concat UNUSED)
4891{
4892 cctx_T *cctx = (cctx_T *)cookie;
4893
4894 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
4895 {
4896 iemsg("Heredoc got to end");
4897 return NULL;
4898 }
4899 ++cctx->ctx_lnum;
4900 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4901 [cctx->ctx_lnum]);
4902}
4903
4904/*
4905 * Compile a nested :def command.
4906 */
4907 static char_u *
4908compile_nested_function(exarg_T *eap, cctx_T *cctx)
4909{
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004910 int is_global = *eap->arg == 'g' && eap->arg[1] == ':';
Bram Moolenaar04b12692020-05-04 23:24:44 +02004911 char_u *name_start = eap->arg;
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02004912 char_u *name_end = to_name_end(eap->arg, TRUE);
Bram Moolenaareef21022020-08-01 22:16:43 +02004913 char_u *lambda_name;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004914 lvar_T *lvar;
4915 ufunc_T *ufunc;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004916 int r;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004917
Bram Moolenaarbcbf4132020-08-01 22:35:13 +02004918 // Only g:Func() can use a namespace.
4919 if (name_start[1] == ':' && !is_global)
4920 {
4921 semsg(_(e_namespace), name_start);
4922 return NULL;
4923 }
Bram Moolenaareef21022020-08-01 22:16:43 +02004924 if (check_defined(name_start, name_end - name_start, cctx) == FAIL)
4925 return NULL;
4926
Bram Moolenaar04b12692020-05-04 23:24:44 +02004927 eap->arg = name_end;
4928 eap->getline = exarg_getline;
4929 eap->cookie = cctx;
Bram Moolenaar9b68c822020-06-18 19:31:08 +02004930 eap->skip = cctx->ctx_skip == SKIP_YES;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004931 eap->forceit = FALSE;
Bram Moolenaareef21022020-08-01 22:16:43 +02004932 lambda_name = get_lambda_name();
4933 ufunc = def_function(eap, lambda_name);
Bram Moolenaar04b12692020-05-04 23:24:44 +02004934
Bram Moolenaar822ba242020-05-24 23:00:18 +02004935 if (ufunc == NULL)
4936 return NULL;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02004937 if (ufunc->uf_def_status == UF_TO_BE_COMPILED
Bram Moolenaar822ba242020-05-24 23:00:18 +02004938 && compile_def_function(ufunc, TRUE, cctx) == FAIL)
Bram Moolenaar04b12692020-05-04 23:24:44 +02004939 return NULL;
4940
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004941 if (is_global)
4942 {
4943 char_u *func_name = vim_strnsave(name_start + 2,
4944 name_end - name_start - 2);
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004945
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004946 if (func_name == NULL)
4947 r = FAIL;
4948 else
Bram Moolenaareef21022020-08-01 22:16:43 +02004949 r = generate_NEWFUNC(cctx, lambda_name, func_name);
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004950 }
4951 else
4952 {
4953 // Define a local variable for the function reference.
4954 lvar = reserve_local(cctx, name_start, name_end - name_start,
4955 TRUE, ufunc->uf_func_type);
Bram Moolenaareef21022020-08-01 22:16:43 +02004956 if (lvar == NULL)
4957 return NULL;
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004958 if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL)
4959 return NULL;
4960 r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
4961 }
Bram Moolenaar04b12692020-05-04 23:24:44 +02004962
Bram Moolenaar61a89812020-05-07 16:58:17 +02004963 // TODO: warning for trailing text?
Bram Moolenaar38ddf332020-07-31 22:05:04 +02004964 return r == FAIL ? NULL : (char_u *)"";
Bram Moolenaar04b12692020-05-04 23:24:44 +02004965}
4966
4967/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004968 * Return the length of an assignment operator, or zero if there isn't one.
4969 */
4970 int
4971assignment_len(char_u *p, int *heredoc)
4972{
4973 if (*p == '=')
4974 {
4975 if (p[1] == '<' && p[2] == '<')
4976 {
4977 *heredoc = TRUE;
4978 return 3;
4979 }
4980 return 1;
4981 }
4982 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
4983 return 2;
4984 if (STRNCMP(p, "..=", 3) == 0)
4985 return 3;
4986 return 0;
4987}
4988
4989// words that cannot be used as a variable
4990static char *reserved[] = {
4991 "true",
4992 "false",
4993 NULL
4994};
4995
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004996typedef enum {
4997 dest_local,
4998 dest_option,
4999 dest_env,
5000 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02005001 dest_buffer,
5002 dest_window,
5003 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005004 dest_vimvar,
5005 dest_script,
5006 dest_reg,
5007} assign_dest_T;
5008
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005009/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005010 * Generate the load instruction for "name".
5011 */
5012 static void
5013generate_loadvar(
5014 cctx_T *cctx,
5015 assign_dest_T dest,
5016 char_u *name,
5017 lvar_T *lvar,
5018 type_T *type)
5019{
5020 switch (dest)
5021 {
5022 case dest_option:
5023 // TODO: check the option exists
5024 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
5025 break;
5026 case dest_global:
5027 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
5028 break;
5029 case dest_buffer:
5030 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
5031 break;
5032 case dest_window:
5033 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
5034 break;
5035 case dest_tab:
5036 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
5037 break;
5038 case dest_script:
5039 compile_load_scriptvar(cctx,
5040 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
5041 break;
5042 case dest_env:
5043 // Include $ in the name here
5044 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
5045 break;
5046 case dest_reg:
5047 generate_LOAD(cctx, ISN_LOADREG, name[1], NULL, &t_string);
5048 break;
5049 case dest_vimvar:
5050 generate_LOADV(cctx, name + 2, TRUE);
5051 break;
5052 case dest_local:
5053 if (lvar->lv_from_outer)
5054 generate_LOAD(cctx, ISN_LOADOUTER, lvar->lv_idx,
5055 NULL, type);
5056 else
5057 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
5058 break;
5059 }
5060}
5061
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005062 void
5063vim9_declare_error(char_u *name)
5064{
5065 char *scope = "";
5066
5067 switch (*name)
5068 {
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005069 case 'g': scope = _("global"); break;
5070 case 'b': scope = _("buffer"); break;
5071 case 'w': scope = _("window"); break;
5072 case 't': scope = _("tab"); break;
5073 case 'v': scope = "v:"; break;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005074 case '$': semsg(_(e_declare_env_var), name);
5075 return;
5076 case '&': semsg(_("E1052: Cannot declare an option: %s"), name);
5077 return;
5078 case '@': semsg(_("E1066: Cannot declare a register: %s"), name);
5079 return;
Bram Moolenaar7fe87552020-06-21 20:38:28 +02005080 default: return;
Bram Moolenaare55b1c02020-06-21 15:52:59 +02005081 }
5082 semsg(_(e_declare_var), scope, name);
5083}
5084
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005085/*
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005086 * Compile declaration and assignment:
5087 * "let var", "let var = expr", "const var = expr" and "var = expr"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005088 * "arg" points to "var".
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005089 * Return NULL for an error.
5090 * Return "arg" if it does not look like a variable list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005091 */
5092 static char_u *
5093compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
5094{
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005095 char_u *var_start;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005096 char_u *p;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005097 char_u *end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005098 char_u *ret = NULL;
5099 int var_count = 0;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005100 int var_idx;
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005101 int scriptvar_sid = 0;
5102 int scriptvar_idx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005103 int semicolon = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005104 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005105 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005106 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005107 int oplen = 0;
5108 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02005109 type_T *type = &t_any;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005110 type_T *member_type = &t_any;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005111 char_u *name = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005112 char_u *sp;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005113 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005114
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005115 // Skip over the "var" or "[var, var]" to get to any "=".
5116 p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
5117 if (p == NULL)
5118 return *arg == '[' ? arg : NULL;
5119
5120 if (var_count > 0 && is_decl)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005121 {
Bram Moolenaarc7db5772020-07-21 20:55:50 +02005122 // TODO: should we allow this, and figure out type inference from list
5123 // members?
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005124 emsg(_("E1092: Cannot use a list for a declaration"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005125 return NULL;
5126 }
5127
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005128 sp = p;
5129 p = skipwhite(p);
5130 op = p;
5131 oplen = assignment_len(p, &heredoc);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005132
5133 if (var_count > 0 && oplen == 0)
5134 // can be something like "[1, 2]->func()"
5135 return arg;
5136
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005137 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
5138 {
Bram Moolenaarbb1b5e22020-08-05 10:53:21 +02005139 error_white_both(op, oplen);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005140 return NULL;
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02005141 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005142
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005143 if (heredoc)
5144 {
5145 list_T *l;
5146 listitem_T *li;
5147
5148 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02005149 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005150 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02005151 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005152
5153 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02005154 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005155 {
5156 generate_PUSHS(cctx, li->li_tv.vval.v_string);
5157 li->li_tv.vval.v_string = NULL;
5158 }
5159 generate_NEWLIST(cctx, l->lv_len);
5160 type = &t_list_string;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005161 member_type = &t_list_string;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005162 list_free(l);
5163 p += STRLEN(p);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005164 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005165 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005166 else if (var_count > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005167 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005168 // for "[var, var] = expr" evaluate the expression here, loop over the
5169 // list of variables below.
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02005170
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005171 p = skipwhite(op + oplen);
5172 if (compile_expr0(&p, cctx) == FAIL)
5173 return NULL;
5174 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005175
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005176 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005177 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005178 type_T *stacktype;
5179
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005180 stacktype = stack->ga_len == 0 ? &t_void
5181 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005182 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005183 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005184 emsg(_(e_cannot_use_void));
5185 goto theend;
5186 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005187 if (need_type(stacktype, &t_list_any, -1, cctx, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005188 goto theend;
Bram Moolenaare8593122020-07-18 15:17:02 +02005189 // TODO: check the length of a constant list here
Bram Moolenaar9af78762020-06-16 11:34:42 +02005190 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
5191 semicolon);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005192 }
5193 }
5194
5195 /*
5196 * Loop over variables in "[var, var] = expr".
5197 * For "var = expr" and "let var: type" this is done only once.
5198 */
5199 if (var_count > 0)
5200 var_start = skipwhite(arg + 1); // skip over the "["
5201 else
5202 var_start = arg;
5203 for (var_idx = 0; var_idx == 0 || var_idx < var_count; var_idx++)
5204 {
5205 char_u *var_end = skip_var_one(var_start, FALSE);
5206 size_t varlen;
5207 int new_local = FALSE;
5208 int opt_type;
5209 int opt_flags = 0;
5210 assign_dest_T dest = dest_local;
5211 int vimvaridx = -1;
5212 lvar_T *lvar = NULL;
5213 lvar_T arg_lvar;
5214 int has_type = FALSE;
5215 int has_index = FALSE;
5216 int instr_count = -1;
5217
Bram Moolenaar65821722020-08-02 18:58:54 +02005218 if (*var_start == '@')
5219 p = var_start + 2;
5220 else
5221 {
5222 p = (*var_start == '&' || *var_start == '$')
5223 ? var_start + 1 : var_start;
5224 p = to_name_end(p, TRUE);
5225 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005226
5227 // "a: type" is declaring variable "a" with a type, not "a:".
5228 if (is_decl && var_end == var_start + 2 && var_end[-1] == ':')
5229 --var_end;
5230 if (is_decl && p == var_start + 2 && p[-1] == ':')
5231 --p;
5232
5233 varlen = p - var_start;
5234 vim_free(name);
5235 name = vim_strnsave(var_start, varlen);
5236 if (name == NULL)
5237 return NULL;
5238 if (!heredoc)
5239 type = &t_any;
5240
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005241 if (cctx->ctx_skip != SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005242 {
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005243 int declare_error = FALSE;
5244
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005245 if (*var_start == '&')
5246 {
5247 int cc;
5248 long numval;
5249
5250 dest = dest_option;
5251 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005252 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005253 emsg(_(e_const_option));
5254 goto theend;
5255 }
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005256 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005257 p = var_start;
5258 p = find_option_end(&p, &opt_flags);
5259 if (p == NULL)
5260 {
5261 // cannot happen?
5262 emsg(_(e_letunexp));
5263 goto theend;
5264 }
5265 cc = *p;
5266 *p = NUL;
5267 opt_type = get_option_value(var_start + 1, &numval,
5268 NULL, opt_flags);
5269 *p = cc;
5270 if (opt_type == -3)
5271 {
5272 semsg(_(e_unknown_option), var_start);
5273 goto theend;
5274 }
5275 if (opt_type == -2 || opt_type == 0)
5276 type = &t_string;
5277 else
5278 type = &t_number; // both number and boolean option
5279 }
5280 else if (*var_start == '$')
5281 {
5282 dest = dest_env;
5283 type = &t_string;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005284 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005285 }
5286 else if (*var_start == '@')
5287 {
Bram Moolenaar65821722020-08-02 18:58:54 +02005288 if (!valid_yank_reg(var_start[1], FALSE) || var_start[1] == '.')
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005289 {
5290 emsg_invreg(var_start[1]);
5291 goto theend;
5292 }
5293 dest = dest_reg;
5294 type = &t_string;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005295 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005296 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005297 else if (varlen > 1 && STRNCMP(var_start, "g:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005298 {
5299 dest = dest_global;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005300 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005301 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005302 else if (varlen > 1 && STRNCMP(var_start, "b:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005303 {
5304 dest = dest_buffer;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005305 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005306 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005307 else if (varlen > 1 && STRNCMP(var_start, "w:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005308 {
5309 dest = dest_window;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005310 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005311 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005312 else if (varlen > 1 && STRNCMP(var_start, "t:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005313 {
5314 dest = dest_tab;
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005315 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005316 }
Bram Moolenaar33afa242020-07-29 19:18:00 +02005317 else if (varlen > 1 && STRNCMP(var_start, "v:", 2) == 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005318 {
5319 typval_T *vtv;
5320 int di_flags;
5321
5322 vimvaridx = find_vim_var(name + 2, &di_flags);
5323 if (vimvaridx < 0)
5324 {
5325 semsg(_(e_var_notfound), var_start);
5326 goto theend;
5327 }
5328 // We use the current value of "sandbox" here, is that OK?
5329 if (var_check_ro(di_flags, name, FALSE))
5330 goto theend;
5331 dest = dest_vimvar;
5332 vtv = get_vim_var_tv(vimvaridx);
Bram Moolenaar4cdb13c2020-07-22 21:45:14 +02005333 type = typval2type_vimvar(vtv, cctx->ctx_type_list);
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005334 declare_error = is_decl;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005335 }
5336 else
5337 {
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005338 int idx;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005339
5340 for (idx = 0; reserved[idx] != NULL; ++idx)
5341 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005342 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005343 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005344 goto theend;
5345 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005346
5347 lvar = lookup_local(var_start, varlen, cctx);
5348 if (lvar == NULL)
5349 {
5350 CLEAR_FIELD(arg_lvar);
5351 if (lookup_arg(var_start, varlen,
5352 &arg_lvar.lv_idx, &arg_lvar.lv_type,
5353 &arg_lvar.lv_from_outer, cctx) == OK)
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005354 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005355 if (is_decl)
5356 {
5357 semsg(_(e_used_as_arg), name);
5358 goto theend;
5359 }
5360 lvar = &arg_lvar;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02005361 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005362 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005363 if (lvar != NULL)
5364 {
5365 if (is_decl)
5366 {
5367 semsg(_("E1017: Variable already declared: %s"), name);
5368 goto theend;
5369 }
5370 else if (lvar->lv_const)
5371 {
5372 semsg(_("E1018: Cannot assign to a constant: %s"),
5373 name);
5374 goto theend;
5375 }
5376 }
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02005377 else
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005378 {
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02005379 int script_namespace = varlen > 1
5380 && STRNCMP(var_start, "s:", 2) == 0;
5381 int script_var = (script_namespace
5382 ? lookup_script(var_start + 2, varlen - 2)
5383 : lookup_script(var_start, varlen)) == OK;
5384 imported_T *import =
5385 find_imported(var_start, varlen, cctx);
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005386
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02005387 if (script_namespace || script_var || import != NULL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005388 {
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02005389 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
5390
5391 if (is_decl)
5392 {
5393 if (script_namespace)
5394 semsg(_("E1101: Cannot declare a script variable in a function: %s"),
Bram Moolenaar33afa242020-07-29 19:18:00 +02005395 name);
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02005396 else
5397 semsg(_("E1054: Variable already declared in the script: %s"),
5398 name);
5399 goto theend;
5400 }
5401 else if (cctx->ctx_ufunc->uf_script_ctx_version
5402 == SCRIPT_VERSION_VIM9
5403 && script_namespace
5404 && !script_var && import == NULL)
5405 {
5406 semsg(_(e_unknown_var), name);
5407 goto theend;
5408 }
5409
5410 dest = dest_script;
5411
5412 // existing script-local variables should have a type
5413 scriptvar_sid = current_sctx.sc_sid;
5414 if (import != NULL)
5415 scriptvar_sid = import->imp_sid;
5416 scriptvar_idx = get_script_item_idx(scriptvar_sid,
5417 rawname, TRUE);
5418 if (scriptvar_idx >= 0)
5419 {
5420 scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
5421 svar_T *sv =
5422 ((svar_T *)si->sn_var_vals.ga_data)
5423 + scriptvar_idx;
5424 type = sv->sv_type;
5425 }
5426 }
5427 else if (name[1] == ':' && name[2] != NUL)
5428 {
5429 semsg(_("E1082: Cannot use a namespaced variable: %s"),
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005430 name);
5431 goto theend;
5432 }
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02005433 else if (!is_decl)
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005434 {
Bram Moolenaarf9b2b492020-08-05 14:34:14 +02005435 semsg(_(e_unknown_var), name);
5436 goto theend;
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005437 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005438 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005439 }
Bram Moolenaarc2ee44c2020-08-02 16:59:00 +02005440
5441 if (declare_error)
5442 {
5443 vim9_declare_error(name);
5444 goto theend;
5445 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005446 }
5447
5448 // handle "a:name" as a name, not index "name" on "a"
5449 if (varlen > 1 || var_start[varlen] != ':')
5450 p = var_end;
5451
5452 if (dest != dest_option)
5453 {
5454 if (is_decl && *p == ':')
5455 {
5456 // parse optional type: "let var: type = expr"
5457 if (!VIM_ISWHITE(p[1]))
5458 {
5459 semsg(_(e_white_after), ":");
5460 goto theend;
5461 }
5462 p = skipwhite(p + 1);
5463 type = parse_type(&p, cctx->ctx_type_list);
5464 has_type = TRUE;
5465 }
5466 else if (lvar != NULL)
5467 type = lvar->lv_type;
5468 }
5469
5470 if (oplen == 3 && !heredoc && dest != dest_global
5471 && type->tt_type != VAR_STRING
5472 && type->tt_type != VAR_ANY)
5473 {
5474 emsg(_("E1019: Can only concatenate to string"));
5475 goto theend;
5476 }
5477
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005478 if (lvar == NULL && dest == dest_local && cctx->ctx_skip != SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005479 {
5480 if (oplen > 1 && !heredoc)
5481 {
5482 // +=, /=, etc. require an existing variable
5483 semsg(_("E1020: cannot use an operator on a new variable: %s"),
5484 name);
5485 goto theend;
5486 }
5487
5488 // new local variable
5489 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
5490 goto theend;
5491 lvar = reserve_local(cctx, var_start, varlen,
5492 cmdidx == CMD_const, type);
5493 if (lvar == NULL)
5494 goto theend;
5495 new_local = TRUE;
5496 }
5497
5498 member_type = type;
5499 if (var_end > var_start + varlen)
5500 {
5501 // Something follows after the variable: "var[idx]".
5502 if (is_decl)
5503 {
5504 emsg(_("E1087: cannot use an index when declaring a variable"));
5505 goto theend;
5506 }
5507
5508 if (var_start[varlen] == '[')
5509 {
5510 has_index = TRUE;
5511 if (type->tt_member == NULL)
Bram Moolenaar2caa1592020-08-01 15:53:19 +02005512 member_type = &t_any;
5513 else
5514 member_type = type->tt_member;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005515 }
5516 else
5517 {
5518 semsg("Not supported yet: %s", var_start);
5519 goto theend;
5520 }
5521 }
5522 else if (lvar == &arg_lvar)
5523 {
5524 semsg(_("E1090: Cannot assign to argument %s"), name);
5525 goto theend;
5526 }
5527
5528 if (!heredoc)
5529 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005530 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005531 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005532 if (oplen > 0 && var_count == 0)
5533 {
5534 // skip over the "=" and the expression
5535 p = skipwhite(op + oplen);
5536 compile_expr0(&p, cctx);
5537 }
5538 }
5539 else if (oplen > 0)
5540 {
5541 type_T *stacktype;
5542
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005543 // For "var = expr" evaluate the expression.
5544 if (var_count == 0)
5545 {
5546 int r;
5547
5548 // for "+=", "*=", "..=" etc. first load the current value
5549 if (*op != '=')
5550 {
5551 generate_loadvar(cctx, dest, name, lvar, type);
5552
5553 if (has_index)
5554 {
5555 // TODO: get member from list or dict
5556 emsg("Index with operation not supported yet");
5557 goto theend;
5558 }
5559 }
5560
5561 // Compile the expression. Temporarily hide the new local
5562 // variable here, it is not available to this expression.
5563 if (new_local)
5564 --cctx->ctx_locals.ga_len;
5565 instr_count = instr->ga_len;
5566 p = skipwhite(op + oplen);
5567 r = compile_expr0(&p, cctx);
5568 if (new_local)
5569 ++cctx->ctx_locals.ga_len;
5570 if (r == FAIL)
5571 goto theend;
5572 }
Bram Moolenaar9af78762020-06-16 11:34:42 +02005573 else if (semicolon && var_idx == var_count - 1)
5574 {
5575 // For "[var; var] = expr" get the rest of the list
5576 if (generate_SLICE(cctx, var_count - 1) == FAIL)
5577 goto theend;
5578 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005579 else
5580 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005581 // For "[var, var] = expr" get the "var_idx" item from the
5582 // list.
5583 if (generate_GETITEM(cctx, var_idx) == FAIL)
5584 return FAIL;
5585 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005586
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005587 stacktype = stack->ga_len == 0 ? &t_void
Bram Moolenaar6802cce2020-07-19 15:49:49 +02005588 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005589 if (lvar != NULL && (is_decl || !has_type))
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005590 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005591 if (new_local && !has_type)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005592 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005593 if (stacktype->tt_type == VAR_VOID)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005594 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005595 emsg(_(e_cannot_use_void));
5596 goto theend;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005597 }
5598 else
5599 {
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005600 // An empty list or dict has a &t_void member,
5601 // for a variable that implies &t_any.
5602 if (stacktype == &t_list_empty)
5603 lvar->lv_type = &t_list_any;
5604 else if (stacktype == &t_dict_empty)
5605 lvar->lv_type = &t_dict_any;
5606 else
5607 lvar->lv_type = stacktype;
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005608 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005609 }
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005610 else
5611 {
5612 type_T *use_type = lvar->lv_type;
5613
5614 if (has_index)
5615 {
5616 use_type = use_type->tt_member;
5617 if (use_type == NULL)
5618 use_type = &t_void;
5619 }
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005620 if (need_type(stacktype, use_type, -1, cctx, FALSE)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005621 == FAIL)
5622 goto theend;
5623 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005624 }
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005625 else if (*p != '=' && need_type(stacktype, member_type, -1,
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005626 cctx, FALSE) == FAIL)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005627 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005628 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005629 else if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005630 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005631 emsg(_(e_const_req_value));
5632 goto theend;
5633 }
5634 else if (!has_type || dest == dest_option)
5635 {
5636 emsg(_(e_type_req));
5637 goto theend;
5638 }
5639 else
5640 {
5641 // variables are always initialized
5642 if (ga_grow(instr, 1) == FAIL)
5643 goto theend;
5644 switch (member_type->tt_type)
5645 {
5646 case VAR_BOOL:
5647 generate_PUSHBOOL(cctx, VVAL_FALSE);
5648 break;
5649 case VAR_FLOAT:
5650#ifdef FEAT_FLOAT
5651 generate_PUSHF(cctx, 0.0);
5652#endif
5653 break;
5654 case VAR_STRING:
5655 generate_PUSHS(cctx, NULL);
5656 break;
5657 case VAR_BLOB:
5658 generate_PUSHBLOB(cctx, NULL);
5659 break;
5660 case VAR_FUNC:
5661 generate_PUSHFUNC(cctx, NULL, &t_func_void);
5662 break;
5663 case VAR_LIST:
5664 generate_NEWLIST(cctx, 0);
5665 break;
5666 case VAR_DICT:
5667 generate_NEWDICT(cctx, 0);
5668 break;
5669 case VAR_JOB:
5670 generate_PUSHJOB(cctx, NULL);
5671 break;
5672 case VAR_CHANNEL:
5673 generate_PUSHCHANNEL(cctx, NULL);
5674 break;
5675 case VAR_NUMBER:
5676 case VAR_UNKNOWN:
5677 case VAR_ANY:
5678 case VAR_PARTIAL:
5679 case VAR_VOID:
5680 case VAR_SPECIAL: // cannot happen
5681 generate_PUSHNR(cctx, 0);
5682 break;
5683 }
5684 }
5685 if (var_count == 0)
5686 end = p;
5687 }
5688
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005689 // no need to parse more when skipping
Bram Moolenaar9b68c822020-06-18 19:31:08 +02005690 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaar72abcf42020-06-18 18:26:24 +02005691 break;
5692
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005693 if (oplen > 0 && *op != '=')
5694 {
5695 type_T *expected = &t_number;
5696 type_T *stacktype;
5697
5698 // TODO: if type is known use float or any operation
5699
5700 if (*op == '.')
5701 expected = &t_string;
5702 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02005703 if (need_type(stacktype, expected, -1, cctx, FALSE) == FAIL)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005704 goto theend;
5705
5706 if (*op == '.')
5707 generate_instr_drop(cctx, ISN_CONCAT, 1);
5708 else
5709 {
5710 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
5711
5712 if (isn == NULL)
5713 goto theend;
5714 switch (*op)
5715 {
5716 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
5717 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
5718 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
5719 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
5720 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
5721 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005722 }
5723 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005724
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005725 if (has_index)
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005726 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005727 int r;
5728
5729 // Compile the "idx" in "var[idx]".
5730 if (new_local)
5731 --cctx->ctx_locals.ga_len;
5732 p = skipwhite(var_start + varlen + 1);
5733 r = compile_expr0(&p, cctx);
5734 if (new_local)
5735 ++cctx->ctx_locals.ga_len;
5736 if (r == FAIL)
5737 goto theend;
5738 if (*skipwhite(p) != ']')
5739 {
5740 emsg(_(e_missbrac));
5741 goto theend;
5742 }
Bram Moolenaar2caa1592020-08-01 15:53:19 +02005743 if (type == &t_any)
5744 {
5745 type_T *idx_type = ((type_T **)stack->ga_data)[
5746 stack->ga_len - 1];
5747 // Index on variable of unknown type: guess the type from the
5748 // index type: number is dict, otherwise dict.
5749 // TODO: should do the assignment at runtime
5750 if (idx_type->tt_type == VAR_NUMBER)
5751 type = &t_list_any;
5752 else
5753 type = &t_dict_any;
5754 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005755 if (type->tt_type == VAR_DICT
5756 && may_generate_2STRING(-1, cctx) == FAIL)
5757 goto theend;
5758 if (type->tt_type == VAR_LIST
5759 && ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005760 != VAR_NUMBER)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005761 {
5762 emsg(_(e_number_exp));
5763 goto theend;
5764 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005765
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005766 // Load the dict or list. On the stack we then have:
5767 // - value
5768 // - index
5769 // - variable
5770 generate_loadvar(cctx, dest, name, lvar, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005771
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005772 if (type->tt_type == VAR_LIST)
5773 {
5774 if (generate_instr_drop(cctx, ISN_STORELIST, 3) == FAIL)
5775 return FAIL;
5776 }
5777 else if (type->tt_type == VAR_DICT)
5778 {
5779 if (generate_instr_drop(cctx, ISN_STOREDICT, 3) == FAIL)
5780 return FAIL;
5781 }
5782 else
5783 {
5784 emsg(_(e_listreq));
5785 goto theend;
5786 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005787 }
5788 else
5789 {
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005790 switch (dest)
5791 {
5792 case dest_option:
5793 generate_STOREOPT(cctx, name + 1, opt_flags);
5794 break;
5795 case dest_global:
5796 // include g: with the name, easier to execute that way
5797 generate_STORE(cctx, ISN_STOREG, 0, name);
5798 break;
5799 case dest_buffer:
5800 // include b: with the name, easier to execute that way
5801 generate_STORE(cctx, ISN_STOREB, 0, name);
5802 break;
5803 case dest_window:
5804 // include w: with the name, easier to execute that way
5805 generate_STORE(cctx, ISN_STOREW, 0, name);
5806 break;
5807 case dest_tab:
5808 // include t: with the name, easier to execute that way
5809 generate_STORE(cctx, ISN_STORET, 0, name);
5810 break;
5811 case dest_env:
5812 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5813 break;
5814 case dest_reg:
5815 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5816 break;
5817 case dest_vimvar:
5818 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5819 break;
5820 case dest_script:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005821 {
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005822 if (scriptvar_idx < 0)
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005823 {
5824 char_u *name_s = name;
5825
5826 // Include s: in the name for store_var()
5827 if (name[1] != ':')
5828 {
5829 int len = (int)STRLEN(name) + 3;
5830
5831 name_s = alloc(len);
5832 if (name_s == NULL)
5833 name_s = name;
5834 else
5835 vim_snprintf((char *)name_s, len,
5836 "s:%s", name);
5837 }
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005838 generate_OLDSCRIPT(cctx, ISN_STORES, name_s,
5839 scriptvar_sid, type);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005840 if (name_s != name)
5841 vim_free(name_s);
5842 }
5843 else
5844 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
Bram Moolenaar8e4c8c82020-08-01 15:38:38 +02005845 scriptvar_sid, scriptvar_idx, type);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005846 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005847 break;
5848 case dest_local:
5849 if (lvar != NULL)
5850 {
5851 isn_T *isn = ((isn_T *)instr->ga_data)
5852 + instr->ga_len - 1;
5853
5854 // optimization: turn "var = 123" from ISN_PUSHNR +
5855 // ISN_STORE into ISN_STORENR
5856 if (!lvar->lv_from_outer
5857 && instr->ga_len == instr_count + 1
5858 && isn->isn_type == ISN_PUSHNR)
5859 {
5860 varnumber_T val = isn->isn_arg.number;
5861
5862 isn->isn_type = ISN_STORENR;
5863 isn->isn_arg.storenr.stnr_idx = lvar->lv_idx;
5864 isn->isn_arg.storenr.stnr_val = val;
5865 if (stack->ga_len > 0)
5866 --stack->ga_len;
5867 }
5868 else if (lvar->lv_from_outer)
5869 generate_STORE(cctx, ISN_STOREOUTER, lvar->lv_idx,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005870 NULL);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005871 else
5872 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
5873 }
5874 break;
5875 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005876 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005877
5878 if (var_idx + 1 < var_count)
5879 var_start = skipwhite(var_end + 1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005880 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005881
5882 // for "[var, var] = expr" drop the "expr" value
Bram Moolenaar9af78762020-06-16 11:34:42 +02005883 if (var_count > 0 && !semicolon)
5884 {
5885 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5886 goto theend;
5887 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02005888
Bram Moolenaarb2097502020-07-19 17:17:02 +02005889 ret = skipwhite(end);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005890
5891theend:
5892 vim_free(name);
5893 return ret;
5894}
5895
5896/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005897 * Check if "name" can be "unlet".
5898 */
5899 int
5900check_vim9_unlet(char_u *name)
5901{
5902 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
5903 {
5904 semsg(_("E1081: Cannot unlet %s"), name);
5905 return FAIL;
5906 }
5907 return OK;
5908}
5909
5910/*
5911 * Callback passed to ex_unletlock().
5912 */
5913 static int
5914compile_unlet(
5915 lval_T *lvp,
5916 char_u *name_end,
5917 exarg_T *eap,
5918 int deep UNUSED,
5919 void *coookie)
5920{
5921 cctx_T *cctx = coookie;
5922
5923 if (lvp->ll_tv == NULL)
5924 {
5925 char_u *p = lvp->ll_name;
5926 int cc = *name_end;
5927 int ret = OK;
5928
5929 // Normal name. Only supports g:, w:, t: and b: namespaces.
5930 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005931 if (*p == '$')
5932 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
5933 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005934 ret = FAIL;
5935 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005936 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005937
5938 *name_end = cc;
5939 return ret;
5940 }
5941
5942 // TODO: unlet {list}[idx]
5943 // TODO: unlet {dict}[key]
5944 emsg("Sorry, :unlet not fully implemented yet");
5945 return FAIL;
5946}
5947
5948/*
5949 * compile "unlet var", "lock var" and "unlock var"
5950 * "arg" points to "var".
5951 */
5952 static char_u *
5953compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
5954{
5955 char_u *p = arg;
5956
5957 if (eap->cmdidx != CMD_unlet)
5958 {
5959 emsg("Sorry, :lock and unlock not implemented yet");
5960 return NULL;
5961 }
5962
5963 if (*p == '!')
5964 {
5965 p = skipwhite(p + 1);
5966 eap->forceit = TRUE;
5967 }
5968
5969 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
5970 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5971}
5972
5973/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005974 * Compile an :import command.
5975 */
5976 static char_u *
5977compile_import(char_u *arg, cctx_T *cctx)
5978{
Bram Moolenaar1c991142020-07-04 13:15:31 +02005979 return handle_import(arg, &cctx->ctx_imports, 0, NULL, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005980}
5981
5982/*
5983 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
5984 */
5985 static int
5986compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
5987{
5988 garray_T *instr = &cctx->ctx_instr;
5989 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
5990
5991 if (endlabel == NULL)
5992 return FAIL;
5993 endlabel->el_next = *el;
5994 *el = endlabel;
5995 endlabel->el_end_label = instr->ga_len;
5996
5997 generate_JUMP(cctx, when, 0);
5998 return OK;
5999}
6000
6001 static void
6002compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
6003{
6004 garray_T *instr = &cctx->ctx_instr;
6005
6006 while (*el != NULL)
6007 {
6008 endlabel_T *cur = (*el);
6009 isn_T *isn;
6010
6011 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
6012 isn->isn_arg.jump.jump_where = instr->ga_len;
6013 *el = cur->el_next;
6014 vim_free(cur);
6015 }
6016}
6017
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006018 static void
6019compile_free_jump_to_end(endlabel_T **el)
6020{
6021 while (*el != NULL)
6022 {
6023 endlabel_T *cur = (*el);
6024
6025 *el = cur->el_next;
6026 vim_free(cur);
6027 }
6028}
6029
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006030/*
6031 * Create a new scope and set up the generic items.
6032 */
6033 static scope_T *
6034new_scope(cctx_T *cctx, scopetype_T type)
6035{
6036 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
6037
6038 if (scope == NULL)
6039 return NULL;
6040 scope->se_outer = cctx->ctx_scope;
6041 cctx->ctx_scope = scope;
6042 scope->se_type = type;
6043 scope->se_local_count = cctx->ctx_locals.ga_len;
6044 return scope;
6045}
6046
6047/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006048 * Free the current scope and go back to the outer scope.
6049 */
6050 static void
6051drop_scope(cctx_T *cctx)
6052{
6053 scope_T *scope = cctx->ctx_scope;
6054
6055 if (scope == NULL)
6056 {
6057 iemsg("calling drop_scope() without a scope");
6058 return;
6059 }
6060 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006061 switch (scope->se_type)
6062 {
6063 case IF_SCOPE:
6064 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
6065 case FOR_SCOPE:
6066 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
6067 case WHILE_SCOPE:
6068 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
6069 case TRY_SCOPE:
6070 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
6071 case NO_SCOPE:
6072 case BLOCK_SCOPE:
6073 break;
6074 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006075 vim_free(scope);
6076}
6077
6078/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006079 * compile "if expr"
6080 *
6081 * "if expr" Produces instructions:
6082 * EVAL expr Push result of "expr"
6083 * JUMP_IF_FALSE end
6084 * ... body ...
6085 * end:
6086 *
6087 * "if expr | else" Produces instructions:
6088 * EVAL expr Push result of "expr"
6089 * JUMP_IF_FALSE else
6090 * ... body ...
6091 * JUMP_ALWAYS end
6092 * else:
6093 * ... body ...
6094 * end:
6095 *
6096 * "if expr1 | elseif expr2 | else" Produces instructions:
6097 * EVAL expr Push result of "expr"
6098 * JUMP_IF_FALSE elseif
6099 * ... body ...
6100 * JUMP_ALWAYS end
6101 * elseif:
6102 * EVAL expr Push result of "expr"
6103 * JUMP_IF_FALSE else
6104 * ... body ...
6105 * JUMP_ALWAYS end
6106 * else:
6107 * ... body ...
6108 * end:
6109 */
6110 static char_u *
6111compile_if(char_u *arg, cctx_T *cctx)
6112{
6113 char_u *p = arg;
6114 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006115 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006116 scope_T *scope;
Bram Moolenaarefd88552020-06-18 20:50:10 +02006117 skip_T skip_save = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006118 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006119
Bram Moolenaara5565e42020-05-09 15:44:01 +02006120 CLEAR_FIELD(ppconst);
6121 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006122 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006123 clear_ppconst(&ppconst);
6124 return NULL;
6125 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02006126 if (cctx->ctx_skip == SKIP_YES)
6127 clear_ppconst(&ppconst);
6128 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaara5565e42020-05-09 15:44:01 +02006129 {
6130 // The expression results in a constant.
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006131 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? SKIP_NOT : SKIP_YES;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006132 clear_ppconst(&ppconst);
6133 }
6134 else
6135 {
6136 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006137 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006138 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006139 return NULL;
6140 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006141
6142 scope = new_scope(cctx, IF_SCOPE);
6143 if (scope == NULL)
6144 return NULL;
Bram Moolenaarefd88552020-06-18 20:50:10 +02006145 scope->se_skip_save = skip_save;
6146 // "is_had_return" will be reset if any block does not end in :return
6147 scope->se_u.se_if.is_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006148
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006149 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006150 {
6151 // "where" is set when ":elseif", "else" or ":endif" is found
6152 scope->se_u.se_if.is_if_label = instr->ga_len;
6153 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
6154 }
6155 else
6156 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006157
6158 return p;
6159}
6160
6161 static char_u *
6162compile_elseif(char_u *arg, cctx_T *cctx)
6163{
6164 char_u *p = arg;
6165 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006166 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006167 isn_T *isn;
6168 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006169 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006170
6171 if (scope == NULL || scope->se_type != IF_SCOPE)
6172 {
6173 emsg(_(e_elseif_without_if));
6174 return NULL;
6175 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01006176 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006177 if (!cctx->ctx_had_return)
6178 scope->se_u.se_if.is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006179
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006180 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006181 {
6182 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006183 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006184 return NULL;
6185 // previous "if" or "elseif" jumps here
6186 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
6187 isn->isn_arg.jump.jump_where = instr->ga_len;
6188 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006189
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006190 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02006191 CLEAR_FIELD(ppconst);
6192 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006193 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02006194 clear_ppconst(&ppconst);
6195 return NULL;
6196 }
Bram Moolenaarefd88552020-06-18 20:50:10 +02006197 if (scope->se_skip_save == SKIP_YES)
6198 clear_ppconst(&ppconst);
6199 else if (instr->ga_len == instr_count && ppconst.pp_used == 1)
Bram Moolenaar7f141552020-05-09 17:35:53 +02006200 {
6201 // The expression results in a constant.
6202 // TODO: how about nesting?
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006203 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? SKIP_NOT : SKIP_YES;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006204 clear_ppconst(&ppconst);
6205 scope->se_u.se_if.is_if_label = -1;
6206 }
6207 else
6208 {
6209 // Not a constant, generate instructions for the expression.
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006210 cctx->ctx_skip = SKIP_UNKNOWN;
Bram Moolenaar7f141552020-05-09 17:35:53 +02006211 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006212 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006213
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006214 // "where" is set when ":elseif", "else" or ":endif" is found
6215 scope->se_u.se_if.is_if_label = instr->ga_len;
6216 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
6217 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006218
6219 return p;
6220}
6221
6222 static char_u *
6223compile_else(char_u *arg, cctx_T *cctx)
6224{
6225 char_u *p = arg;
6226 garray_T *instr = &cctx->ctx_instr;
6227 isn_T *isn;
6228 scope_T *scope = cctx->ctx_scope;
6229
6230 if (scope == NULL || scope->se_type != IF_SCOPE)
6231 {
6232 emsg(_(e_else_without_if));
6233 return NULL;
6234 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01006235 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006236 if (!cctx->ctx_had_return)
6237 scope->se_u.se_if.is_had_return = FALSE;
6238 scope->se_u.se_if.is_seen_else = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006239
Bram Moolenaarefd88552020-06-18 20:50:10 +02006240 if (scope->se_skip_save != SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006241 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02006242 // jump from previous block to the end, unless the else block is empty
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006243 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006244 {
Bram Moolenaarefd88552020-06-18 20:50:10 +02006245 if (!cctx->ctx_had_return
6246 && compile_jump_to_end(&scope->se_u.se_if.is_end_label,
6247 JUMP_ALWAYS, cctx) == FAIL)
6248 return NULL;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006249 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006250
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006251 if (cctx->ctx_skip == SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02006252 {
6253 if (scope->se_u.se_if.is_if_label >= 0)
6254 {
6255 // previous "if" or "elseif" jumps here
6256 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
6257 isn->isn_arg.jump.jump_where = instr->ga_len;
6258 scope->se_u.se_if.is_if_label = -1;
6259 }
6260 }
6261
Bram Moolenaar280b0dc2020-06-20 13:29:03 +02006262 if (cctx->ctx_skip != SKIP_UNKNOWN)
Bram Moolenaarefd88552020-06-18 20:50:10 +02006263 cctx->ctx_skip = cctx->ctx_skip == SKIP_YES ? SKIP_NOT : SKIP_YES;
6264 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006265
6266 return p;
6267}
6268
6269 static char_u *
6270compile_endif(char_u *arg, cctx_T *cctx)
6271{
6272 scope_T *scope = cctx->ctx_scope;
6273 ifscope_T *ifscope;
6274 garray_T *instr = &cctx->ctx_instr;
6275 isn_T *isn;
6276
6277 if (scope == NULL || scope->se_type != IF_SCOPE)
6278 {
6279 emsg(_(e_endif_without_if));
6280 return NULL;
6281 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006282 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006283 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006284 if (!cctx->ctx_had_return)
6285 ifscope->is_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006286
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006287 if (scope->se_u.se_if.is_if_label >= 0)
6288 {
6289 // previous "if" or "elseif" jumps here
6290 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
6291 isn->isn_arg.jump.jump_where = instr->ga_len;
6292 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006293 // Fill in the "end" label in jumps at the end of the blocks.
6294 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02006295 cctx->ctx_skip = scope->se_skip_save;
6296
6297 // If all the blocks end in :return and there is an :else then the
6298 // had_return flag is set.
6299 cctx->ctx_had_return = ifscope->is_had_return && ifscope->is_seen_else;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006300
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006301 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006302 return arg;
6303}
6304
6305/*
6306 * compile "for var in expr"
6307 *
6308 * Produces instructions:
6309 * PUSHNR -1
6310 * STORE loop-idx Set index to -1
6311 * EVAL expr Push result of "expr"
6312 * top: FOR loop-idx, end Increment index, use list on bottom of stack
6313 * - if beyond end, jump to "end"
6314 * - otherwise get item from list and push it
6315 * STORE var Store item in "var"
6316 * ... body ...
6317 * JUMP top Jump back to repeat
6318 * end: DROP Drop the result of "expr"
6319 *
6320 */
6321 static char_u *
6322compile_for(char_u *arg, cctx_T *cctx)
6323{
6324 char_u *p;
6325 size_t varlen;
6326 garray_T *instr = &cctx->ctx_instr;
6327 garray_T *stack = &cctx->ctx_type_stack;
6328 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006329 lvar_T *loop_lvar; // loop iteration variable
6330 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006331 type_T *vartype;
6332
6333 // TODO: list of variables: "for [key, value] in dict"
6334 // parse "var"
6335 for (p = arg; eval_isnamec1(*p); ++p)
6336 ;
6337 varlen = p - arg;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006338 var_lvar = lookup_local(arg, varlen, cctx);
6339 if (var_lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006340 {
6341 semsg(_("E1023: variable already defined: %s"), arg);
6342 return NULL;
6343 }
6344
6345 // consume "in"
6346 p = skipwhite(p);
6347 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
6348 {
6349 emsg(_(e_missing_in));
6350 return NULL;
6351 }
6352 p = skipwhite(p + 2);
6353
6354
6355 scope = new_scope(cctx, FOR_SCOPE);
6356 if (scope == NULL)
6357 return NULL;
6358
6359 // Reserve a variable to store the loop iteration counter.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006360 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
6361 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006362 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006363 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006364 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006365 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006366 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006367
6368 // Reserve a variable to store "var"
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006369 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
6370 if (var_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006371 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006372 // out of memory or used as an argument
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006373 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006374 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006375 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006376
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006377 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006378
6379 // compile "expr", it remains on the stack until "endfor"
6380 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006381 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006382 {
6383 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006384 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006385 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006386
Bram Moolenaar0ad3e892020-07-05 21:38:11 +02006387 // Now that we know the type of "var", check that it is a list, now or at
6388 // runtime.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006389 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +02006390 if (need_type(vartype, &t_list_any, -1, cctx, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006391 {
Bram Moolenaar25b70c72020-04-01 16:34:17 +02006392 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006393 return NULL;
6394 }
Bram Moolenaar0ad3e892020-07-05 21:38:11 +02006395 if (vartype->tt_type == VAR_LIST && vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006396 var_lvar->lv_type = vartype->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006397
6398 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006399 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006400
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006401 generate_FOR(cctx, loop_lvar->lv_idx);
6402 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006403
6404 return arg;
6405}
6406
6407/*
6408 * compile "endfor"
6409 */
6410 static char_u *
6411compile_endfor(char_u *arg, cctx_T *cctx)
6412{
6413 garray_T *instr = &cctx->ctx_instr;
6414 scope_T *scope = cctx->ctx_scope;
6415 forscope_T *forscope;
6416 isn_T *isn;
6417
6418 if (scope == NULL || scope->se_type != FOR_SCOPE)
6419 {
6420 emsg(_(e_for));
6421 return NULL;
6422 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006423 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006424 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006425 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006426
6427 // At end of ":for" scope jump back to the FOR instruction.
6428 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
6429
6430 // Fill in the "end" label in the FOR statement so it can jump here
6431 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
6432 isn->isn_arg.forloop.for_end = instr->ga_len;
6433
6434 // Fill in the "end" label any BREAK statements
6435 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
6436
6437 // Below the ":for" scope drop the "expr" list from the stack.
6438 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
6439 return NULL;
6440
6441 vim_free(scope);
6442
6443 return arg;
6444}
6445
6446/*
6447 * compile "while expr"
6448 *
6449 * Produces instructions:
6450 * top: EVAL expr Push result of "expr"
6451 * JUMP_IF_FALSE end jump if false
6452 * ... body ...
6453 * JUMP top Jump back to repeat
6454 * end:
6455 *
6456 */
6457 static char_u *
6458compile_while(char_u *arg, cctx_T *cctx)
6459{
6460 char_u *p = arg;
6461 garray_T *instr = &cctx->ctx_instr;
6462 scope_T *scope;
6463
6464 scope = new_scope(cctx, WHILE_SCOPE);
6465 if (scope == NULL)
6466 return NULL;
6467
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006468 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006469
6470 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02006471 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006472 return NULL;
6473
6474 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006475 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006476 JUMP_IF_FALSE, cctx) == FAIL)
6477 return FAIL;
6478
6479 return p;
6480}
6481
6482/*
6483 * compile "endwhile"
6484 */
6485 static char_u *
6486compile_endwhile(char_u *arg, cctx_T *cctx)
6487{
6488 scope_T *scope = cctx->ctx_scope;
6489
6490 if (scope == NULL || scope->se_type != WHILE_SCOPE)
6491 {
6492 emsg(_(e_while));
6493 return NULL;
6494 }
6495 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006496 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006497
6498 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006499 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006500
6501 // Fill in the "end" label in the WHILE statement so it can jump here.
6502 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006503 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006504
6505 vim_free(scope);
6506
6507 return arg;
6508}
6509
6510/*
6511 * compile "continue"
6512 */
6513 static char_u *
6514compile_continue(char_u *arg, cctx_T *cctx)
6515{
6516 scope_T *scope = cctx->ctx_scope;
6517
6518 for (;;)
6519 {
6520 if (scope == NULL)
6521 {
6522 emsg(_(e_continue));
6523 return NULL;
6524 }
6525 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
6526 break;
6527 scope = scope->se_outer;
6528 }
6529
6530 // Jump back to the FOR or WHILE instruction.
6531 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006532 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
6533 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006534 return arg;
6535}
6536
6537/*
6538 * compile "break"
6539 */
6540 static char_u *
6541compile_break(char_u *arg, cctx_T *cctx)
6542{
6543 scope_T *scope = cctx->ctx_scope;
6544 endlabel_T **el;
6545
6546 for (;;)
6547 {
6548 if (scope == NULL)
6549 {
6550 emsg(_(e_break));
6551 return NULL;
6552 }
6553 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
6554 break;
6555 scope = scope->se_outer;
6556 }
6557
6558 // Jump to the end of the FOR or WHILE loop.
6559 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006560 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006561 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006562 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006563 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
6564 return FAIL;
6565
6566 return arg;
6567}
6568
6569/*
6570 * compile "{" start of block
6571 */
6572 static char_u *
6573compile_block(char_u *arg, cctx_T *cctx)
6574{
6575 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
6576 return NULL;
6577 return skipwhite(arg + 1);
6578}
6579
6580/*
6581 * compile end of block: drop one scope
6582 */
6583 static void
6584compile_endblock(cctx_T *cctx)
6585{
6586 scope_T *scope = cctx->ctx_scope;
6587
6588 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006589 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006590 vim_free(scope);
6591}
6592
6593/*
6594 * compile "try"
6595 * Creates a new scope for the try-endtry, pointing to the first catch and
6596 * finally.
6597 * Creates another scope for the "try" block itself.
6598 * TRY instruction sets up exception handling at runtime.
6599 *
6600 * "try"
6601 * TRY -> catch1, -> finally push trystack entry
6602 * ... try block
6603 * "throw {exception}"
6604 * EVAL {exception}
6605 * THROW create exception
6606 * ... try block
6607 * " catch {expr}"
6608 * JUMP -> finally
6609 * catch1: PUSH exeception
6610 * EVAL {expr}
6611 * MATCH
6612 * JUMP nomatch -> catch2
6613 * CATCH remove exception
6614 * ... catch block
6615 * " catch"
6616 * JUMP -> finally
6617 * catch2: CATCH remove exception
6618 * ... catch block
6619 * " finally"
6620 * finally:
6621 * ... finally block
6622 * " endtry"
6623 * ENDTRY pop trystack entry, may rethrow
6624 */
6625 static char_u *
6626compile_try(char_u *arg, cctx_T *cctx)
6627{
6628 garray_T *instr = &cctx->ctx_instr;
6629 scope_T *try_scope;
6630 scope_T *scope;
6631
6632 // scope that holds the jumps that go to catch/finally/endtry
6633 try_scope = new_scope(cctx, TRY_SCOPE);
6634 if (try_scope == NULL)
6635 return NULL;
6636
6637 // "catch" is set when the first ":catch" is found.
6638 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006639 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006640 if (generate_instr(cctx, ISN_TRY) == NULL)
6641 return NULL;
6642
6643 // scope for the try block itself
6644 scope = new_scope(cctx, BLOCK_SCOPE);
6645 if (scope == NULL)
6646 return NULL;
6647
6648 return arg;
6649}
6650
6651/*
6652 * compile "catch {expr}"
6653 */
6654 static char_u *
6655compile_catch(char_u *arg, cctx_T *cctx UNUSED)
6656{
6657 scope_T *scope = cctx->ctx_scope;
6658 garray_T *instr = &cctx->ctx_instr;
6659 char_u *p;
6660 isn_T *isn;
6661
6662 // end block scope from :try or :catch
6663 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6664 compile_endblock(cctx);
6665 scope = cctx->ctx_scope;
6666
6667 // Error if not in a :try scope
6668 if (scope == NULL || scope->se_type != TRY_SCOPE)
6669 {
6670 emsg(_(e_catch));
6671 return NULL;
6672 }
6673
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006674 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006675 {
6676 emsg(_("E1033: catch unreachable after catch-all"));
6677 return NULL;
6678 }
6679
6680 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006681 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006682 JUMP_ALWAYS, cctx) == FAIL)
6683 return NULL;
6684
6685 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006686 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006687 if (isn->isn_arg.try.try_catch == 0)
6688 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006689 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006690 {
6691 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006692 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006693 isn->isn_arg.jump.jump_where = instr->ga_len;
6694 }
6695
6696 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02006697 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006698 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006699 scope->se_u.se_try.ts_caught_all = TRUE;
6700 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006701 }
6702 else
6703 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006704 char_u *end;
6705 char_u *pat;
6706 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006707 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006708 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006709
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006710 // Push v:exception, push {expr} and MATCH
6711 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
6712
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006713 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006714 if (*end != *p)
6715 {
6716 semsg(_("E1067: Separator mismatch: %s"), p);
6717 vim_free(tofree);
6718 return FAIL;
6719 }
6720 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006721 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006722 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006723 len = (int)(end - tofree);
6724 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006725 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006726 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006727 if (pat == NULL)
6728 return FAIL;
6729 if (generate_PUSHS(cctx, pat) == FAIL)
6730 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006731
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006732 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
6733 return NULL;
6734
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006735 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006736 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
6737 return NULL;
6738 }
6739
6740 if (generate_instr(cctx, ISN_CATCH) == NULL)
6741 return NULL;
6742
6743 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
6744 return NULL;
6745 return p;
6746}
6747
6748 static char_u *
6749compile_finally(char_u *arg, cctx_T *cctx)
6750{
6751 scope_T *scope = cctx->ctx_scope;
6752 garray_T *instr = &cctx->ctx_instr;
6753 isn_T *isn;
6754
6755 // end block scope from :try or :catch
6756 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6757 compile_endblock(cctx);
6758 scope = cctx->ctx_scope;
6759
6760 // Error if not in a :try scope
6761 if (scope == NULL || scope->se_type != TRY_SCOPE)
6762 {
6763 emsg(_(e_finally));
6764 return NULL;
6765 }
6766
6767 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006768 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006769 if (isn->isn_arg.try.try_finally != 0)
6770 {
6771 emsg(_(e_finally_dup));
6772 return NULL;
6773 }
6774
6775 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006776 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006777
Bram Moolenaar585fea72020-04-02 22:33:21 +02006778 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006779 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006780 {
6781 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006782 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006783 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaare8593122020-07-18 15:17:02 +02006784 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006785 }
6786
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006787 // TODO: set index in ts_finally_label jumps
6788
6789 return arg;
6790}
6791
6792 static char_u *
6793compile_endtry(char_u *arg, cctx_T *cctx)
6794{
6795 scope_T *scope = cctx->ctx_scope;
6796 garray_T *instr = &cctx->ctx_instr;
6797 isn_T *isn;
6798
6799 // end block scope from :catch or :finally
6800 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6801 compile_endblock(cctx);
6802 scope = cctx->ctx_scope;
6803
6804 // Error if not in a :try scope
6805 if (scope == NULL || scope->se_type != TRY_SCOPE)
6806 {
6807 if (scope == NULL)
6808 emsg(_(e_no_endtry));
6809 else if (scope->se_type == WHILE_SCOPE)
6810 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01006811 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006812 emsg(_(e_endfor));
6813 else
6814 emsg(_(e_endif));
6815 return NULL;
6816 }
6817
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006818 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006819 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
6820 {
6821 emsg(_("E1032: missing :catch or :finally"));
6822 return NULL;
6823 }
6824
6825 // Fill in the "end" label in jumps at the end of the blocks, if not done
6826 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006827 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006828
6829 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaare8593122020-07-18 15:17:02 +02006830 if (isn->isn_arg.try.try_catch == 0)
6831 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006832 if (isn->isn_arg.try.try_finally == 0)
6833 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaare8593122020-07-18 15:17:02 +02006834
6835 if (scope->se_u.se_try.ts_catch_label != 0)
6836 {
6837 // Last catch without match jumps here
6838 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
6839 isn->isn_arg.jump.jump_where = instr->ga_len;
6840 }
6841
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006842 compile_endblock(cctx);
6843
6844 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
6845 return NULL;
6846 return arg;
6847}
6848
6849/*
6850 * compile "throw {expr}"
6851 */
6852 static char_u *
6853compile_throw(char_u *arg, cctx_T *cctx UNUSED)
6854{
6855 char_u *p = skipwhite(arg);
6856
Bram Moolenaara5565e42020-05-09 15:44:01 +02006857 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006858 return NULL;
6859 if (may_generate_2STRING(-1, cctx) == FAIL)
6860 return NULL;
6861 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
6862 return NULL;
6863
6864 return p;
6865}
6866
6867/*
6868 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006869 * compile "echomsg expr"
6870 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01006871 * compile "execute expr"
6872 */
6873 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006874compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006875{
6876 char_u *p = arg;
6877 int count = 0;
6878
6879 for (;;)
6880 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006881 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006882 return NULL;
6883 ++count;
6884 p = skipwhite(p);
6885 if (ends_excmd(*p))
6886 break;
6887 }
6888
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006889 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
6890 generate_ECHO(cctx, cmdidx == CMD_echo, count);
6891 else if (cmdidx == CMD_execute)
6892 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
6893 else if (cmdidx == CMD_echomsg)
6894 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
6895 else
6896 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006897 return p;
6898}
6899
6900/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006901 * A command that is not compiled, execute with legacy code.
6902 */
6903 static char_u *
6904compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
6905{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006906 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006907 int has_expr = FALSE;
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006908 char_u *nextcmd = (char_u *)"";
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006909
Bram Moolenaar9b68c822020-06-18 19:31:08 +02006910 if (cctx->ctx_skip == SKIP_YES)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006911 goto theend;
6912
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006913 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006914 {
6915 long argt = excmd_get_argt(eap->cmdidx);
6916 int usefilter = FALSE;
6917
6918 has_expr = argt & (EX_XFILE | EX_EXPAND);
6919
6920 // If the command can be followed by a bar, find the bar and truncate
6921 // it, so that the following command can be compiled.
6922 // The '|' is overwritten with a NUL, it is put back below.
6923 if ((eap->cmdidx == CMD_write || eap->cmdidx == CMD_read)
6924 && *eap->arg == '!')
6925 // :w !filter or :r !filter or :r! filter
6926 usefilter = TRUE;
6927 if ((argt & EX_TRLBAR) && !usefilter)
6928 {
6929 separate_nextcmd(eap);
6930 if (eap->nextcmd != NULL)
6931 nextcmd = eap->nextcmd;
6932 }
6933 }
6934
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006935 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
6936 {
6937 // expand filename in "syntax include [@group] filename"
6938 has_expr = TRUE;
6939 eap->arg = skipwhite(eap->arg + 7);
6940 if (*eap->arg == '@')
6941 eap->arg = skiptowhite(eap->arg);
6942 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006943
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006944 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006945 {
6946 int count = 0;
6947 char_u *start = skipwhite(line);
6948
6949 // :cmd xxx`=expr1`yyy`=expr2`zzz
6950 // PUSHS ":cmd xxx"
6951 // eval expr1
6952 // PUSHS "yyy"
6953 // eval expr2
6954 // PUSHS "zzz"
6955 // EXECCONCAT 5
6956 for (;;)
6957 {
6958 if (p > start)
6959 {
Bram Moolenaar71ccd032020-06-12 22:59:11 +02006960 generate_PUSHS(cctx, vim_strnsave(start, p - start));
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006961 ++count;
6962 }
6963 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006964 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006965 return NULL;
6966 may_generate_2STRING(-1, cctx);
6967 ++count;
6968 p = skipwhite(p);
6969 if (*p != '`')
6970 {
6971 emsg(_("E1083: missing backtick"));
6972 return NULL;
6973 }
6974 start = p + 1;
6975
6976 p = (char_u *)strstr((char *)start, "`=");
6977 if (p == NULL)
6978 {
6979 if (*skipwhite(start) != NUL)
6980 {
6981 generate_PUSHS(cctx, vim_strsave(start));
6982 ++count;
6983 }
6984 break;
6985 }
6986 }
6987 generate_EXECCONCAT(cctx, count);
6988 }
6989 else
6990 generate_EXEC(cctx, line);
6991
6992theend:
Bram Moolenaare9f262b2020-07-05 14:57:51 +02006993 if (*nextcmd != NUL)
6994 {
6995 // the parser expects a pointer to the bar, put it back
6996 --nextcmd;
6997 *nextcmd = '|';
6998 }
6999
7000 return nextcmd;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007001}
7002
7003/*
Bram Moolenaar09689a02020-05-09 22:50:08 +02007004 * Add a function to the list of :def functions.
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007005 * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet.
Bram Moolenaar09689a02020-05-09 22:50:08 +02007006 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02007007 static int
Bram Moolenaar09689a02020-05-09 22:50:08 +02007008add_def_function(ufunc_T *ufunc)
7009{
7010 dfunc_T *dfunc;
7011
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007012 if (def_functions.ga_len == 0)
7013 {
7014 // The first position is not used, so that a zero uf_dfunc_idx means it
7015 // wasn't set.
7016 if (ga_grow(&def_functions, 1) == FAIL)
7017 return FAIL;
7018 ++def_functions.ga_len;
7019 }
7020
Bram Moolenaar09689a02020-05-09 22:50:08 +02007021 // Add the function to "def_functions".
7022 if (ga_grow(&def_functions, 1) == FAIL)
7023 return FAIL;
7024 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
7025 CLEAR_POINTER(dfunc);
7026 dfunc->df_idx = def_functions.ga_len;
7027 ufunc->uf_dfunc_idx = dfunc->df_idx;
7028 dfunc->df_ufunc = ufunc;
7029 ++def_functions.ga_len;
7030 return OK;
7031}
7032
7033/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007034 * After ex_function() has collected all the function lines: parse and compile
7035 * the lines into instructions.
7036 * Adds the function to "def_functions".
7037 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
7038 * return statement (used for lambda).
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007039 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007040 * This can be used recursively through compile_lambda(), which may reallocate
7041 * "def_functions".
Bram Moolenaar822ba242020-05-24 23:00:18 +02007042 * Returns OK or FAIL.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007043 */
Bram Moolenaar822ba242020-05-24 23:00:18 +02007044 int
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007045compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007046{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007047 char_u *line = NULL;
7048 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007049 char *errormsg = NULL; // error message
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007050 cctx_T cctx;
7051 garray_T *instr;
7052 int called_emsg_before = called_emsg;
7053 int ret = FAIL;
7054 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007055 int do_estack_push;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007056 int emsg_before = called_emsg;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007057 int new_def_function = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007058
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007059 // When using a function that was compiled before: Free old instructions.
7060 // Otherwise add a new entry in "def_functions".
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007061 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007062 {
Bram Moolenaar09689a02020-05-09 22:50:08 +02007063 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7064 + ufunc->uf_dfunc_idx;
Bram Moolenaar09689a02020-05-09 22:50:08 +02007065 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007066 }
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007067 else
7068 {
7069 if (add_def_function(ufunc) == FAIL)
7070 return FAIL;
7071 new_def_function = TRUE;
7072 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007073
Bram Moolenaar985116a2020-07-12 17:31:09 +02007074 ufunc->uf_def_status = UF_COMPILING;
7075
Bram Moolenaara80faa82020-04-12 19:37:17 +02007076 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007077 cctx.ctx_ufunc = ufunc;
7078 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007079 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007080 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
7081 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
7082 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
7083 cctx.ctx_type_list = &ufunc->uf_type_list;
7084 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
7085 instr = &cctx.ctx_instr;
7086
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007087 // Set the context to the function, it may be compiled when called from
7088 // another script. Set the script version to the most modern one.
7089 // The line number will be set in next_line_from_context().
7090 current_sctx = ufunc->uf_script_ctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007091 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
7092
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007093 // Make sure error messages are OK.
7094 do_estack_push = !estack_top_is_ufunc(ufunc, 1);
7095 if (do_estack_push)
7096 estack_push_ufunc(ufunc, 1);
7097
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007098 if (ufunc->uf_def_args.ga_len > 0)
7099 {
7100 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007101 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007102 int i;
7103 char_u *arg;
7104 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
Bram Moolenaarb8070e32020-07-23 20:56:04 +02007105 int did_set_arg_type = FALSE;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007106
7107 // Produce instructions for the default values of optional arguments.
7108 // Store the instruction index in uf_def_arg_idx[] so that we know
7109 // where to start when the function is called, depending on the number
7110 // of arguments.
7111 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
7112 if (ufunc->uf_def_arg_idx == NULL)
7113 goto erret;
7114 for (i = 0; i < count; ++i)
7115 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007116 garray_T *stack = &cctx.ctx_type_stack;
7117 type_T *val_type;
7118 int arg_idx = first_def_arg + i;
7119
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007120 ufunc->uf_def_arg_idx[i] = instr->ga_len;
7121 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaara5565e42020-05-09 15:44:01 +02007122 if (compile_expr0(&arg, &cctx) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007123 goto erret;
7124
7125 // If no type specified use the type of the default value.
7126 // Otherwise check that the default value type matches the
7127 // specified type.
7128 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
7129 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
Bram Moolenaarb8070e32020-07-23 20:56:04 +02007130 {
7131 did_set_arg_type = TRUE;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007132 ufunc->uf_arg_types[arg_idx] = val_type;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02007133 }
Bram Moolenaare30f64b2020-07-15 19:48:20 +02007134 else if (check_type(ufunc->uf_arg_types[arg_idx], val_type, FALSE)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02007135 == FAIL)
7136 {
7137 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
7138 arg_idx + 1);
7139 goto erret;
7140 }
7141
7142 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007143 goto erret;
7144 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007145 ufunc->uf_def_arg_idx[count] = instr->ga_len;
Bram Moolenaarb8070e32020-07-23 20:56:04 +02007146
7147 if (did_set_arg_type)
7148 set_function_type(ufunc);
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01007149 }
7150
7151 /*
7152 * Loop over all the lines of the function and generate instructions.
7153 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007154 for (;;)
7155 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007156 exarg_T ea;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007157 int starts_with_colon = FALSE;
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007158 char_u *cmd;
Bram Moolenaar47e7d702020-07-05 18:18:42 +02007159 int save_msg_scroll = msg_scroll;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007160
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02007161 // Bail out on the first error to avoid a flood of errors and report
7162 // the right line number when inside try/catch.
7163 if (emsg_before != called_emsg)
7164 goto erret;
7165
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007166 if (line != NULL && *line == '|')
7167 // the line continues after a '|'
7168 ++line;
Bram Moolenaara3b7fdc2020-06-21 14:12:17 +02007169 else if (line != NULL && *skipwhite(line) != NUL
Bram Moolenaar7a092242020-04-16 22:10:49 +02007170 && !(*line == '#' && (line == cctx.ctx_line_start
7171 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007172 {
Bram Moolenaardd1a9af2020-07-23 15:38:03 +02007173 semsg(_(e_trailing_arg), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007174 goto erret;
7175 }
7176 else
7177 {
Bram Moolenaar23c55272020-06-21 16:58:13 +02007178 line = next_line_from_context(&cctx, FALSE);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02007179 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007180 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007181 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007182 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007183 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007184
Bram Moolenaara80faa82020-04-12 19:37:17 +02007185 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007186 ea.cmdlinep = &line;
7187 ea.cmd = skipwhite(line);
7188
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007189 // Some things can be recognized by the first character.
7190 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007191 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007192 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007193 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007194 if (ea.cmd[1] != '{')
7195 {
7196 line = (char_u *)"";
7197 continue;
7198 }
7199 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007200
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007201 case '}':
7202 {
7203 // "}" ends a block scope
7204 scopetype_T stype = cctx.ctx_scope == NULL
7205 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007206
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007207 if (stype == BLOCK_SCOPE)
7208 {
7209 compile_endblock(&cctx);
7210 line = ea.cmd;
7211 }
7212 else
7213 {
7214 emsg(_("E1025: using } outside of a block scope"));
7215 goto erret;
7216 }
7217 if (line != NULL)
7218 line = skipwhite(ea.cmd + 1);
7219 continue;
7220 }
7221
7222 case '{':
7223 // "{" starts a block scope
7224 // "{'a': 1}->func() is something else
7225 if (ends_excmd(*skipwhite(ea.cmd + 1)))
7226 {
7227 line = compile_block(ea.cmd, &cctx);
7228 continue;
7229 }
7230 break;
7231
7232 case ':':
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007233 starts_with_colon = TRUE;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02007234 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007235 }
7236
7237 /*
7238 * COMMAND MODIFIERS
7239 */
7240 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
7241 {
7242 if (errormsg != NULL)
7243 goto erret;
7244 // empty line or comment
7245 line = (char_u *)"";
7246 continue;
7247 }
Bram Moolenaar47e7d702020-07-05 18:18:42 +02007248 // TODO: use modifiers in the command
7249 undo_cmdmod(&ea, save_msg_scroll);
Bram Moolenaarb074e8b2020-07-11 13:40:45 +02007250 CLEAR_FIELD(cmdmod);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007251
7252 // Skip ":call" to get to the function name.
7253 if (checkforcmd(&ea.cmd, "call", 3))
7254 ea.cmd = skipwhite(ea.cmd);
7255
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007256 if (!starts_with_colon)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007257 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007258 char_u *pskip;
7259
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007260 // Assuming the command starts with a variable or function name,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007261 // find what follows.
7262 // Skip over "var.member", "var[idx]" and the like.
7263 // Also "&opt = val", "$ENV = val" and "@r = val".
7264 pskip = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007265 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007266 p = to_name_end(pskip, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02007267 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007268 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007269 char_u *var_end;
7270 int oplen;
7271 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007272
Bram Moolenaar65821722020-08-02 18:58:54 +02007273 if (ea.cmd[0] == '@')
7274 var_end = ea.cmd + 2;
7275 else
7276 var_end = find_name_end(pskip, NULL, NULL,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007277 FNE_CHECK_START | FNE_INCL_BR);
7278 oplen = assignment_len(skipwhite(var_end), &heredoc);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007279 if (oplen > 0)
7280 {
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02007281 size_t len = p - ea.cmd;
7282
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007283 // Recognize an assignment if we recognize the variable
7284 // name:
7285 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01007286 // "local = expr" where "local" is a local var.
7287 // "script = expr" where "script" is a script-local var.
7288 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007289 // "&opt = expr"
7290 // "$ENV = expr"
7291 // "@r = expr"
7292 if (*ea.cmd == '&'
7293 || *ea.cmd == '$'
7294 || *ea.cmd == '@'
Bram Moolenaarcb2bdb12020-05-10 22:53:56 +02007295 || ((len) > 2 && ea.cmd[1] == ':')
7296 || lookup_local(ea.cmd, len, &cctx) != NULL
7297 || lookup_arg(ea.cmd, len, NULL, NULL,
7298 NULL, &cctx) == OK
7299 || lookup_script(ea.cmd, len) == OK
7300 || find_imported(ea.cmd, len, &cctx) != NULL)
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007301 {
7302 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02007303 if (line == NULL || line == ea.cmd)
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007304 goto erret;
7305 continue;
7306 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007307 }
7308 }
Bram Moolenaar47a519a2020-06-14 23:05:10 +02007309
7310 if (*ea.cmd == '[')
7311 {
7312 // [var, var] = expr
7313 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
7314 if (line == NULL)
7315 goto erret;
7316 if (line != ea.cmd)
7317 continue;
7318 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007319 }
7320
7321 /*
7322 * COMMAND after range
Bram Moolenaar3d48e252020-07-15 14:15:52 +02007323 * 'text'->func() should not be confused with 'a mark
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007324 */
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007325 cmd = ea.cmd;
Bram Moolenaar3d48e252020-07-15 14:15:52 +02007326 if (*cmd != '\'')
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007327 {
Bram Moolenaar3d48e252020-07-15 14:15:52 +02007328 ea.cmd = skip_range(ea.cmd, NULL);
7329 if (ea.cmd > cmd && !starts_with_colon)
7330 {
7331 emsg(_(e_colon_required));
7332 goto erret;
7333 }
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007334 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007335 p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007336 : (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01007337 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007338
7339 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
7340 {
Bram Moolenaar9b68c822020-06-18 19:31:08 +02007341 if (cctx.ctx_skip == SKIP_YES)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007342 {
7343 line += STRLEN(line);
7344 continue;
7345 }
7346
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007347 // Expression or function call.
Bram Moolenaar007f9d62020-07-06 23:04:49 +02007348 if (ea.cmdidx != CMD_eval)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007349 {
Bram Moolenaar007f9d62020-07-06 23:04:49 +02007350 // CMD_let cannot happen, compile_assignment() above is used
7351 iemsg("Command from find_ex_command() not handled");
7352 goto erret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007353 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007354 }
7355
7356 p = skipwhite(p);
7357
Bram Moolenaar9b68c822020-06-18 19:31:08 +02007358 if (cctx.ctx_skip == SKIP_YES
Bram Moolenaar7e380032020-06-19 22:35:44 +02007359 && ea.cmdidx != CMD_if
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007360 && ea.cmdidx != CMD_elseif
7361 && ea.cmdidx != CMD_else
7362 && ea.cmdidx != CMD_endif)
7363 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007364 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01007365 continue;
7366 }
7367
Bram Moolenaarefd88552020-06-18 20:50:10 +02007368 if (ea.cmdidx != CMD_elseif
7369 && ea.cmdidx != CMD_else
7370 && ea.cmdidx != CMD_endif
7371 && ea.cmdidx != CMD_endfor
7372 && ea.cmdidx != CMD_endwhile
7373 && ea.cmdidx != CMD_catch
7374 && ea.cmdidx != CMD_finally
7375 && ea.cmdidx != CMD_endtry)
7376 {
7377 if (cctx.ctx_had_return)
7378 {
7379 emsg(_("E1095: Unreachable code after :return"));
7380 goto erret;
7381 }
7382 }
7383
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007384 switch (ea.cmdidx)
7385 {
7386 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02007387 ea.arg = p;
7388 line = compile_nested_function(&ea, &cctx);
7389 break;
7390
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007391 case CMD_function:
Bram Moolenaar04b12692020-05-04 23:24:44 +02007392 emsg(_("E1086: Cannot use :function inside :def"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007393 goto erret;
7394
7395 case CMD_return:
7396 line = compile_return(p, set_return_type, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007397 cctx.ctx_had_return = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007398 break;
7399
7400 case CMD_let:
7401 case CMD_const:
7402 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
Bram Moolenaar47a519a2020-06-14 23:05:10 +02007403 if (line == p)
7404 line = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007405 break;
7406
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007407 case CMD_unlet:
7408 case CMD_unlockvar:
7409 case CMD_lockvar:
7410 line = compile_unletlock(p, &ea, &cctx);
7411 break;
7412
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007413 case CMD_import:
7414 line = compile_import(p, &cctx);
7415 break;
7416
7417 case CMD_if:
7418 line = compile_if(p, &cctx);
7419 break;
7420 case CMD_elseif:
7421 line = compile_elseif(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007422 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007423 break;
7424 case CMD_else:
7425 line = compile_else(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007426 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007427 break;
7428 case CMD_endif:
7429 line = compile_endif(p, &cctx);
7430 break;
7431
7432 case CMD_while:
7433 line = compile_while(p, &cctx);
7434 break;
7435 case CMD_endwhile:
7436 line = compile_endwhile(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007437 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007438 break;
7439
7440 case CMD_for:
7441 line = compile_for(p, &cctx);
7442 break;
7443 case CMD_endfor:
7444 line = compile_endfor(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007445 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007446 break;
7447 case CMD_continue:
7448 line = compile_continue(p, &cctx);
7449 break;
7450 case CMD_break:
7451 line = compile_break(p, &cctx);
7452 break;
7453
7454 case CMD_try:
7455 line = compile_try(p, &cctx);
7456 break;
7457 case CMD_catch:
7458 line = compile_catch(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007459 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007460 break;
7461 case CMD_finally:
7462 line = compile_finally(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007463 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007464 break;
7465 case CMD_endtry:
7466 line = compile_endtry(p, &cctx);
Bram Moolenaarefd88552020-06-18 20:50:10 +02007467 cctx.ctx_had_return = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007468 break;
7469 case CMD_throw:
7470 line = compile_throw(p, &cctx);
7471 break;
7472
Bram Moolenaar007f9d62020-07-06 23:04:49 +02007473 case CMD_eval:
7474 if (compile_expr0(&p, &cctx) == FAIL)
7475 goto erret;
7476
7477 // drop the return value
7478 generate_instr_drop(&cctx, ISN_DROP, 1);
7479
7480 line = skipwhite(p);
7481 break;
7482
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007483 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007484 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01007485 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02007486 case CMD_echomsg:
7487 case CMD_echoerr:
7488 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01007489 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007490
Bram Moolenaardf069ee2020-06-22 23:02:51 +02007491 // TODO: other commands with an expression argument
7492
Bram Moolenaarae616492020-07-28 20:07:27 +02007493 case CMD_append:
7494 case CMD_change:
7495 case CMD_insert:
Bram Moolenaarf5a48012020-08-01 17:00:03 +02007496 case CMD_t:
Bram Moolenaarae616492020-07-28 20:07:27 +02007497 case CMD_xit:
7498 not_in_vim9(&ea);
7499 goto erret;
7500
Bram Moolenaar002262f2020-07-08 17:47:57 +02007501 case CMD_SIZE:
7502 semsg(_("E476: Invalid command: %s"), ea.cmd);
7503 goto erret;
7504
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007505 default:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007506 // Not recognized, execute with do_cmdline_cmd().
7507 ea.arg = p;
7508 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007509 break;
7510 }
7511 if (line == NULL)
7512 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02007513 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007514
7515 if (cctx.ctx_type_stack.ga_len < 0)
7516 {
7517 iemsg("Type stack underflow");
7518 goto erret;
7519 }
7520 }
7521
7522 if (cctx.ctx_scope != NULL)
7523 {
7524 if (cctx.ctx_scope->se_type == IF_SCOPE)
7525 emsg(_(e_endif));
7526 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
7527 emsg(_(e_endwhile));
7528 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
7529 emsg(_(e_endfor));
7530 else
7531 emsg(_("E1026: Missing }"));
7532 goto erret;
7533 }
7534
Bram Moolenaarefd88552020-06-18 20:50:10 +02007535 if (!cctx.ctx_had_return)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007536 {
7537 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
7538 {
7539 emsg(_("E1027: Missing return statement"));
7540 goto erret;
7541 }
7542
7543 // Return zero if there is no return at the end.
7544 generate_PUSHNR(&cctx, 0);
7545 generate_instr(&cctx, ISN_RETURN);
7546 }
7547
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007548 {
7549 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7550 + ufunc->uf_dfunc_idx;
7551 dfunc->df_deleted = FALSE;
7552 dfunc->df_instr = instr->ga_data;
7553 dfunc->df_instr_count = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007554 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02007555 dfunc->df_closure_count = cctx.ctx_closure_count;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007556 if (cctx.ctx_outer_used)
7557 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007558 ufunc->uf_def_status = UF_COMPILED;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007559 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007560
7561 ret = OK;
7562
7563erret:
7564 if (ret == FAIL)
7565 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01007566 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02007567 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7568 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007569
7570 for (idx = 0; idx < instr->ga_len; ++idx)
7571 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007572 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01007573
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007574 // If using the last entry in the table and it was added above, we
7575 // might as well remove it.
7576 if (!dfunc->df_deleted && new_def_function
Bram Moolenaar45a15082020-05-25 00:28:33 +02007577 && ufunc->uf_dfunc_idx == def_functions.ga_len - 1)
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007578 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01007579 --def_functions.ga_len;
Bram Moolenaar6c4bfe42020-07-23 18:26:30 +02007580 ufunc->uf_dfunc_idx = 0;
7581 }
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007582 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar20431c92020-03-20 18:39:46 +01007583
Bram Moolenaar3cca2992020-04-02 22:57:36 +02007584 while (cctx.ctx_scope != NULL)
7585 drop_scope(&cctx);
7586
Bram Moolenaar20431c92020-03-20 18:39:46 +01007587 // Don't execute this function body.
7588 ga_clear_strings(&ufunc->uf_lines);
7589
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007590 if (errormsg != NULL)
7591 emsg(errormsg);
7592 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01007593 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007594 }
7595
7596 current_sctx = save_current_sctx;
Bram Moolenaar25e0f582020-05-25 22:36:50 +02007597 if (do_estack_push)
7598 estack_pop();
7599
Bram Moolenaar20431c92020-03-20 18:39:46 +01007600 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02007601 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007602 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar822ba242020-05-24 23:00:18 +02007603 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007604}
7605
Bram Moolenaar6ff71d82020-05-24 23:45:24 +02007606 void
7607set_function_type(ufunc_T *ufunc)
7608{
7609 int varargs = ufunc->uf_va_name != NULL;
7610 int argcount = ufunc->uf_args.ga_len;
7611
7612 // Create a type for the function, with the return type and any
7613 // argument types.
7614 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
7615 // The type is included in "tt_args".
7616 if (argcount > 0 || varargs)
7617 {
7618 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
7619 argcount, &ufunc->uf_type_list);
7620 // Add argument types to the function type.
7621 if (func_type_add_arg_types(ufunc->uf_func_type,
7622 argcount + varargs,
7623 &ufunc->uf_type_list) == FAIL)
7624 return;
7625 ufunc->uf_func_type->tt_argcount = argcount + varargs;
7626 ufunc->uf_func_type->tt_min_argcount =
7627 argcount - ufunc->uf_def_args.ga_len;
7628 if (ufunc->uf_arg_types == NULL)
7629 {
7630 int i;
7631
7632 // lambda does not have argument types.
7633 for (i = 0; i < argcount; ++i)
7634 ufunc->uf_func_type->tt_args[i] = &t_any;
7635 }
7636 else
7637 mch_memmove(ufunc->uf_func_type->tt_args,
7638 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
7639 if (varargs)
7640 {
7641 ufunc->uf_func_type->tt_args[argcount] =
7642 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
7643 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
7644 }
7645 }
7646 else
7647 // No arguments, can use a predefined type.
7648 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
7649 argcount, &ufunc->uf_type_list);
7650}
7651
7652
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007653/*
7654 * Delete an instruction, free what it contains.
7655 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01007656 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007657delete_instr(isn_T *isn)
7658{
7659 switch (isn->isn_type)
7660 {
7661 case ISN_EXEC:
7662 case ISN_LOADENV:
7663 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02007664 case ISN_LOADB:
7665 case ISN_LOADW:
7666 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007667 case ISN_LOADOPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007668 case ISN_STRINGMEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007669 case ISN_PUSHEXC:
7670 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007671 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007672 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02007673 case ISN_STOREB:
7674 case ISN_STOREW:
7675 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007676 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007677 vim_free(isn->isn_arg.string);
7678 break;
7679
7680 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007681 case ISN_STORES:
7682 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007683 break;
7684
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007685 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02007686 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02007687 vim_free(isn->isn_arg.unlet.ul_name);
7688 break;
7689
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007690 case ISN_STOREOPT:
7691 vim_free(isn->isn_arg.storeopt.so_name);
7692 break;
7693
7694 case ISN_PUSHBLOB: // push blob isn_arg.blob
7695 blob_unref(isn->isn_arg.blob);
7696 break;
7697
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007698 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007699#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007700 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007701#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007702 break;
7703
7704 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007705#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007706 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01007707#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01007708 break;
7709
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007710 case ISN_UCALL:
7711 vim_free(isn->isn_arg.ufunc.cuf_name);
7712 break;
7713
Bram Moolenaar221fcc72020-05-05 19:46:20 +02007714 case ISN_FUNCREF:
7715 {
7716 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7717 + isn->isn_arg.funcref.fr_func;
7718 func_ptr_unref(dfunc->df_ufunc);
7719 }
7720 break;
7721
Bram Moolenaar38ddf332020-07-31 22:05:04 +02007722 case ISN_NEWFUNC:
Bram Moolenaarce658352020-07-31 23:47:12 +02007723 {
7724 char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
7725 ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
7726
7727 if (ufunc != NULL)
7728 {
7729 // Clear uf_dfunc_idx so that the function is deleted.
7730 clear_def_function(ufunc);
7731 ufunc->uf_dfunc_idx = 0;
7732 func_ptr_unref(ufunc);
7733 }
7734
7735 vim_free(lambda);
7736 vim_free(isn->isn_arg.newfunc.nf_global);
7737 }
Bram Moolenaar38ddf332020-07-31 22:05:04 +02007738 break;
7739
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007740 case ISN_2BOOL:
7741 case ISN_2STRING:
7742 case ISN_ADDBLOB:
7743 case ISN_ADDLIST:
7744 case ISN_BCALL:
7745 case ISN_CATCH:
7746 case ISN_CHECKNR:
7747 case ISN_CHECKTYPE:
Bram Moolenaar9af78762020-06-16 11:34:42 +02007748 case ISN_CHECKLEN:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007749 case ISN_COMPAREANY:
7750 case ISN_COMPAREBLOB:
7751 case ISN_COMPAREBOOL:
7752 case ISN_COMPAREDICT:
7753 case ISN_COMPAREFLOAT:
7754 case ISN_COMPAREFUNC:
7755 case ISN_COMPARELIST:
7756 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007757 case ISN_COMPARESPECIAL:
7758 case ISN_COMPARESTRING:
7759 case ISN_CONCAT:
7760 case ISN_DCALL:
Bram Moolenaar389df252020-07-09 21:20:47 +02007761 case ISN_SHUFFLE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007762 case ISN_DROP:
7763 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02007764 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007765 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007766 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02007767 case ISN_EXECCONCAT:
7768 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007769 case ISN_FOR:
Bram Moolenaarbf9d8c32020-07-19 17:55:44 +02007770 case ISN_LISTINDEX:
7771 case ISN_STRINDEX:
Bram Moolenaar47a519a2020-06-14 23:05:10 +02007772 case ISN_GETITEM:
Bram Moolenaar9af78762020-06-16 11:34:42 +02007773 case ISN_SLICE:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007774 case ISN_MEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007775 case ISN_JUMP:
7776 case ISN_LOAD:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007777 case ISN_LOADBDICT:
7778 case ISN_LOADGDICT:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02007779 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007780 case ISN_LOADREG:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007781 case ISN_LOADSCRIPT:
7782 case ISN_LOADTDICT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007783 case ISN_LOADV:
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +02007784 case ISN_LOADWDICT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007785 case ISN_NEGATENR:
7786 case ISN_NEWDICT:
7787 case ISN_NEWLIST:
7788 case ISN_OPNR:
7789 case ISN_OPFLOAT:
7790 case ISN_OPANY:
7791 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02007792 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007793 case ISN_PUSHF:
7794 case ISN_PUSHNR:
7795 case ISN_PUSHBOOL:
7796 case ISN_PUSHSPEC:
7797 case ISN_RETURN:
7798 case ISN_STORE:
Bram Moolenaarb68b3462020-05-06 21:06:30 +02007799 case ISN_STOREOUTER:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007800 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007801 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01007802 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007803 case ISN_STORESCRIPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02007804 case ISN_STOREDICT:
7805 case ISN_STORELIST:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007806 case ISN_THROW:
7807 case ISN_TRY:
7808 // nothing allocated
7809 break;
7810 }
7811}
7812
7813/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01007814 * Free all instructions for "dfunc".
7815 */
7816 static void
7817delete_def_function_contents(dfunc_T *dfunc)
7818{
7819 int idx;
7820
7821 ga_clear(&dfunc->df_def_args_isn);
7822
7823 if (dfunc->df_instr != NULL)
7824 {
7825 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
7826 delete_instr(dfunc->df_instr + idx);
7827 VIM_CLEAR(dfunc->df_instr);
7828 }
7829
7830 dfunc->df_deleted = TRUE;
7831}
7832
7833/*
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007834 * When a user function is deleted, clear the contents of any associated def
7835 * function. The position in def_functions can be re-used.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007836 */
7837 void
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007838clear_def_function(ufunc_T *ufunc)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007839{
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007840 if (ufunc->uf_dfunc_idx > 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007841 {
7842 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
7843 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007844
Bram Moolenaar20431c92020-03-20 18:39:46 +01007845 delete_def_function_contents(dfunc);
Bram Moolenaar0cb5bcf2020-06-20 18:19:09 +02007846 ufunc->uf_def_status = UF_NOT_COMPILED;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007847 }
7848}
7849
7850#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01007851/*
7852 * Free all functions defined with ":def".
7853 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007854 void
7855free_def_functions(void)
7856{
Bram Moolenaar20431c92020-03-20 18:39:46 +01007857 int idx;
7858
7859 for (idx = 0; idx < def_functions.ga_len; ++idx)
7860 {
7861 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
7862
7863 delete_def_function_contents(dfunc);
7864 }
7865
7866 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007867}
7868#endif
7869
7870
7871#endif // FEAT_EVAL