blob: 5320cafc686d9150cf906d06e4393743722545e7 [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
26/*
27 * Chain of jump instructions where the end label needs to be set.
28 */
29typedef struct endlabel_S endlabel_T;
30struct endlabel_S {
31 endlabel_T *el_next; // chain end_label locations
32 int el_end_label; // instruction idx where to set end
33};
34
35/*
36 * info specific for the scope of :if / elseif / else
37 */
38typedef struct {
39 int is_if_label; // instruction idx at IF or ELSEIF
40 endlabel_T *is_end_label; // instructions to set end label
41} ifscope_T;
42
43/*
44 * info specific for the scope of :while
45 */
46typedef struct {
47 int ws_top_label; // instruction idx at WHILE
48 endlabel_T *ws_end_label; // instructions to set end
49} whilescope_T;
50
51/*
52 * info specific for the scope of :for
53 */
54typedef struct {
55 int fs_top_label; // instruction idx at FOR
56 endlabel_T *fs_end_label; // break instructions
57} forscope_T;
58
59/*
60 * info specific for the scope of :try
61 */
62typedef struct {
63 int ts_try_label; // instruction idx at TRY
64 endlabel_T *ts_end_label; // jump to :finally or :endtry
65 int ts_catch_label; // instruction idx of last CATCH
66 int ts_caught_all; // "catch" without argument encountered
67} tryscope_T;
68
69typedef enum {
70 NO_SCOPE,
71 IF_SCOPE,
72 WHILE_SCOPE,
73 FOR_SCOPE,
74 TRY_SCOPE,
75 BLOCK_SCOPE
76} scopetype_T;
77
78/*
79 * Info for one scope, pointed to by "ctx_scope".
80 */
81typedef struct scope_S scope_T;
82struct scope_S {
83 scope_T *se_outer; // scope containing this one
84 scopetype_T se_type;
85 int se_local_count; // ctx_locals.ga_len before scope
86 union {
87 ifscope_T se_if;
88 whilescope_T se_while;
89 forscope_T se_for;
90 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +010091 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010092};
93
94/*
95 * Entry for "ctx_locals". Used for arguments and local variables.
96 */
97typedef struct {
98 char_u *lv_name;
99 type_T *lv_type;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200100 int lv_idx; // index of the variable on the stack
101 int lv_from_outer; // when TRUE using ctx_outer scope
102 int lv_const; // when TRUE cannot be assigned to
103 int lv_arg; // when TRUE this is an argument
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100104} lvar_T;
105
106/*
107 * Context for compiling lines of Vim script.
108 * Stores info about the local variables and condition stack.
109 */
110struct cctx_S {
111 ufunc_T *ctx_ufunc; // current function
112 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200113 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100114 garray_T ctx_instr; // generated instructions
115
116 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200117 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100118
Bram Moolenaarbf67ea12020-05-02 17:52:42 +0200119 int ctx_closure_count; // number of closures created in the
120 // function
121
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100122 garray_T ctx_imports; // imported items
123
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100124 int ctx_skip; // when TRUE skip commands, when FALSE skip
125 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100126 scope_T *ctx_scope; // current scope, NULL at toplevel
127
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200128 cctx_T *ctx_outer; // outer scope for lambda or nested
129 // function
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200130 int ctx_outer_used; // var in ctx_outer was used
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200131
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100132 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200133 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100134};
135
136static char e_var_notfound[] = N_("E1001: variable not found: %s");
137static char e_syntax_at[] = N_("E1002: Syntax error at %s");
138
Bram Moolenaar20431c92020-03-20 18:39:46 +0100139static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200140static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
141static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100142
143/*
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200144 * Lookup variable "name" in the local scope and return it.
145 * Return NULL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200147 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100148lookup_local(char_u *name, size_t len, cctx_T *cctx)
149{
150 int idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200151 lvar_T *lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100152
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100153 if (len == 0)
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200154 return NULL;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200155
156 // Find local in current function scope.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100157 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
158 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200159 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100160 if (STRNCMP(name, lvar->lv_name, len) == 0
161 && STRLEN(lvar->lv_name) == len)
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200162 {
163 lvar->lv_from_outer = FALSE;
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200164 return lvar;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200165 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100166 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200167
168 // Find local in outer function scope.
169 if (cctx->ctx_outer != NULL)
170 {
171 lvar = lookup_local(name, len, cctx->ctx_outer);
172 if (lvar != NULL)
173 {
174 // TODO: are there situations we should not mark the outer scope as
175 // used?
176 cctx->ctx_outer_used = TRUE;
177 lvar->lv_from_outer = TRUE;
178 return lvar;
179 }
180 }
181
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200182 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100183}
184
185/*
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200186 * Lookup an argument in the current function and an enclosing function.
187 * Returns the argument index in "idxp"
188 * Returns the argument type in "type"
189 * Sets "gen_load_outer" to TRUE if found in outer scope.
190 * Returns OK when found, FAIL otherwise.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100191 */
192 static int
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200193lookup_arg(
194 char_u *name,
195 size_t len,
196 int *idxp,
197 type_T **type,
198 int *gen_load_outer,
199 cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100200{
201 int idx;
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200202 char_u *va_name;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100203
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100204 if (len == 0)
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200205 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100206 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
207 {
208 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
209
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200210 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
211 {
212 if (idxp != NULL)
213 {
214 // Arguments are located above the frame pointer. One further
215 // if there is a vararg argument
216 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
217 + STACK_FRAME_SIZE)
218 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
219
220 if (cctx->ctx_ufunc->uf_arg_types != NULL)
221 *type = cctx->ctx_ufunc->uf_arg_types[idx];
222 else
223 *type = &t_any;
224 }
225 return OK;
226 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100227 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100228
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200229 va_name = cctx->ctx_ufunc->uf_va_name;
230 if (va_name != NULL
231 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
232 {
233 if (idxp != NULL)
234 {
235 // varargs is always the last argument
236 *idxp = -STACK_FRAME_SIZE - 1;
237 *type = cctx->ctx_ufunc->uf_va_type;
238 }
239 return OK;
240 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100241
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +0200242 if (cctx->ctx_outer != NULL)
243 {
244 // Lookup the name for an argument of the outer function.
245 if (lookup_arg(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
246 == OK)
247 {
248 *gen_load_outer = TRUE;
249 return OK;
250 }
251 }
252
253 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100254}
255
256/*
257 * Lookup a variable in the current script.
258 * Returns OK or FAIL.
259 */
260 static int
261lookup_script(char_u *name, size_t len)
262{
263 int cc;
264 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
265 dictitem_T *di;
266
267 cc = name[len];
268 name[len] = NUL;
269 di = find_var_in_ht(ht, 0, name, TRUE);
270 name[len] = cc;
271 return di == NULL ? FAIL: OK;
272}
273
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100274/*
275 * Check if "p[len]" is already defined, either in script "import_sid" or in
276 * compilation context "cctx".
277 * Return FAIL and give an error if it defined.
278 */
279 int
280check_defined(char_u *p, int len, cctx_T *cctx)
281{
282 if (lookup_script(p, len) == OK
283 || (cctx != NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200284 && (lookup_local(p, len, cctx) != NULL
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100285 || find_imported(p, len, cctx) != NULL)))
286 {
287 semsg("E1073: imported name already defined: %s", p);
288 return FAIL;
289 }
290 return OK;
291}
292
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200293/*
294 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
295 * be freed later.
296 */
297 static type_T *
298alloc_type(garray_T *type_gap)
299{
300 type_T *type;
301
302 if (ga_grow(type_gap, 1) == FAIL)
303 return NULL;
304 type = ALLOC_CLEAR_ONE(type_T);
305 if (type != NULL)
306 {
307 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
308 ++type_gap->ga_len;
309 }
310 return type;
311}
312
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100313 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200314get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100315{
316 type_T *type;
317
318 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200319 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100320 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200321 if (member_type->tt_type == VAR_VOID
322 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100323 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100324 if (member_type->tt_type == VAR_BOOL)
325 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100326 if (member_type->tt_type == VAR_NUMBER)
327 return &t_list_number;
328 if (member_type->tt_type == VAR_STRING)
329 return &t_list_string;
330
331 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200332 type = alloc_type(type_gap);
333 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100334 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100335 type->tt_type = VAR_LIST;
336 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200337 type->tt_argcount = 0;
338 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100339 return type;
340}
341
342 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200343get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100344{
345 type_T *type;
346
347 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200348 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100349 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200350 if (member_type->tt_type == VAR_VOID
351 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100352 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100353 if (member_type->tt_type == VAR_BOOL)
354 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100355 if (member_type->tt_type == VAR_NUMBER)
356 return &t_dict_number;
357 if (member_type->tt_type == VAR_STRING)
358 return &t_dict_string;
359
360 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200361 type = alloc_type(type_gap);
362 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100363 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100364 type->tt_type = VAR_DICT;
365 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200366 type->tt_argcount = 0;
367 type->tt_args = NULL;
368 return type;
369}
370
371/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200372 * Allocate a new type for a function.
373 */
374 static type_T *
375alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
376{
377 type_T *type = alloc_type(type_gap);
378
379 if (type == NULL)
380 return &t_any;
381 type->tt_type = VAR_FUNC;
382 type->tt_member = ret_type;
383 type->tt_argcount = argcount;
384 type->tt_args = NULL;
385 return type;
386}
387
388/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200389 * Get a function type, based on the return type "ret_type".
390 * If "argcount" is -1 or 0 a predefined type can be used.
391 * If "argcount" > 0 always create a new type, so that arguments can be added.
392 */
393 static type_T *
394get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
395{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200396 // recognize commonly used types
397 if (argcount <= 0)
398 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200399 if (ret_type == &t_unknown)
400 {
401 // (argcount == 0) is not possible
402 return &t_func_unknown;
403 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200404 if (ret_type == &t_void)
405 {
406 if (argcount == 0)
407 return &t_func_0_void;
408 else
409 return &t_func_void;
410 }
411 if (ret_type == &t_any)
412 {
413 if (argcount == 0)
414 return &t_func_0_any;
415 else
416 return &t_func_any;
417 }
418 if (ret_type == &t_number)
419 {
420 if (argcount == 0)
421 return &t_func_0_number;
422 else
423 return &t_func_number;
424 }
425 if (ret_type == &t_string)
426 {
427 if (argcount == 0)
428 return &t_func_0_string;
429 else
430 return &t_func_string;
431 }
432 }
433
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200434 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100435}
436
Bram Moolenaara8c17702020-04-01 21:17:24 +0200437/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200438 * For a function type, reserve space for "argcount" argument types (including
439 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200440 */
441 static int
442func_type_add_arg_types(
443 type_T *functype,
444 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200445 garray_T *type_gap)
446{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200447 // To make it easy to free the space needed for the argument types, add the
448 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200449 if (ga_grow(type_gap, 1) == FAIL)
450 return FAIL;
451 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
452 if (functype->tt_args == NULL)
453 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200454 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
455 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200456 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200457 return OK;
458}
459
460/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200461 * Return the type_T for a typval. Only for primitive types.
462 */
463 static type_T *
464typval2type(typval_T *tv)
465{
466 if (tv->v_type == VAR_NUMBER)
467 return &t_number;
468 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200469 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200470 if (tv->v_type == VAR_STRING)
471 return &t_string;
472 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
473 return &t_list_string;
474 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
475 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200476 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200477}
478
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200479 static void
480type_mismatch(type_T *expected, type_T *actual)
481{
482 char *tofree1, *tofree2;
483
484 semsg(_("E1013: type mismatch, expected %s but got %s"),
485 type_name(expected, &tofree1), type_name(actual, &tofree2));
486 vim_free(tofree1);
487 vim_free(tofree2);
488}
489
490 static void
491arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
492{
493 char *tofree1, *tofree2;
494
495 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
496 argidx,
497 type_name(expected, &tofree1), type_name(actual, &tofree2));
498 vim_free(tofree1);
499 vim_free(tofree2);
500}
501
502/*
503 * Check if the expected and actual types match.
504 * Does not allow for assigning "any" to a specific type.
505 */
506 static int
507check_type(type_T *expected, type_T *actual, int give_msg)
508{
509 int ret = OK;
510
511 // When expected is "unknown" we accept any actual type.
512 // When expected is "any" we accept any actual type except "void".
513 if (expected->tt_type != VAR_UNKNOWN
514 && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID))
515
516 {
517 if (expected->tt_type != actual->tt_type)
518 {
519 if (give_msg)
520 type_mismatch(expected, actual);
521 return FAIL;
522 }
523 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
524 {
525 // "unknown" is used for an empty list or dict
526 if (actual->tt_member != &t_unknown)
527 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
528 }
529 else if (expected->tt_type == VAR_FUNC)
530 {
531 if (expected->tt_member != &t_unknown)
532 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
533 if (ret == OK && expected->tt_argcount != -1
534 && (actual->tt_argcount < expected->tt_min_argcount
535 || actual->tt_argcount > expected->tt_argcount))
536 ret = FAIL;
537 }
538 if (ret == FAIL && give_msg)
539 type_mismatch(expected, actual);
540 }
541 return ret;
542}
543
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100544/////////////////////////////////////////////////////////////////////
545// Following generate_ functions expect the caller to call ga_grow().
546
Bram Moolenaar080457c2020-03-03 21:53:32 +0100547#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
548#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
549
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100550/*
551 * Generate an instruction without arguments.
552 * Returns a pointer to the new instruction, NULL if failed.
553 */
554 static isn_T *
555generate_instr(cctx_T *cctx, isntype_T isn_type)
556{
557 garray_T *instr = &cctx->ctx_instr;
558 isn_T *isn;
559
Bram Moolenaar080457c2020-03-03 21:53:32 +0100560 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100561 if (ga_grow(instr, 1) == FAIL)
562 return NULL;
563 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
564 isn->isn_type = isn_type;
565 isn->isn_lnum = cctx->ctx_lnum + 1;
566 ++instr->ga_len;
567
568 return isn;
569}
570
571/*
572 * Generate an instruction without arguments.
573 * "drop" will be removed from the stack.
574 * Returns a pointer to the new instruction, NULL if failed.
575 */
576 static isn_T *
577generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
578{
579 garray_T *stack = &cctx->ctx_type_stack;
580
Bram Moolenaar080457c2020-03-03 21:53:32 +0100581 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100582 stack->ga_len -= drop;
583 return generate_instr(cctx, isn_type);
584}
585
586/*
587 * Generate instruction "isn_type" and put "type" on the type stack.
588 */
589 static isn_T *
590generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
591{
592 isn_T *isn;
593 garray_T *stack = &cctx->ctx_type_stack;
594
595 if ((isn = generate_instr(cctx, isn_type)) == NULL)
596 return NULL;
597
598 if (ga_grow(stack, 1) == FAIL)
599 return NULL;
600 ((type_T **)stack->ga_data)[stack->ga_len] = type;
601 ++stack->ga_len;
602
603 return isn;
604}
605
606/*
607 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
608 */
609 static int
610may_generate_2STRING(int offset, cctx_T *cctx)
611{
612 isn_T *isn;
613 garray_T *stack = &cctx->ctx_type_stack;
614 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
615
616 if ((*type)->tt_type == VAR_STRING)
617 return OK;
618 *type = &t_string;
619
620 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
621 return FAIL;
622 isn->isn_arg.number = offset;
623
624 return OK;
625}
626
627 static int
628check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
629{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200630 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100631 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200632 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100633 {
634 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100635 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100636 else
637 semsg(_("E1036: %c requires number or float arguments"), *op);
638 return FAIL;
639 }
640 return OK;
641}
642
643/*
644 * Generate an instruction with two arguments. The instruction depends on the
645 * type of the arguments.
646 */
647 static int
648generate_two_op(cctx_T *cctx, char_u *op)
649{
650 garray_T *stack = &cctx->ctx_type_stack;
651 type_T *type1;
652 type_T *type2;
653 vartype_T vartype;
654 isn_T *isn;
655
Bram Moolenaar080457c2020-03-03 21:53:32 +0100656 RETURN_OK_IF_SKIP(cctx);
657
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100658 // Get the known type of the two items on the stack. If they are matching
659 // use a type-specific instruction. Otherwise fall back to runtime type
660 // checking.
661 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
662 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200663 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100664 if (type1->tt_type == type2->tt_type
665 && (type1->tt_type == VAR_NUMBER
666 || type1->tt_type == VAR_LIST
667#ifdef FEAT_FLOAT
668 || type1->tt_type == VAR_FLOAT
669#endif
670 || type1->tt_type == VAR_BLOB))
671 vartype = type1->tt_type;
672
673 switch (*op)
674 {
675 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200676 && type1->tt_type != VAR_ANY
677 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100678 && check_number_or_float(
679 type1->tt_type, type2->tt_type, op) == FAIL)
680 return FAIL;
681 isn = generate_instr_drop(cctx,
682 vartype == VAR_NUMBER ? ISN_OPNR
683 : vartype == VAR_LIST ? ISN_ADDLIST
684 : vartype == VAR_BLOB ? ISN_ADDBLOB
685#ifdef FEAT_FLOAT
686 : vartype == VAR_FLOAT ? ISN_OPFLOAT
687#endif
688 : ISN_OPANY, 1);
689 if (isn != NULL)
690 isn->isn_arg.op.op_type = EXPR_ADD;
691 break;
692
693 case '-':
694 case '*':
695 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
696 op) == FAIL)
697 return FAIL;
698 if (vartype == VAR_NUMBER)
699 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
700#ifdef FEAT_FLOAT
701 else if (vartype == VAR_FLOAT)
702 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
703#endif
704 else
705 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
706 if (isn != NULL)
707 isn->isn_arg.op.op_type = *op == '*'
708 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
709 break;
710
Bram Moolenaar4c683752020-04-05 21:38:23 +0200711 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100712 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200713 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100714 && type2->tt_type != VAR_NUMBER))
715 {
716 emsg(_("E1035: % requires number arguments"));
717 return FAIL;
718 }
719 isn = generate_instr_drop(cctx,
720 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
721 if (isn != NULL)
722 isn->isn_arg.op.op_type = EXPR_REM;
723 break;
724 }
725
726 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200727 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100728 {
729 type_T *type = &t_any;
730
731#ifdef FEAT_FLOAT
732 // float+number and number+float results in float
733 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
734 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
735 type = &t_float;
736#endif
737 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
738 }
739
740 return OK;
741}
742
743/*
Bram Moolenaara5565e42020-05-09 15:44:01 +0200744 * Get the instruction to use for comparing "type1" with "type2"
745 * Return ISN_DROP when failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100746 */
Bram Moolenaara5565e42020-05-09 15:44:01 +0200747 static isntype_T
748get_compare_isn(exptype_T exptype, vartype_T type1, vartype_T type2)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100749{
750 isntype_T isntype = ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100751
Bram Moolenaar4c683752020-04-05 21:38:23 +0200752 if (type1 == VAR_UNKNOWN)
753 type1 = VAR_ANY;
754 if (type2 == VAR_UNKNOWN)
755 type2 = VAR_ANY;
756
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100757 if (type1 == type2)
758 {
759 switch (type1)
760 {
761 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
762 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
763 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
764 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
765 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
766 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
767 case VAR_LIST: isntype = ISN_COMPARELIST; break;
768 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
769 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100770 default: isntype = ISN_COMPAREANY; break;
771 }
772 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200773 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100774 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
775 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
776 isntype = ISN_COMPAREANY;
777
778 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
779 && (isntype == ISN_COMPAREBOOL
780 || isntype == ISN_COMPARESPECIAL
781 || isntype == ISN_COMPARENR
782 || isntype == ISN_COMPAREFLOAT))
783 {
784 semsg(_("E1037: Cannot use \"%s\" with %s"),
785 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200786 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100787 }
788 if (isntype == ISN_DROP
789 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
790 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
791 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
792 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
793 && exptype != EXPR_IS && exptype != EXPR_ISNOT
794 && (type1 == VAR_BLOB || type2 == VAR_BLOB
795 || type1 == VAR_LIST || type2 == VAR_LIST))))
796 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100797 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100798 vartype_name(type1), vartype_name(type2));
Bram Moolenaara5565e42020-05-09 15:44:01 +0200799 return ISN_DROP;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100800 }
Bram Moolenaara5565e42020-05-09 15:44:01 +0200801 return isntype;
802}
803
804/*
805 * Generate an ISN_COMPARE* instruction with a boolean result.
806 */
807 static int
808generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
809{
810 isntype_T isntype;
811 isn_T *isn;
812 garray_T *stack = &cctx->ctx_type_stack;
813 vartype_T type1;
814 vartype_T type2;
815
816 RETURN_OK_IF_SKIP(cctx);
817
818 // Get the known type of the two items on the stack. If they are matching
819 // use a type-specific instruction. Otherwise fall back to runtime type
820 // checking.
821 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
822 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
823 isntype = get_compare_isn(exptype, type1, type2);
824 if (isntype == ISN_DROP)
825 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100826
827 if ((isn = generate_instr(cctx, isntype)) == NULL)
828 return FAIL;
829 isn->isn_arg.op.op_type = exptype;
830 isn->isn_arg.op.op_ic = ic;
831
832 // takes two arguments, puts one bool back
833 if (stack->ga_len >= 2)
834 {
835 --stack->ga_len;
836 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
837 }
838
839 return OK;
840}
841
842/*
843 * Generate an ISN_2BOOL instruction.
844 */
845 static int
846generate_2BOOL(cctx_T *cctx, int invert)
847{
848 isn_T *isn;
849 garray_T *stack = &cctx->ctx_type_stack;
850
Bram Moolenaar080457c2020-03-03 21:53:32 +0100851 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100852 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
853 return FAIL;
854 isn->isn_arg.number = invert;
855
856 // type becomes bool
857 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
858
859 return OK;
860}
861
862 static int
863generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
864{
865 isn_T *isn;
866 garray_T *stack = &cctx->ctx_type_stack;
867
Bram Moolenaar080457c2020-03-03 21:53:32 +0100868 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100869 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
870 return FAIL;
Bram Moolenaar939b5db2020-04-28 22:49:08 +0200871 // TODO: whole type, e.g. for a function also arg and return types
872 isn->isn_arg.type.ct_type = vartype->tt_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100873 isn->isn_arg.type.ct_off = offset;
874
875 // type becomes vartype
Bram Moolenaar5adc55c2020-05-02 23:12:58 +0200876 ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100877
878 return OK;
879}
880
881/*
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +0200882 * Check that
883 * - "actual" is "expected" type or
884 * - "actual" is a type that can be "expected" type: add a runtime check; or
885 * - return FAIL.
886 */
887 static int
888need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
889{
890 if (check_type(expected, actual, FALSE) == OK)
891 return OK;
892 if (actual->tt_type != VAR_ANY
893 && actual->tt_type != VAR_UNKNOWN
894 && !(actual->tt_type == VAR_FUNC
895 && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
896 {
897 type_mismatch(expected, actual);
898 return FAIL;
899 }
900 generate_TYPECHECK(cctx, expected, offset);
901 return OK;
902}
903
904/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100905 * Generate an ISN_PUSHNR instruction.
906 */
907 static int
908generate_PUSHNR(cctx_T *cctx, varnumber_T number)
909{
910 isn_T *isn;
911
Bram Moolenaar080457c2020-03-03 21:53:32 +0100912 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100913 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
914 return FAIL;
915 isn->isn_arg.number = number;
916
917 return OK;
918}
919
920/*
921 * Generate an ISN_PUSHBOOL instruction.
922 */
923 static int
924generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
925{
926 isn_T *isn;
927
Bram Moolenaar080457c2020-03-03 21:53:32 +0100928 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100929 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
930 return FAIL;
931 isn->isn_arg.number = number;
932
933 return OK;
934}
935
936/*
937 * Generate an ISN_PUSHSPEC instruction.
938 */
939 static int
940generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
941{
942 isn_T *isn;
943
Bram Moolenaar080457c2020-03-03 21:53:32 +0100944 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100945 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
946 return FAIL;
947 isn->isn_arg.number = number;
948
949 return OK;
950}
951
952#ifdef FEAT_FLOAT
953/*
954 * Generate an ISN_PUSHF instruction.
955 */
956 static int
957generate_PUSHF(cctx_T *cctx, float_T fnumber)
958{
959 isn_T *isn;
960
Bram Moolenaar080457c2020-03-03 21:53:32 +0100961 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100962 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
963 return FAIL;
964 isn->isn_arg.fnumber = fnumber;
965
966 return OK;
967}
968#endif
969
970/*
971 * Generate an ISN_PUSHS instruction.
972 * Consumes "str".
973 */
974 static int
975generate_PUSHS(cctx_T *cctx, char_u *str)
976{
977 isn_T *isn;
978
Bram Moolenaar080457c2020-03-03 21:53:32 +0100979 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100980 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
981 return FAIL;
982 isn->isn_arg.string = str;
983
984 return OK;
985}
986
987/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100988 * Generate an ISN_PUSHCHANNEL instruction.
989 * Consumes "channel".
990 */
991 static int
992generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
993{
994 isn_T *isn;
995
Bram Moolenaar080457c2020-03-03 21:53:32 +0100996 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100997 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
998 return FAIL;
999 isn->isn_arg.channel = channel;
1000
1001 return OK;
1002}
1003
1004/*
1005 * Generate an ISN_PUSHJOB instruction.
1006 * Consumes "job".
1007 */
1008 static int
1009generate_PUSHJOB(cctx_T *cctx, job_T *job)
1010{
1011 isn_T *isn;
1012
Bram Moolenaar080457c2020-03-03 21:53:32 +01001013 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01001014 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001015 return FAIL;
1016 isn->isn_arg.job = job;
1017
1018 return OK;
1019}
1020
1021/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001022 * Generate an ISN_PUSHBLOB instruction.
1023 * Consumes "blob".
1024 */
1025 static int
1026generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
1027{
1028 isn_T *isn;
1029
Bram Moolenaar080457c2020-03-03 21:53:32 +01001030 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001031 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
1032 return FAIL;
1033 isn->isn_arg.blob = blob;
1034
1035 return OK;
1036}
1037
1038/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001039 * Generate an ISN_PUSHFUNC instruction with name "name".
1040 * Consumes "name".
1041 */
1042 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001043generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001044{
1045 isn_T *isn;
1046
Bram Moolenaar080457c2020-03-03 21:53:32 +01001047 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001048 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +01001049 return FAIL;
1050 isn->isn_arg.string = name;
1051
1052 return OK;
1053}
1054
1055/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001056 * Generate an ISN_STORE instruction.
1057 */
1058 static int
1059generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
1060{
1061 isn_T *isn;
1062
Bram Moolenaar080457c2020-03-03 21:53:32 +01001063 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001064 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
1065 return FAIL;
1066 if (name != NULL)
1067 isn->isn_arg.string = vim_strsave(name);
1068 else
1069 isn->isn_arg.number = idx;
1070
1071 return OK;
1072}
1073
1074/*
1075 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
1076 */
1077 static int
1078generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
1079{
1080 isn_T *isn;
1081
Bram Moolenaar080457c2020-03-03 21:53:32 +01001082 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001083 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
1084 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +01001085 isn->isn_arg.storenr.stnr_idx = idx;
1086 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001087
1088 return OK;
1089}
1090
1091/*
1092 * Generate an ISN_STOREOPT instruction
1093 */
1094 static int
1095generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
1096{
1097 isn_T *isn;
1098
Bram Moolenaar080457c2020-03-03 21:53:32 +01001099 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001100 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
1101 return FAIL;
1102 isn->isn_arg.storeopt.so_name = vim_strsave(name);
1103 isn->isn_arg.storeopt.so_flags = opt_flags;
1104
1105 return OK;
1106}
1107
1108/*
1109 * Generate an ISN_LOAD or similar instruction.
1110 */
1111 static int
1112generate_LOAD(
1113 cctx_T *cctx,
1114 isntype_T isn_type,
1115 int idx,
1116 char_u *name,
1117 type_T *type)
1118{
1119 isn_T *isn;
1120
Bram Moolenaar080457c2020-03-03 21:53:32 +01001121 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001122 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
1123 return FAIL;
1124 if (name != NULL)
1125 isn->isn_arg.string = vim_strsave(name);
1126 else
1127 isn->isn_arg.number = idx;
1128
1129 return OK;
1130}
1131
1132/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001133 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001134 */
1135 static int
1136generate_LOADV(
1137 cctx_T *cctx,
1138 char_u *name,
1139 int error)
1140{
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001141 int di_flags;
1142 int vidx = find_vim_var(name, &di_flags);
1143 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001144
Bram Moolenaar080457c2020-03-03 21:53:32 +01001145 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001146 if (vidx < 0)
1147 {
1148 if (error)
1149 semsg(_(e_var_notfound), name);
1150 return FAIL;
1151 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001152 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001153
Bram Moolenaar5da356e2020-04-09 19:34:43 +02001154 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001155}
1156
1157/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001158 * Generate an ISN_UNLET instruction.
1159 */
1160 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001161generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001162{
1163 isn_T *isn;
1164
1165 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001166 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001167 return FAIL;
1168 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1169 isn->isn_arg.unlet.ul_forceit = forceit;
1170
1171 return OK;
1172}
1173
1174/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001175 * Generate an ISN_LOADS instruction.
1176 */
1177 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001178generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001179 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001180 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001181 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001182 int sid,
1183 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001184{
1185 isn_T *isn;
1186
Bram Moolenaar080457c2020-03-03 21:53:32 +01001187 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001188 if (isn_type == ISN_LOADS)
1189 isn = generate_instr_type(cctx, isn_type, type);
1190 else
1191 isn = generate_instr_drop(cctx, isn_type, 1);
1192 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001193 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001194 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1195 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001196
1197 return OK;
1198}
1199
1200/*
1201 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1202 */
1203 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001204generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001205 cctx_T *cctx,
1206 isntype_T isn_type,
1207 int sid,
1208 int idx,
1209 type_T *type)
1210{
1211 isn_T *isn;
1212
Bram Moolenaar080457c2020-03-03 21:53:32 +01001213 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001214 if (isn_type == ISN_LOADSCRIPT)
1215 isn = generate_instr_type(cctx, isn_type, type);
1216 else
1217 isn = generate_instr_drop(cctx, isn_type, 1);
1218 if (isn == NULL)
1219 return FAIL;
1220 isn->isn_arg.script.script_sid = sid;
1221 isn->isn_arg.script.script_idx = idx;
1222 return OK;
1223}
1224
1225/*
1226 * Generate an ISN_NEWLIST instruction.
1227 */
1228 static int
1229generate_NEWLIST(cctx_T *cctx, int count)
1230{
1231 isn_T *isn;
1232 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001233 type_T *type;
1234 type_T *member;
1235
Bram Moolenaar080457c2020-03-03 21:53:32 +01001236 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001237 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1238 return FAIL;
1239 isn->isn_arg.number = count;
1240
1241 // drop the value types
1242 stack->ga_len -= count;
1243
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001244 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001245 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001246 if (count > 0)
1247 member = ((type_T **)stack->ga_data)[stack->ga_len];
1248 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001249 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001250 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001251
1252 // add the list type to the type stack
1253 if (ga_grow(stack, 1) == FAIL)
1254 return FAIL;
1255 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1256 ++stack->ga_len;
1257
1258 return OK;
1259}
1260
1261/*
1262 * Generate an ISN_NEWDICT instruction.
1263 */
1264 static int
1265generate_NEWDICT(cctx_T *cctx, int count)
1266{
1267 isn_T *isn;
1268 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001269 type_T *type;
1270 type_T *member;
1271
Bram Moolenaar080457c2020-03-03 21:53:32 +01001272 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001273 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1274 return FAIL;
1275 isn->isn_arg.number = count;
1276
1277 // drop the key and value types
1278 stack->ga_len -= 2 * count;
1279
Bram Moolenaar436472f2020-02-20 22:54:43 +01001280 // Use the first value type for the list member type. Use "void" for an
1281 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001282 if (count > 0)
1283 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1284 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001285 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001286 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001287
1288 // add the dict type to the type stack
1289 if (ga_grow(stack, 1) == FAIL)
1290 return FAIL;
1291 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1292 ++stack->ga_len;
1293
1294 return OK;
1295}
1296
1297/*
1298 * Generate an ISN_FUNCREF instruction.
1299 */
1300 static int
1301generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1302{
1303 isn_T *isn;
1304 garray_T *stack = &cctx->ctx_type_stack;
1305
Bram Moolenaar080457c2020-03-03 21:53:32 +01001306 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001307 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1308 return FAIL;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02001309 isn->isn_arg.funcref.fr_func = dfunc_idx;
1310 isn->isn_arg.funcref.fr_var_idx = cctx->ctx_closure_count++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001311
1312 if (ga_grow(stack, 1) == FAIL)
1313 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001314 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001315 // TODO: argument and return types
1316 ++stack->ga_len;
1317
1318 return OK;
1319}
1320
1321/*
1322 * Generate an ISN_JUMP instruction.
1323 */
1324 static int
1325generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1326{
1327 isn_T *isn;
1328 garray_T *stack = &cctx->ctx_type_stack;
1329
Bram Moolenaar080457c2020-03-03 21:53:32 +01001330 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001331 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1332 return FAIL;
1333 isn->isn_arg.jump.jump_when = when;
1334 isn->isn_arg.jump.jump_where = where;
1335
1336 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1337 --stack->ga_len;
1338
1339 return OK;
1340}
1341
1342 static int
1343generate_FOR(cctx_T *cctx, int loop_idx)
1344{
1345 isn_T *isn;
1346 garray_T *stack = &cctx->ctx_type_stack;
1347
Bram Moolenaar080457c2020-03-03 21:53:32 +01001348 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001349 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1350 return FAIL;
1351 isn->isn_arg.forloop.for_idx = loop_idx;
1352
1353 if (ga_grow(stack, 1) == FAIL)
1354 return FAIL;
1355 // type doesn't matter, will be stored next
1356 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1357 ++stack->ga_len;
1358
1359 return OK;
1360}
1361
1362/*
1363 * Generate an ISN_BCALL instruction.
1364 * Return FAIL if the number of arguments is wrong.
1365 */
1366 static int
1367generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1368{
1369 isn_T *isn;
1370 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001371 type_T *argtypes[MAX_FUNC_ARGS];
1372 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001373
Bram Moolenaar080457c2020-03-03 21:53:32 +01001374 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001375 if (check_internal_func(func_idx, argcount) == FAIL)
1376 return FAIL;
1377
1378 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1379 return FAIL;
1380 isn->isn_arg.bfunc.cbf_idx = func_idx;
1381 isn->isn_arg.bfunc.cbf_argcount = argcount;
1382
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001383 for (i = 0; i < argcount; ++i)
1384 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1385
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001386 stack->ga_len -= argcount; // drop the arguments
1387 if (ga_grow(stack, 1) == FAIL)
1388 return FAIL;
1389 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001390 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001391 ++stack->ga_len; // add return value
1392
1393 return OK;
1394}
1395
1396/*
1397 * Generate an ISN_DCALL or ISN_UCALL instruction.
1398 * Return FAIL if the number of arguments is wrong.
1399 */
1400 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001401generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001402{
1403 isn_T *isn;
1404 garray_T *stack = &cctx->ctx_type_stack;
1405 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001406 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001407
Bram Moolenaar080457c2020-03-03 21:53:32 +01001408 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001409 if (argcount > regular_args && !has_varargs(ufunc))
1410 {
1411 semsg(_(e_toomanyarg), ufunc->uf_name);
1412 return FAIL;
1413 }
1414 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1415 {
1416 semsg(_(e_toofewarg), ufunc->uf_name);
1417 return FAIL;
1418 }
1419
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001420 if (ufunc->uf_dfunc_idx >= 0)
1421 {
1422 int i;
1423
1424 for (i = 0; i < argcount; ++i)
1425 {
1426 type_T *expected;
1427 type_T *actual;
1428
1429 if (i < regular_args)
1430 {
1431 if (ufunc->uf_arg_types == NULL)
1432 continue;
1433 expected = ufunc->uf_arg_types[i];
1434 }
1435 else
1436 expected = ufunc->uf_va_type->tt_member;
1437 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001438 if (need_type(actual, expected, -argcount + i, cctx) == FAIL)
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001439 {
1440 arg_type_mismatch(expected, actual, i + 1);
1441 return FAIL;
1442 }
1443 }
1444 }
1445
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001446 if ((isn = generate_instr(cctx,
1447 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1448 return FAIL;
1449 if (ufunc->uf_dfunc_idx >= 0)
1450 {
1451 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1452 isn->isn_arg.dfunc.cdf_argcount = argcount;
1453 }
1454 else
1455 {
1456 // A user function may be deleted and redefined later, can't use the
1457 // ufunc pointer, need to look it up again at runtime.
1458 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1459 isn->isn_arg.ufunc.cuf_argcount = argcount;
1460 }
1461
1462 stack->ga_len -= argcount; // drop the arguments
1463 if (ga_grow(stack, 1) == FAIL)
1464 return FAIL;
1465 // add return value
1466 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1467 ++stack->ga_len;
1468
1469 return OK;
1470}
1471
1472/*
1473 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1474 */
1475 static int
1476generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1477{
1478 isn_T *isn;
1479 garray_T *stack = &cctx->ctx_type_stack;
1480
Bram Moolenaar080457c2020-03-03 21:53:32 +01001481 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001482 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1483 return FAIL;
1484 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1485 isn->isn_arg.ufunc.cuf_argcount = argcount;
1486
1487 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001488 if (ga_grow(stack, 1) == FAIL)
1489 return FAIL;
1490 // add return value
1491 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1492 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001493
1494 return OK;
1495}
1496
1497/*
1498 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001499 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001500 */
1501 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001502generate_PCALL(
1503 cctx_T *cctx,
1504 int argcount,
1505 char_u *name,
1506 type_T *type,
1507 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001508{
1509 isn_T *isn;
1510 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001511 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001512
Bram Moolenaar080457c2020-03-03 21:53:32 +01001513 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001514
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001515 if (type->tt_type == VAR_ANY)
1516 ret_type = &t_any;
1517 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001518 {
1519 if (type->tt_argcount != -1)
1520 {
1521 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
1522
1523 if (argcount < type->tt_min_argcount - varargs)
1524 {
1525 semsg(_(e_toofewarg), "[reference]");
1526 return FAIL;
1527 }
1528 if (!varargs && argcount > type->tt_argcount)
1529 {
1530 semsg(_(e_toomanyarg), "[reference]");
1531 return FAIL;
1532 }
1533 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001534 ret_type = type->tt_member;
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02001535 }
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001536 else
1537 {
1538 semsg(_("E1085: Not a callable type: %s"), name);
1539 return FAIL;
1540 }
1541
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001542 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1543 return FAIL;
1544 isn->isn_arg.pfunc.cpf_top = at_top;
1545 isn->isn_arg.pfunc.cpf_argcount = argcount;
1546
1547 stack->ga_len -= argcount; // drop the arguments
1548
1549 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001550 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001551
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001552 // If partial is above the arguments it must be cleared and replaced with
1553 // the return value.
1554 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1555 return FAIL;
1556
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001557 return OK;
1558}
1559
1560/*
1561 * Generate an ISN_MEMBER instruction.
1562 */
1563 static int
1564generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1565{
1566 isn_T *isn;
1567 garray_T *stack = &cctx->ctx_type_stack;
1568 type_T *type;
1569
Bram Moolenaar080457c2020-03-03 21:53:32 +01001570 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001571 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1572 return FAIL;
1573 isn->isn_arg.string = vim_strnsave(name, (int)len);
1574
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001575 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001576 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001577 if (type->tt_type != VAR_DICT && type != &t_any)
1578 {
1579 emsg(_(e_dictreq));
1580 return FAIL;
1581 }
1582 // change dict type to dict member type
1583 if (type->tt_type == VAR_DICT)
1584 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001585
1586 return OK;
1587}
1588
1589/*
1590 * Generate an ISN_ECHO instruction.
1591 */
1592 static int
1593generate_ECHO(cctx_T *cctx, int with_white, int count)
1594{
1595 isn_T *isn;
1596
Bram Moolenaar080457c2020-03-03 21:53:32 +01001597 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001598 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1599 return FAIL;
1600 isn->isn_arg.echo.echo_with_white = with_white;
1601 isn->isn_arg.echo.echo_count = count;
1602
1603 return OK;
1604}
1605
Bram Moolenaarad39c092020-02-26 18:23:43 +01001606/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001607 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001608 */
1609 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001610generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001611{
1612 isn_T *isn;
1613
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001614 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001615 return FAIL;
1616 isn->isn_arg.number = count;
1617
1618 return OK;
1619}
1620
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001621 static int
1622generate_EXEC(cctx_T *cctx, char_u *line)
1623{
1624 isn_T *isn;
1625
Bram Moolenaar080457c2020-03-03 21:53:32 +01001626 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001627 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1628 return FAIL;
1629 isn->isn_arg.string = vim_strsave(line);
1630 return OK;
1631}
1632
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001633 static int
1634generate_EXECCONCAT(cctx_T *cctx, int count)
1635{
1636 isn_T *isn;
1637
1638 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1639 return FAIL;
1640 isn->isn_arg.number = count;
1641 return OK;
1642}
1643
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001644/*
1645 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001646 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001647 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001648 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001649reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1650{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001651 lvar_T *lvar;
1652
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02001653 if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001654 {
1655 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001656 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001657 }
1658
1659 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001660 return NULL;
1661 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001662
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001663 // Every local variable uses the next entry on the stack. We could re-use
1664 // the last ones when leaving a scope, but then variables used in a closure
1665 // might get overwritten. To keep things simple do not re-use stack
1666 // entries. This is less efficient, but memory is cheap these days.
1667 lvar->lv_idx = cctx->ctx_locals_count++;
1668
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001669 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1670 lvar->lv_const = isConst;
1671 lvar->lv_type = type;
1672
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001673 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001674}
1675
1676/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001677 * Remove local variables above "new_top".
1678 */
1679 static void
1680unwind_locals(cctx_T *cctx, int new_top)
1681{
1682 if (cctx->ctx_locals.ga_len > new_top)
1683 {
1684 int idx;
1685 lvar_T *lvar;
1686
1687 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1688 {
1689 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1690 vim_free(lvar->lv_name);
1691 }
1692 }
1693 cctx->ctx_locals.ga_len = new_top;
1694}
1695
1696/*
1697 * Free all local variables.
1698 */
1699 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001700free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01001701{
1702 unwind_locals(cctx, 0);
1703 ga_clear(&cctx->ctx_locals);
1704}
1705
1706/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001707 * Skip over a type definition and return a pointer to just after it.
1708 */
1709 char_u *
1710skip_type(char_u *start)
1711{
1712 char_u *p = start;
1713
1714 while (ASCII_ISALNUM(*p) || *p == '_')
1715 ++p;
1716
1717 // Skip over "<type>"; this is permissive about white space.
1718 if (*skipwhite(p) == '<')
1719 {
1720 p = skipwhite(p);
1721 p = skip_type(skipwhite(p + 1));
1722 p = skipwhite(p);
1723 if (*p == '>')
1724 ++p;
1725 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001726 else if (*p == '(' && STRNCMP("func", start, 4) == 0)
1727 {
1728 // handle func(args): type
1729 ++p;
1730 while (*p != ')' && *p != NUL)
1731 {
Bram Moolenaar1c0d44f2020-05-02 19:04:58 +02001732 char_u *sp = p;
1733
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001734 p = skip_type(p);
Bram Moolenaar1c0d44f2020-05-02 19:04:58 +02001735 if (p == sp)
1736 return p; // syntax error
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001737 if (*p == ',')
1738 p = skipwhite(p + 1);
1739 }
Bram Moolenaar5adc55c2020-05-02 23:12:58 +02001740 if (*p == ')')
1741 {
1742 if (p[1] == ':')
1743 p = skip_type(skipwhite(p + 2));
1744 else
1745 p = skipwhite(p + 1);
1746 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02001747 }
1748
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001749 return p;
1750}
1751
1752/*
1753 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001754 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001755 * Returns NULL in case of failure.
1756 */
1757 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001758parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001759{
1760 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001761 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001762
1763 if (**arg != '<')
1764 {
1765 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001766 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001767 else
1768 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001769 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001770 }
1771 *arg = skipwhite(*arg + 1);
1772
Bram Moolenaard77a8522020-04-03 21:59:57 +02001773 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001774
1775 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001776 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001777 {
1778 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001779 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001780 }
1781 ++*arg;
1782
1783 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001784 return get_list_type(member_type, type_gap);
1785 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001786}
1787
1788/*
1789 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001790 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001791 */
1792 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001793parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001794{
1795 char_u *p = *arg;
1796 size_t len;
1797
1798 // skip over the first word
1799 while (ASCII_ISALNUM(*p) || *p == '_')
1800 ++p;
1801 len = p - *arg;
1802
1803 switch (**arg)
1804 {
1805 case 'a':
1806 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1807 {
1808 *arg += len;
1809 return &t_any;
1810 }
1811 break;
1812 case 'b':
1813 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1814 {
1815 *arg += len;
1816 return &t_bool;
1817 }
1818 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1819 {
1820 *arg += len;
1821 return &t_blob;
1822 }
1823 break;
1824 case 'c':
1825 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1826 {
1827 *arg += len;
1828 return &t_channel;
1829 }
1830 break;
1831 case 'd':
1832 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1833 {
1834 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001835 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001836 }
1837 break;
1838 case 'f':
1839 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1840 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001841#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001842 *arg += len;
1843 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001844#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001845 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001846 return &t_any;
1847#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001848 }
1849 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1850 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001851 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001852 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001853 int argcount = -1;
1854 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001855 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001856 type_T *arg_type[MAX_FUNC_ARGS + 1];
1857
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001858 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001859 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001860 if (**arg == '(')
1861 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001862 // "func" may or may not return a value, "func()" does
1863 // not return a value.
1864 ret_type = &t_void;
1865
Bram Moolenaard77a8522020-04-03 21:59:57 +02001866 p = ++*arg;
1867 argcount = 0;
1868 while (*p != NUL && *p != ')')
1869 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001870 if (*p == '?')
1871 {
1872 if (first_optional == -1)
1873 first_optional = argcount;
1874 ++p;
1875 }
1876 else if (first_optional != -1)
1877 {
1878 emsg(_("E1007: mandatory argument after optional argument"));
1879 return &t_any;
1880 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001881 else if (STRNCMP(p, "...", 3) == 0)
1882 {
1883 flags |= TTFLAG_VARARGS;
1884 p += 3;
1885 }
1886
1887 arg_type[argcount++] = parse_type(&p, type_gap);
1888
1889 // Nothing comes after "...{type}".
1890 if (flags & TTFLAG_VARARGS)
1891 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001892
Bram Moolenaard77a8522020-04-03 21:59:57 +02001893 if (*p != ',' && *skipwhite(p) == ',')
1894 {
1895 semsg(_(e_no_white_before), ",");
1896 return &t_any;
1897 }
1898 if (*p == ',')
1899 {
1900 ++p;
1901 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001902 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001903 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001904 return &t_any;
1905 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001906 }
1907 p = skipwhite(p);
1908 if (argcount == MAX_FUNC_ARGS)
1909 {
1910 emsg(_("E740: Too many argument types"));
1911 return &t_any;
1912 }
1913 }
1914
1915 p = skipwhite(p);
1916 if (*p != ')')
1917 {
1918 emsg(_(e_missing_close));
1919 return &t_any;
1920 }
1921 *arg = p + 1;
1922 }
1923 if (**arg == ':')
1924 {
1925 // parse return type
1926 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001927 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001928 semsg(_(e_white_after), ":");
1929 *arg = skipwhite(*arg);
1930 ret_type = parse_type(arg, type_gap);
1931 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001932 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001933 type = get_func_type(ret_type, argcount, type_gap);
1934 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001935 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001936 type = alloc_func_type(ret_type, argcount, type_gap);
1937 type->tt_flags = flags;
1938 if (argcount > 0)
1939 {
1940 type->tt_argcount = argcount;
1941 type->tt_min_argcount = first_optional == -1
1942 ? argcount : first_optional;
1943 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001944 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001945 return &t_any;
1946 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001947 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001948 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001949 }
1950 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001951 }
1952 break;
1953 case 'j':
1954 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1955 {
1956 *arg += len;
1957 return &t_job;
1958 }
1959 break;
1960 case 'l':
1961 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1962 {
1963 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001964 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001965 }
1966 break;
1967 case 'n':
1968 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1969 {
1970 *arg += len;
1971 return &t_number;
1972 }
1973 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001974 case 's':
1975 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1976 {
1977 *arg += len;
1978 return &t_string;
1979 }
1980 break;
1981 case 'v':
1982 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1983 {
1984 *arg += len;
1985 return &t_void;
1986 }
1987 break;
1988 }
1989
1990 semsg(_("E1010: Type not recognized: %s"), *arg);
1991 return &t_any;
1992}
1993
1994/*
1995 * Check if "type1" and "type2" are exactly the same.
1996 */
1997 static int
1998equal_type(type_T *type1, type_T *type2)
1999{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002000 int i;
2001
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002002 if (type1->tt_type != type2->tt_type)
2003 return FALSE;
2004 switch (type1->tt_type)
2005 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002006 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02002007 case VAR_ANY:
2008 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002009 case VAR_SPECIAL:
2010 case VAR_BOOL:
2011 case VAR_NUMBER:
2012 case VAR_FLOAT:
2013 case VAR_STRING:
2014 case VAR_BLOB:
2015 case VAR_JOB:
2016 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002017 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002018 case VAR_LIST:
2019 case VAR_DICT:
2020 return equal_type(type1->tt_member, type2->tt_member);
2021 case VAR_FUNC:
2022 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002023 if (!equal_type(type1->tt_member, type2->tt_member)
2024 || type1->tt_argcount != type2->tt_argcount)
2025 return FALSE;
2026 if (type1->tt_argcount < 0
2027 || type1->tt_args == NULL || type2->tt_args == NULL)
2028 return TRUE;
2029 for (i = 0; i < type1->tt_argcount; ++i)
2030 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
2031 return FALSE;
2032 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002033 }
2034 return TRUE;
2035}
2036
2037/*
2038 * Find the common type of "type1" and "type2" and put it in "dest".
2039 * "type2" and "dest" may be the same.
2040 */
2041 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02002042common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002043{
2044 if (equal_type(type1, type2))
2045 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002046 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002047 return;
2048 }
2049
2050 if (type1->tt_type == type2->tt_type)
2051 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002052 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
2053 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002054 type_T *common;
2055
Bram Moolenaard77a8522020-04-03 21:59:57 +02002056 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002057 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02002058 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002059 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02002060 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002061 return;
2062 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002063 if (type1->tt_type == VAR_FUNC)
2064 {
2065 type_T *common;
2066
2067 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
2068 if (type1->tt_argcount == type2->tt_argcount
2069 && type1->tt_argcount >= 0)
2070 {
2071 int argcount = type1->tt_argcount;
2072 int i;
2073
2074 *dest = alloc_func_type(common, argcount, type_gap);
2075 if (type1->tt_args != NULL && type2->tt_args != NULL)
2076 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02002077 if (func_type_add_arg_types(*dest, argcount,
2078 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02002079 for (i = 0; i < argcount; ++i)
2080 common_type(type1->tt_args[i], type2->tt_args[i],
2081 &(*dest)->tt_args[i], type_gap);
2082 }
2083 }
2084 else
2085 *dest = alloc_func_type(common, -1, type_gap);
2086 return;
2087 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002088 }
2089
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01002090 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002091}
2092
2093 char *
2094vartype_name(vartype_T type)
2095{
2096 switch (type)
2097 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002098 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002099 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002100 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002101 case VAR_SPECIAL: return "special";
2102 case VAR_BOOL: return "bool";
2103 case VAR_NUMBER: return "number";
2104 case VAR_FLOAT: return "float";
2105 case VAR_STRING: return "string";
2106 case VAR_BLOB: return "blob";
2107 case VAR_JOB: return "job";
2108 case VAR_CHANNEL: return "channel";
2109 case VAR_LIST: return "list";
2110 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002111
2112 case VAR_FUNC:
2113 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002114 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02002115 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002116}
2117
2118/*
2119 * Return the name of a type.
2120 * The result may be in allocated memory, in which case "tofree" is set.
2121 */
2122 char *
2123type_name(type_T *type, char **tofree)
2124{
2125 char *name = vartype_name(type->tt_type);
2126
2127 *tofree = NULL;
2128 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
2129 {
2130 char *member_free;
2131 char *member_name = type_name(type->tt_member, &member_free);
2132 size_t len;
2133
2134 len = STRLEN(name) + STRLEN(member_name) + 3;
2135 *tofree = alloc(len);
2136 if (*tofree != NULL)
2137 {
2138 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
2139 vim_free(member_free);
2140 return *tofree;
2141 }
2142 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002143 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002144 {
2145 garray_T ga;
2146 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002147 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002148
2149 ga_init2(&ga, 1, 100);
2150 if (ga_grow(&ga, 20) == FAIL)
2151 return "[unknown]";
2152 *tofree = ga.ga_data;
2153 STRCPY(ga.ga_data, "func(");
2154 ga.ga_len += 5;
2155
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002156 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002157 {
2158 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002159 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002160 int len;
2161
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002162 if (type->tt_args == NULL)
2163 arg_type = "[unknown]";
2164 else
2165 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002166 if (i > 0)
2167 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002168 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002169 ga.ga_len += 2;
2170 }
2171 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002172 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002173 {
2174 vim_free(arg_free);
2175 return "[unknown]";
2176 }
2177 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02002178 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02002179 {
2180 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
2181 ga.ga_len += 3;
2182 }
2183 else if (i >= type->tt_min_argcount)
2184 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002185 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002186 ga.ga_len += len;
2187 vim_free(arg_free);
2188 }
2189
2190 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002191 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002192 else
2193 {
2194 char *ret_free;
2195 char *ret_name = type_name(type->tt_member, &ret_free);
2196 int len;
2197
2198 len = (int)STRLEN(ret_name) + 4;
2199 if (ga_grow(&ga, len) == FAIL)
2200 {
2201 vim_free(ret_free);
2202 return "[unknown]";
2203 }
2204 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002205 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
2206 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002207 vim_free(ret_free);
2208 }
2209 return ga.ga_data;
2210 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002211
2212 return name;
2213}
2214
2215/*
2216 * Find "name" in script-local items of script "sid".
2217 * Returns the index in "sn_var_vals" if found.
2218 * If found but not in "sn_var_vals" returns -1.
2219 * If not found returns -2.
2220 */
2221 int
2222get_script_item_idx(int sid, char_u *name, int check_writable)
2223{
2224 hashtab_T *ht;
2225 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002226 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002227 int idx;
2228
2229 // First look the name up in the hashtable.
2230 if (sid <= 0 || sid > script_items.ga_len)
2231 return -1;
2232 ht = &SCRIPT_VARS(sid);
2233 di = find_var_in_ht(ht, 0, name, TRUE);
2234 if (di == NULL)
2235 return -2;
2236
2237 // Now find the svar_T index in sn_var_vals.
2238 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2239 {
2240 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2241
2242 if (sv->sv_tv == &di->di_tv)
2243 {
2244 if (check_writable && sv->sv_const)
2245 semsg(_(e_readonlyvar), name);
2246 return idx;
2247 }
2248 }
2249 return -1;
2250}
2251
2252/*
2253 * Find "name" in imported items of the current script/
2254 */
2255 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002256find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002257{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002258 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002259 int idx;
2260
2261 if (cctx != NULL)
2262 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2263 {
2264 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2265 + idx;
2266
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002267 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2268 : STRLEN(import->imp_name) == len
2269 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002270 return import;
2271 }
2272
2273 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2274 {
2275 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2276
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002277 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2278 : STRLEN(import->imp_name) == len
2279 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002280 return import;
2281 }
2282 return NULL;
2283}
2284
2285/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002286 * Free all imported variables.
2287 */
2288 static void
2289free_imported(cctx_T *cctx)
2290{
2291 int idx;
2292
2293 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2294 {
2295 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2296
2297 vim_free(import->imp_name);
2298 }
2299 ga_clear(&cctx->ctx_imports);
2300}
2301
2302/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002303 * Get the next line of the function from "cctx".
2304 * Returns NULL when at the end.
2305 */
2306 static char_u *
2307next_line_from_context(cctx_T *cctx)
2308{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002309 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002310
2311 do
2312 {
2313 ++cctx->ctx_lnum;
2314 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002315 {
2316 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002317 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002318 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002319 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002320 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002321 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2322 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002323 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002324 return line;
2325}
2326
2327/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002328 * Return TRUE if "p" points at a "#" but not at "#{".
2329 */
2330 static int
2331comment_start(char_u *p)
2332{
2333 return p[0] == '#' && p[1] != '{';
2334}
2335
2336/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002337 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002338 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002339 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2340 */
2341 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002342may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002343{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002344 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002345 {
2346 char_u *next = next_line_from_context(cctx);
2347
2348 if (next == NULL)
2349 return FAIL;
2350 *arg = skipwhite(next);
2351 }
2352 return OK;
2353}
2354
Bram Moolenaara5565e42020-05-09 15:44:01 +02002355// Structure passed between the compile_expr* functions to keep track of
2356// constants that have been parsed but for which no code was produced yet. If
2357// possible expressions on these constants are applied at compile time. If
2358// that is not possible, the code to push the constants needs to be generated
2359// before other instructions.
Bram Moolenaar1c747212020-05-09 18:28:34 +02002360// Using 50 should be more than enough of 5 levels of ().
2361#define PPSIZE 50
Bram Moolenaara5565e42020-05-09 15:44:01 +02002362typedef struct {
Bram Moolenaar1c747212020-05-09 18:28:34 +02002363 typval_T pp_tv[PPSIZE]; // stack of ppconst constants
Bram Moolenaara5565e42020-05-09 15:44:01 +02002364 int pp_used; // active entries in pp_tv[]
2365} ppconst_T;
2366
Bram Moolenaar1c747212020-05-09 18:28:34 +02002367static int compile_expr0(char_u **arg, cctx_T *cctx);
2368static int compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
2369
Bram Moolenaara5565e42020-05-09 15:44:01 +02002370/*
2371 * Generate a PUSH instruction for "tv".
2372 * "tv" will be consumed or cleared.
2373 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
2374 */
2375 static int
2376generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
2377{
2378 if (tv != NULL)
2379 {
2380 switch (tv->v_type)
2381 {
2382 case VAR_UNKNOWN:
2383 break;
2384 case VAR_BOOL:
2385 generate_PUSHBOOL(cctx, tv->vval.v_number);
2386 break;
2387 case VAR_SPECIAL:
2388 generate_PUSHSPEC(cctx, tv->vval.v_number);
2389 break;
2390 case VAR_NUMBER:
2391 generate_PUSHNR(cctx, tv->vval.v_number);
2392 break;
2393#ifdef FEAT_FLOAT
2394 case VAR_FLOAT:
2395 generate_PUSHF(cctx, tv->vval.v_float);
2396 break;
2397#endif
2398 case VAR_BLOB:
2399 generate_PUSHBLOB(cctx, tv->vval.v_blob);
2400 tv->vval.v_blob = NULL;
2401 break;
2402 case VAR_STRING:
2403 generate_PUSHS(cctx, tv->vval.v_string);
2404 tv->vval.v_string = NULL;
2405 break;
2406 default:
2407 iemsg("constant type not supported");
2408 clear_tv(tv);
2409 return FAIL;
2410 }
2411 tv->v_type = VAR_UNKNOWN;
2412 }
2413 return OK;
2414}
2415
2416/*
2417 * Generate code for any ppconst entries.
2418 */
2419 static int
2420generate_ppconst(cctx_T *cctx, ppconst_T *ppconst)
2421{
2422 int i;
2423 int ret = OK;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002424 int save_skip = cctx->ctx_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002425
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002426 cctx->ctx_skip = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002427 for (i = 0; i < ppconst->pp_used; ++i)
2428 if (generate_tv_PUSH(cctx, &ppconst->pp_tv[i]) == FAIL)
2429 ret = FAIL;
2430 ppconst->pp_used = 0;
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002431 cctx->ctx_skip = save_skip;
Bram Moolenaara5565e42020-05-09 15:44:01 +02002432 return ret;
2433}
2434
2435/*
2436 * Clear ppconst constants. Used when failing.
2437 */
2438 static void
2439clear_ppconst(ppconst_T *ppconst)
2440{
2441 int i;
2442
2443 for (i = 0; i < ppconst->pp_used; ++i)
2444 clear_tv(&ppconst->pp_tv[i]);
2445 ppconst->pp_used = 0;
2446}
2447
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002448/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002449 * Generate an instruction to load script-local variable "name", without the
2450 * leading "s:".
2451 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002452 */
2453 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002454compile_load_scriptvar(
2455 cctx_T *cctx,
2456 char_u *name, // variable NUL terminated
2457 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002458 char_u **end, // end of variable
2459 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002460{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002461 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002462 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2463 imported_T *import;
2464
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002465 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002466 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002467 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002468 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2469 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002470 }
2471 if (idx >= 0)
2472 {
2473 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2474
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002475 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002476 current_sctx.sc_sid, idx, sv->sv_type);
2477 return OK;
2478 }
2479
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002480 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002481 if (import != NULL)
2482 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002483 if (import->imp_all)
2484 {
2485 char_u *p = skipwhite(*end);
2486 int name_len;
2487 ufunc_T *ufunc;
2488 type_T *type;
2489
2490 // Used "import * as Name", need to lookup the member.
2491 if (*p != '.')
2492 {
2493 semsg(_("E1060: expected dot after name: %s"), start);
2494 return FAIL;
2495 }
2496 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002497 if (VIM_ISWHITE(*p))
2498 {
2499 emsg(_("E1074: no white space allowed after dot"));
2500 return FAIL;
2501 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002502
2503 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2504 // TODO: what if it is a function?
2505 if (idx < 0)
2506 return FAIL;
2507 *end = p;
2508
2509 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2510 import->imp_sid,
2511 idx,
2512 type);
2513 }
2514 else
2515 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002516 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002517 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2518 import->imp_sid,
2519 import->imp_var_vals_idx,
2520 import->imp_type);
2521 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002522 return OK;
2523 }
2524
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002525 if (error)
2526 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002527 return FAIL;
2528}
2529
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002530 static int
2531generate_funcref(cctx_T *cctx, char_u *name)
2532{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002533 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002534
2535 if (ufunc == NULL)
2536 return FAIL;
2537
2538 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2539}
2540
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002541/*
2542 * Compile a variable name into a load instruction.
2543 * "end" points to just after the name.
2544 * When "error" is FALSE do not give an error when not found.
2545 */
2546 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002547compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002548{
2549 type_T *type;
2550 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002551 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002552 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002553 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002554
2555 if (*(*arg + 1) == ':')
2556 {
2557 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002558 if (end <= *arg + 2)
2559 name = vim_strsave((char_u *)"[empty]");
2560 else
2561 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002562 if (name == NULL)
2563 return FAIL;
2564
2565 if (**arg == 'v')
2566 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002567 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002568 }
2569 else if (**arg == 'g')
2570 {
2571 // Global variables can be defined later, thus we don't check if it
2572 // exists, give error at runtime.
2573 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2574 }
2575 else if (**arg == 's')
2576 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002577 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002578 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002579 else if (**arg == 'b')
2580 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002581 // Buffer-local variables can be defined later, thus we don't check
2582 // if it exists, give error at runtime.
2583 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002584 }
2585 else if (**arg == 'w')
2586 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002587 // Window-local variables can be defined later, thus we don't check
2588 // if it exists, give error at runtime.
2589 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002590 }
2591 else if (**arg == 't')
2592 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002593 // Tabpage-local variables can be defined later, thus we don't
2594 // check if it exists, give error at runtime.
2595 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002596 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002597 else
2598 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002599 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002600 goto theend;
2601 }
2602 }
2603 else
2604 {
2605 size_t len = end - *arg;
2606 int idx;
2607 int gen_load = FALSE;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002608 int gen_load_outer = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002609
2610 name = vim_strnsave(*arg, end - *arg);
2611 if (name == NULL)
2612 return FAIL;
2613
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002614 if (lookup_arg(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002615 {
Bram Moolenaar2fd4cd72020-05-03 22:30:49 +02002616 if (!gen_load_outer)
2617 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002618 }
2619 else
2620 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002621 lvar_T *lvar = lookup_local(*arg, len, cctx);
2622
2623 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002624 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002625 type = lvar->lv_type;
2626 idx = lvar->lv_idx;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002627 if (lvar->lv_from_outer)
2628 gen_load_outer = TRUE;
2629 else
2630 gen_load = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002631 }
2632 else
2633 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02002634 // "var" can be script-local even without using "s:" if it
2635 // already exists.
2636 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2637 == SCRIPT_VERSION_VIM9
2638 || lookup_script(*arg, len) == OK)
2639 res = compile_load_scriptvar(cctx, name, *arg, &end,
2640 FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002641
Bram Moolenaara5565e42020-05-09 15:44:01 +02002642 // When the name starts with an uppercase letter or "x:" it
2643 // can be a user defined function.
2644 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2645 res = generate_funcref(cctx, name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002646 }
2647 }
2648 if (gen_load)
2649 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002650 if (gen_load_outer)
2651 res = generate_LOAD(cctx, ISN_LOADOUTER, idx, NULL, type);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002652 }
2653
2654 *arg = end;
2655
2656theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002657 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002658 semsg(_(e_var_notfound), name);
2659 vim_free(name);
2660 return res;
2661}
2662
2663/*
2664 * Compile the argument expressions.
2665 * "arg" points to just after the "(" and is advanced to after the ")"
2666 */
2667 static int
2668compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2669{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002670 char_u *p = *arg;
2671 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002672
Bram Moolenaare6085c52020-04-12 20:19:16 +02002673 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002674 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002675 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002676 {
2677 p = next_line_from_context(cctx);
2678 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002679 goto failret;
2680 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002681 p = skipwhite(p);
2682 }
2683 if (*p == ')')
2684 {
2685 *arg = p + 1;
2686 return OK;
2687 }
2688
Bram Moolenaara5565e42020-05-09 15:44:01 +02002689 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002690 return FAIL;
2691 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002692
2693 if (*p != ',' && *skipwhite(p) == ',')
2694 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002695 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002696 p = skipwhite(p);
2697 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002698 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002699 {
2700 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002701 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002702 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002703 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002704 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002705 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002706 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002707failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002708 emsg(_(e_missing_close));
2709 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002710}
2711
2712/*
2713 * Compile a function call: name(arg1, arg2)
2714 * "arg" points to "name", "arg + varlen" to the "(".
2715 * "argcount_init" is 1 for "value->method()"
2716 * Instructions:
2717 * EVAL arg1
2718 * EVAL arg2
2719 * BCALL / DCALL / UCALL
2720 */
2721 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02002722compile_call(
2723 char_u **arg,
2724 size_t varlen,
2725 cctx_T *cctx,
2726 ppconst_T *ppconst,
2727 int argcount_init)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002728{
2729 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002730 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002731 int argcount = argcount_init;
2732 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002733 char_u fname_buf[FLEN_FIXED + 1];
2734 char_u *tofree = NULL;
2735 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002736 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002737 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002738
Bram Moolenaara5565e42020-05-09 15:44:01 +02002739 // we can evaluate "has('name')" at compile time
2740 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
2741 {
2742 char_u *s = skipwhite(*arg + varlen + 1);
2743 typval_T argvars[2];
2744
2745 argvars[0].v_type = VAR_UNKNOWN;
2746 if (*s == '"')
2747 (void)get_string_tv(&s, &argvars[0], TRUE);
2748 else if (*s == '\'')
2749 (void)get_lit_string_tv(&s, &argvars[0], TRUE);
2750 s = skipwhite(s);
2751 if (*s == ')' && argvars[0].v_type == VAR_STRING)
2752 {
2753 typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
2754
2755 *arg = s + 1;
2756 argvars[1].v_type = VAR_UNKNOWN;
2757 tv->v_type = VAR_NUMBER;
2758 tv->vval.v_number = 0;
2759 f_has(argvars, tv);
2760 clear_tv(&argvars[0]);
2761 ++ppconst->pp_used;
2762 return OK;
2763 }
Bram Moolenaar497f76b2020-05-09 16:44:22 +02002764 clear_tv(&argvars[0]);
Bram Moolenaara5565e42020-05-09 15:44:01 +02002765 }
2766
2767 if (generate_ppconst(cctx, ppconst) == FAIL)
2768 return FAIL;
2769
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002770 if (varlen >= sizeof(namebuf))
2771 {
2772 semsg(_("E1011: name too long: %s"), name);
2773 return FAIL;
2774 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002775 vim_strncpy(namebuf, *arg, varlen);
2776 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002777
2778 *arg = skipwhite(*arg + varlen + 1);
2779 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002780 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002781
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002782 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002783 {
2784 int idx;
2785
2786 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002787 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002788 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002789 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002790 else
2791 semsg(_(e_unknownfunc), namebuf);
2792 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002793 }
2794
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002795 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002796 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002797 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002798 {
2799 res = generate_CALL(cctx, ufunc, argcount);
2800 goto theend;
2801 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002802
2803 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002804 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002805 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002806 if (STRNCMP(namebuf, "g:", 2) != 0
2807 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002808 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002809 garray_T *stack = &cctx->ctx_type_stack;
2810 type_T *type;
2811
2812 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2813 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002814 goto theend;
2815 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002816
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002817 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002818 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002819 if (STRNCMP(namebuf, "g:", 2) == 0)
2820 res = generate_UCALL(cctx, name, argcount);
2821 else
2822 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002823
2824theend:
2825 vim_free(tofree);
2826 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002827}
2828
2829// like NAMESPACE_CHAR but with 'a' and 'l'.
2830#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2831
2832/*
2833 * Find the end of a variable or function name. Unlike find_name_end() this
2834 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002835 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002836 * Return a pointer to just after the name. Equal to "arg" if there is no
2837 * valid name.
2838 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002839 static char_u *
2840to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002841{
2842 char_u *p;
2843
2844 // Quick check for valid starting character.
2845 if (!eval_isnamec1(*arg))
2846 return arg;
2847
2848 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2849 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2850 // and can be used in slice "[n:]".
2851 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002852 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002853 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2854 break;
2855 return p;
2856}
2857
2858/*
2859 * Like to_name_end() but also skip over a list or dict constant.
2860 */
2861 char_u *
2862to_name_const_end(char_u *arg)
2863{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002864 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002865 typval_T rettv;
2866
2867 if (p == arg && *arg == '[')
2868 {
2869
2870 // Can be "[1, 2, 3]->Func()".
2871 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2872 p = arg;
2873 }
2874 else if (p == arg && *arg == '#' && arg[1] == '{')
2875 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002876 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002877 ++p;
2878 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2879 p = arg;
2880 }
2881 else if (p == arg && *arg == '{')
2882 {
2883 int ret = get_lambda_tv(&p, &rettv, FALSE);
2884
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002885 // Can be "{x -> ret}()".
2886 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002887 if (ret == NOTDONE)
2888 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2889 if (ret != OK)
2890 p = arg;
2891 }
2892
2893 return p;
2894}
2895
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002896/*
2897 * parse a list: [expr, expr]
2898 * "*arg" points to the '['.
2899 */
2900 static int
2901compile_list(char_u **arg, cctx_T *cctx)
2902{
2903 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002904 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002905 int count = 0;
2906
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002907 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002908 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002909 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002910 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002911 p = next_line_from_context(cctx);
2912 if (p == NULL)
2913 {
2914 semsg(_(e_list_end), *arg);
2915 return FAIL;
2916 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002917 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002918 p = skipwhite(p);
2919 }
2920 if (*p == ']')
2921 {
2922 ++p;
2923 // Allow for following comment, after at least one space.
2924 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2925 p += STRLEN(p);
2926 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002927 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02002928 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002929 break;
2930 ++count;
2931 if (*p == ',')
2932 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002933 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002934 p = skipwhite(p);
2935 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002936 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002937
2938 generate_NEWLIST(cctx, count);
2939 return OK;
2940}
2941
2942/*
2943 * parse a lambda: {arg, arg -> expr}
2944 * "*arg" points to the '{'.
2945 */
2946 static int
2947compile_lambda(char_u **arg, cctx_T *cctx)
2948{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002949 typval_T rettv;
2950 ufunc_T *ufunc;
2951
2952 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002953 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002954 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002955
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002956 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002957 ++ufunc->uf_refcount;
2958 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002959 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002960
2961 // The function will have one line: "return {expr}".
2962 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02002963 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002964
2965 if (ufunc->uf_dfunc_idx >= 0)
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02002966 return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002967 return FAIL;
2968}
2969
2970/*
2971 * Compile a lamda call: expr->{lambda}(args)
2972 * "arg" points to the "{".
2973 */
2974 static int
2975compile_lambda_call(char_u **arg, cctx_T *cctx)
2976{
2977 ufunc_T *ufunc;
2978 typval_T rettv;
2979 int argcount = 1;
2980 int ret = FAIL;
2981
2982 // Get the funcref in "rettv".
2983 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2984 return FAIL;
2985
2986 if (**arg != '(')
2987 {
2988 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002989 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002990 else
2991 semsg(_(e_missing_paren), "lambda");
2992 clear_tv(&rettv);
2993 return FAIL;
2994 }
2995
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002996 ufunc = rettv.vval.v_partial->pt_func;
2997 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002998 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002999 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01003000
3001 // The function will have one line: "return {expr}".
3002 // Compile it into instructions.
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02003003 compile_def_function(ufunc, TRUE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003004
3005 // compile the arguments
3006 *arg = skipwhite(*arg + 1);
3007 if (compile_arguments(arg, cctx, &argcount) == OK)
3008 // call the compiled function
3009 ret = generate_CALL(cctx, ufunc, argcount);
3010
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003011 return ret;
3012}
3013
3014/*
3015 * parse a dict: {'key': val} or #{key: val}
3016 * "*arg" points to the '{'.
3017 */
3018 static int
3019compile_dict(char_u **arg, cctx_T *cctx, int literal)
3020{
3021 garray_T *instr = &cctx->ctx_instr;
3022 int count = 0;
3023 dict_T *d = dict_alloc();
3024 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003025 char_u *whitep = *arg;
3026 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003027
3028 if (d == NULL)
3029 return FAIL;
3030 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003031 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003032 {
3033 char_u *key = NULL;
3034
Bram Moolenaar2c330432020-04-13 14:41:35 +02003035 while (**arg == NUL || (literal && **arg == '"')
3036 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003037 {
3038 *arg = next_line_from_context(cctx);
3039 if (*arg == NULL)
3040 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003041 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003042 *arg = skipwhite(*arg);
3043 }
3044
3045 if (**arg == '}')
3046 break;
3047
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003048 if (literal)
3049 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02003050 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003051
Bram Moolenaar2c330432020-04-13 14:41:35 +02003052 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003053 {
3054 semsg(_("E1014: Invalid key: %s"), *arg);
3055 return FAIL;
3056 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003057 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003058 if (generate_PUSHS(cctx, key) == FAIL)
3059 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003060 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003061 }
3062 else
3063 {
3064 isn_T *isn;
3065
Bram Moolenaara5565e42020-05-09 15:44:01 +02003066 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003067 return FAIL;
3068 // TODO: check type is string
3069 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
3070 if (isn->isn_type == ISN_PUSHS)
3071 key = isn->isn_arg.string;
3072 }
3073
3074 // Check for duplicate keys, if using string keys.
3075 if (key != NULL)
3076 {
3077 item = dict_find(d, key, -1);
3078 if (item != NULL)
3079 {
3080 semsg(_(e_duplicate_key), key);
3081 goto failret;
3082 }
3083 item = dictitem_alloc(key);
3084 if (item != NULL)
3085 {
3086 item->di_tv.v_type = VAR_UNKNOWN;
3087 item->di_tv.v_lock = 0;
3088 if (dict_add(d, item) == FAIL)
3089 dictitem_free(item);
3090 }
3091 }
3092
3093 *arg = skipwhite(*arg);
3094 if (**arg != ':')
3095 {
3096 semsg(_(e_missing_dict_colon), *arg);
3097 return FAIL;
3098 }
3099
Bram Moolenaar2c330432020-04-13 14:41:35 +02003100 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003101 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003102 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003103 {
3104 *arg = next_line_from_context(cctx);
3105 if (*arg == NULL)
3106 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003107 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003108 *arg = skipwhite(*arg);
3109 }
3110
Bram Moolenaara5565e42020-05-09 15:44:01 +02003111 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003112 return FAIL;
3113 ++count;
3114
Bram Moolenaar2c330432020-04-13 14:41:35 +02003115 whitep = *arg;
3116 p = skipwhite(*arg);
3117 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003118 {
3119 *arg = next_line_from_context(cctx);
3120 if (*arg == NULL)
3121 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02003122 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003123 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003124 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003125 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003126 if (**arg == '}')
3127 break;
3128 if (**arg != ',')
3129 {
3130 semsg(_(e_missing_dict_comma), *arg);
3131 goto failret;
3132 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02003133 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003134 *arg = skipwhite(*arg + 1);
3135 }
3136
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003137 *arg = *arg + 1;
3138
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003139 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02003140 p = skipwhite(*arg);
3141 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003142 *arg += STRLEN(*arg);
3143
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003144 dict_unref(d);
3145 return generate_NEWDICT(cctx, count);
3146
3147failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02003148 if (*arg == NULL)
3149 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003150 dict_unref(d);
3151 return FAIL;
3152}
3153
3154/*
3155 * Compile "&option".
3156 */
3157 static int
3158compile_get_option(char_u **arg, cctx_T *cctx)
3159{
3160 typval_T rettv;
3161 char_u *start = *arg;
3162 int ret;
3163
3164 // parse the option and get the current value to get the type.
3165 rettv.v_type = VAR_UNKNOWN;
3166 ret = get_option_tv(arg, &rettv, TRUE);
3167 if (ret == OK)
3168 {
3169 // include the '&' in the name, get_option_tv() expects it.
3170 char_u *name = vim_strnsave(start, *arg - start);
3171 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
3172
3173 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
3174 vim_free(name);
3175 }
3176 clear_tv(&rettv);
3177
3178 return ret;
3179}
3180
3181/*
3182 * Compile "$VAR".
3183 */
3184 static int
3185compile_get_env(char_u **arg, cctx_T *cctx)
3186{
3187 char_u *start = *arg;
3188 int len;
3189 int ret;
3190 char_u *name;
3191
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003192 ++*arg;
3193 len = get_env_len(arg);
3194 if (len == 0)
3195 {
3196 semsg(_(e_syntax_at), start - 1);
3197 return FAIL;
3198 }
3199
3200 // include the '$' in the name, get_env_tv() expects it.
3201 name = vim_strnsave(start, len + 1);
3202 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
3203 vim_free(name);
3204 return ret;
3205}
3206
3207/*
3208 * Compile "@r".
3209 */
3210 static int
3211compile_get_register(char_u **arg, cctx_T *cctx)
3212{
3213 int ret;
3214
3215 ++*arg;
3216 if (**arg == NUL)
3217 {
3218 semsg(_(e_syntax_at), *arg - 1);
3219 return FAIL;
3220 }
3221 if (!valid_yank_reg(**arg, TRUE))
3222 {
3223 emsg_invreg(**arg);
3224 return FAIL;
3225 }
3226 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3227 ++*arg;
3228 return ret;
3229}
3230
3231/*
3232 * Apply leading '!', '-' and '+' to constant "rettv".
3233 */
3234 static int
3235apply_leader(typval_T *rettv, char_u *start, char_u *end)
3236{
3237 char_u *p = end;
3238
3239 // this works from end to start
3240 while (p > start)
3241 {
3242 --p;
3243 if (*p == '-' || *p == '+')
3244 {
3245 // only '-' has an effect, for '+' we only check the type
3246#ifdef FEAT_FLOAT
3247 if (rettv->v_type == VAR_FLOAT)
3248 {
3249 if (*p == '-')
3250 rettv->vval.v_float = -rettv->vval.v_float;
3251 }
3252 else
3253#endif
3254 {
3255 varnumber_T val;
3256 int error = FALSE;
3257
3258 // tv_get_number_chk() accepts a string, but we don't want that
3259 // here
3260 if (check_not_string(rettv) == FAIL)
3261 return FAIL;
3262 val = tv_get_number_chk(rettv, &error);
3263 clear_tv(rettv);
3264 if (error)
3265 return FAIL;
3266 if (*p == '-')
3267 val = -val;
3268 rettv->v_type = VAR_NUMBER;
3269 rettv->vval.v_number = val;
3270 }
3271 }
3272 else
3273 {
3274 int v = tv2bool(rettv);
3275
3276 // '!' is permissive in the type.
3277 clear_tv(rettv);
3278 rettv->v_type = VAR_BOOL;
3279 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3280 }
3281 }
3282 return OK;
3283}
3284
3285/*
3286 * Recognize v: variables that are constants and set "rettv".
3287 */
3288 static void
3289get_vim_constant(char_u **arg, typval_T *rettv)
3290{
3291 if (STRNCMP(*arg, "v:true", 6) == 0)
3292 {
3293 rettv->v_type = VAR_BOOL;
3294 rettv->vval.v_number = VVAL_TRUE;
3295 *arg += 6;
3296 }
3297 else if (STRNCMP(*arg, "v:false", 7) == 0)
3298 {
3299 rettv->v_type = VAR_BOOL;
3300 rettv->vval.v_number = VVAL_FALSE;
3301 *arg += 7;
3302 }
3303 else if (STRNCMP(*arg, "v:null", 6) == 0)
3304 {
3305 rettv->v_type = VAR_SPECIAL;
3306 rettv->vval.v_number = VVAL_NULL;
3307 *arg += 6;
3308 }
3309 else if (STRNCMP(*arg, "v:none", 6) == 0)
3310 {
3311 rettv->v_type = VAR_SPECIAL;
3312 rettv->vval.v_number = VVAL_NONE;
3313 *arg += 6;
3314 }
3315}
3316
Bram Moolenaar61a89812020-05-07 16:58:17 +02003317 static exptype_T
3318get_compare_type(char_u *p, int *len, int *type_is)
3319{
3320 exptype_T type = EXPR_UNKNOWN;
3321 int i;
3322
3323 switch (p[0])
3324 {
3325 case '=': if (p[1] == '=')
3326 type = EXPR_EQUAL;
3327 else if (p[1] == '~')
3328 type = EXPR_MATCH;
3329 break;
3330 case '!': if (p[1] == '=')
3331 type = EXPR_NEQUAL;
3332 else if (p[1] == '~')
3333 type = EXPR_NOMATCH;
3334 break;
3335 case '>': if (p[1] != '=')
3336 {
3337 type = EXPR_GREATER;
3338 *len = 1;
3339 }
3340 else
3341 type = EXPR_GEQUAL;
3342 break;
3343 case '<': if (p[1] != '=')
3344 {
3345 type = EXPR_SMALLER;
3346 *len = 1;
3347 }
3348 else
3349 type = EXPR_SEQUAL;
3350 break;
3351 case 'i': if (p[1] == 's')
3352 {
3353 // "is" and "isnot"; but not a prefix of a name
3354 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3355 *len = 5;
3356 i = p[*len];
3357 if (!isalnum(i) && i != '_')
3358 {
3359 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3360 *type_is = TRUE;
3361 }
3362 }
3363 break;
3364 }
3365 return type;
3366}
3367
3368/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003369 * Compile code to apply '-', '+' and '!'.
3370 */
3371 static int
3372compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3373{
3374 char_u *p = end;
3375
3376 // this works from end to start
3377 while (p > start)
3378 {
3379 --p;
3380 if (*p == '-' || *p == '+')
3381 {
3382 int negate = *p == '-';
3383 isn_T *isn;
3384
3385 // TODO: check type
3386 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3387 {
3388 --p;
3389 if (*p == '-')
3390 negate = !negate;
3391 }
3392 // only '-' has an effect, for '+' we only check the type
3393 if (negate)
3394 isn = generate_instr(cctx, ISN_NEGATENR);
3395 else
3396 isn = generate_instr(cctx, ISN_CHECKNR);
3397 if (isn == NULL)
3398 return FAIL;
3399 }
3400 else
3401 {
3402 int invert = TRUE;
3403
3404 while (p > start && p[-1] == '!')
3405 {
3406 --p;
3407 invert = !invert;
3408 }
3409 if (generate_2BOOL(cctx, invert) == FAIL)
3410 return FAIL;
3411 }
3412 }
3413 return OK;
3414}
3415
3416/*
3417 * Compile whatever comes after "name" or "name()".
3418 */
3419 static int
3420compile_subscript(
3421 char_u **arg,
3422 cctx_T *cctx,
3423 char_u **start_leader,
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003424 char_u *end_leader,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003425 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003426{
3427 for (;;)
3428 {
3429 if (**arg == '(')
3430 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003431 garray_T *stack = &cctx->ctx_type_stack;
3432 type_T *type;
3433 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003434
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003435 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003436 return FAIL;
3437
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003438 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003439 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3440
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003441 *arg = skipwhite(*arg + 1);
3442 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3443 return FAIL;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003444 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003445 return FAIL;
3446 }
3447 else if (**arg == '-' && (*arg)[1] == '>')
3448 {
3449 char_u *p;
3450
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003451 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003452 return FAIL;
3453
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003454 // something->method()
3455 // Apply the '!', '-' and '+' first:
3456 // -1.0->func() works like (-1.0)->func()
3457 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3458 return FAIL;
3459 *start_leader = end_leader; // don't apply again later
3460
3461 *arg = skipwhite(*arg + 2);
3462 if (**arg == '{')
3463 {
3464 // lambda call: list->{lambda}
3465 if (compile_lambda_call(arg, cctx) == FAIL)
3466 return FAIL;
3467 }
3468 else
3469 {
3470 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003471 p = *arg;
3472 if (ASCII_ISALPHA(*p) && p[1] == ':')
3473 p += 2;
3474 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003475 ;
3476 if (*p != '(')
3477 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003478 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003479 return FAIL;
3480 }
3481 // TODO: base value may not be the first argument
Bram Moolenaara5565e42020-05-09 15:44:01 +02003482 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003483 return FAIL;
3484 }
3485 }
3486 else if (**arg == '[')
3487 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003488 garray_T *stack;
3489 type_T **typep;
3490
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003491 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003492 return FAIL;
3493
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003494 // list index: list[123]
3495 // TODO: more arguments
3496 // TODO: dict member dict['name']
3497 *arg = skipwhite(*arg + 1);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003498 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003499 return FAIL;
3500
3501 if (**arg != ']')
3502 {
3503 emsg(_(e_missbrac));
3504 return FAIL;
3505 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003506 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003507
3508 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3509 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003510 stack = &cctx->ctx_type_stack;
3511 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3512 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3513 {
3514 emsg(_(e_listreq));
3515 return FAIL;
3516 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003517 if ((*typep)->tt_type == VAR_LIST)
3518 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003519 }
3520 else if (**arg == '.' && (*arg)[1] != '.')
3521 {
3522 char_u *p;
3523
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003524 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003525 return FAIL;
3526
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003527 ++*arg;
3528 p = *arg;
3529 // dictionary member: dict.name
3530 if (eval_isnamec1(*p))
3531 while (eval_isnamec(*p))
3532 MB_PTR_ADV(p);
3533 if (p == *arg)
3534 {
3535 semsg(_(e_syntax_at), *arg);
3536 return FAIL;
3537 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003538 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3539 return FAIL;
3540 *arg = p;
3541 }
3542 else
3543 break;
3544 }
3545
3546 // TODO - see handle_subscript():
3547 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3548 // Don't do this when "Func" is already a partial that was bound
3549 // explicitly (pt_auto is FALSE).
3550
3551 return OK;
3552}
3553
3554/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003555 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
3556 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003557 *
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003558 * If the value is a constant "ppconst->pp_ret" will be set.
3559 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003560 *
3561 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003562 */
3563
3564/*
3565 * number number constant
3566 * 0zFFFFFFFF Blob constant
3567 * "string" string constant
3568 * 'string' literal string constant
3569 * &option-name option value
3570 * @r register contents
3571 * identifier variable value
3572 * function() function call
3573 * $VAR environment variable
3574 * (expression) nested expression
3575 * [expr, expr] List
3576 * {key: val, key: val} Dictionary
3577 * #{key: val, key: val} Dictionary with literal keys
3578 *
3579 * Also handle:
3580 * ! in front logical NOT
3581 * - in front unary minus
3582 * + in front unary plus (ignored)
3583 * trailing (arg) funcref/partial call
3584 * trailing [] subscript in String or List
3585 * trailing .name entry in Dictionary
3586 * trailing ->name() method call
3587 */
3588 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003589compile_expr7(
3590 char_u **arg,
3591 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003592 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003593{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003594 char_u *start_leader, *end_leader;
3595 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003596 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02003597 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003598
3599 /*
3600 * Skip '!', '-' and '+' characters. They are handled later.
3601 */
3602 start_leader = *arg;
3603 while (**arg == '!' || **arg == '-' || **arg == '+')
3604 *arg = skipwhite(*arg + 1);
3605 end_leader = *arg;
3606
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003607 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003608 switch (**arg)
3609 {
3610 /*
3611 * Number constant.
3612 */
3613 case '0': // also for blob starting with 0z
3614 case '1':
3615 case '2':
3616 case '3':
3617 case '4':
3618 case '5':
3619 case '6':
3620 case '7':
3621 case '8':
3622 case '9':
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003623 case '.': if (get_number_tv(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003624 return FAIL;
3625 break;
3626
3627 /*
3628 * String constant: "string".
3629 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003630 case '"': if (get_string_tv(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003631 return FAIL;
3632 break;
3633
3634 /*
3635 * Literal string constant: 'str''ing'.
3636 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003637 case '\'': if (get_lit_string_tv(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003638 return FAIL;
3639 break;
3640
3641 /*
3642 * Constant Vim variable.
3643 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003644 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003645 ret = NOTDONE;
3646 break;
3647
3648 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02003649 * "true" constant
3650 */
3651 case 't': if (STRNCMP(*arg, "true", 4) == 0
3652 && !eval_isnamec((*arg)[4]))
3653 {
3654 *arg += 4;
3655 rettv->v_type = VAR_BOOL;
3656 rettv->vval.v_number = VVAL_TRUE;
3657 }
3658 else
3659 ret = NOTDONE;
3660 break;
3661
3662 /*
3663 * "false" constant
3664 */
3665 case 'f': if (STRNCMP(*arg, "false", 5) == 0
3666 && !eval_isnamec((*arg)[5]))
3667 {
3668 *arg += 5;
3669 rettv->v_type = VAR_BOOL;
3670 rettv->vval.v_number = VVAL_FALSE;
3671 }
3672 else
3673 ret = NOTDONE;
3674 break;
3675
3676 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003677 * List: [expr, expr]
3678 */
3679 case '[': ret = compile_list(arg, cctx);
3680 break;
3681
3682 /*
3683 * Dictionary: #{key: val, key: val}
3684 */
3685 case '#': if ((*arg)[1] == '{')
3686 {
3687 ++*arg;
3688 ret = compile_dict(arg, cctx, TRUE);
3689 }
3690 else
3691 ret = NOTDONE;
3692 break;
3693
3694 /*
3695 * Lambda: {arg, arg -> expr}
3696 * Dictionary: {'key': val, 'key': val}
3697 */
3698 case '{': {
3699 char_u *start = skipwhite(*arg + 1);
3700
3701 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003702 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003703 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003704 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003705 if (ret != FAIL && *start == '>')
3706 ret = compile_lambda(arg, cctx);
3707 else
3708 ret = compile_dict(arg, cctx, FALSE);
3709 }
3710 break;
3711
3712 /*
3713 * Option value: &name
3714 */
3715 case '&': ret = compile_get_option(arg, cctx);
3716 break;
3717
3718 /*
3719 * Environment variable: $VAR.
3720 */
3721 case '$': ret = compile_get_env(arg, cctx);
3722 break;
3723
3724 /*
3725 * Register contents: @r.
3726 */
3727 case '@': ret = compile_get_register(arg, cctx);
3728 break;
3729 /*
3730 * nested expression: (expression).
3731 */
3732 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaar1c747212020-05-09 18:28:34 +02003733
3734 // recursive!
3735 if (ppconst->pp_used <= PPSIZE - 10)
3736 {
3737 ret = compile_expr1(arg, cctx, ppconst);
3738 }
3739 else
3740 {
3741 // Not enough space in ppconst, flush constants.
3742 if (generate_ppconst(cctx, ppconst) == FAIL)
3743 return FAIL;
3744 ret = compile_expr0(arg, cctx);
3745 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003746 *arg = skipwhite(*arg);
3747 if (**arg == ')')
3748 ++*arg;
3749 else if (ret == OK)
3750 {
3751 emsg(_(e_missing_close));
3752 ret = FAIL;
3753 }
3754 break;
3755
3756 default: ret = NOTDONE;
3757 break;
3758 }
3759 if (ret == FAIL)
3760 return FAIL;
3761
Bram Moolenaar1c747212020-05-09 18:28:34 +02003762 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003763 {
3764 // apply the '!', '-' and '+' before the constant
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003765 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003766 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003767 clear_tv(rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003768 return FAIL;
3769 }
3770 start_leader = end_leader; // don't apply again below
3771
Bram Moolenaara5565e42020-05-09 15:44:01 +02003772 if (cctx->ctx_skip == TRUE)
3773 clear_tv(rettv);
3774 else
3775 // A constant expression can possibly be handled compile time,
3776 // return the value instead of generating code.
3777 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003778 }
3779 else if (ret == NOTDONE)
3780 {
3781 char_u *p;
3782 int r;
3783
3784 if (!eval_isnamec1(**arg))
3785 {
3786 semsg(_("E1015: Name expected: %s"), *arg);
3787 return FAIL;
3788 }
3789
3790 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003791 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003792 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02003793 {
3794 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
3795 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003796 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02003797 {
3798 if (generate_ppconst(cctx, ppconst) == FAIL)
3799 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003800 r = compile_load(arg, p, cctx, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003801 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003802 if (r == FAIL)
3803 return FAIL;
3804 }
3805
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02003806 // Handle following "[]", ".member", etc.
3807 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003808 if (compile_subscript(arg, cctx, &start_leader, end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02003809 ppconst) == FAIL)
3810 return FAIL;
3811 if (ppconst->pp_used > 0)
3812 {
3813 // apply the '!', '-' and '+' before the constant
3814 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
3815 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
3816 return FAIL;
3817 return OK;
3818 }
3819 if (compile_leader(cctx, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003820 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02003821 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003822}
3823
3824/*
3825 * * number multiplication
3826 * / number division
3827 * % number modulo
3828 */
3829 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003830compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003831{
3832 char_u *op;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003833 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003834
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003835 // get the first expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003836 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003837 return FAIL;
3838
3839 /*
3840 * Repeat computing, until no "*", "/" or "%" is following.
3841 */
3842 for (;;)
3843 {
3844 op = skipwhite(*arg);
3845 if (*op != '*' && *op != '/' && *op != '%')
3846 break;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003847
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003848 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003849 {
3850 char_u buf[3];
3851
3852 vim_strncpy(buf, op, 1);
3853 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003854 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003855 }
3856 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003857 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003858 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003859
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003860 // get the second expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003861 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003862 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003863
3864 if (ppconst->pp_used == ppconst_used + 2
3865 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
3866 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003867 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003868 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
3869 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003870 varnumber_T res = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003871
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003872 // both are numbers: compute the result
3873 switch (*op)
3874 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003875 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003876 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003877 case '/': res = tv1->vval.v_number / tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003878 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003879 case '%': res = tv1->vval.v_number % tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003880 break;
3881 }
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003882 tv1->vval.v_number = res;
3883 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003884 }
3885 else
3886 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003887 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003888 generate_two_op(cctx, op);
3889 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003890 }
3891
3892 return OK;
3893}
3894
3895/*
3896 * + number addition
3897 * - number subtraction
3898 * .. string concatenation
3899 */
3900 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003901compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003902{
3903 char_u *op;
3904 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02003905 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003906
3907 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02003908 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003909 return FAIL;
3910
3911 /*
3912 * Repeat computing, until no "+", "-" or ".." is following.
3913 */
3914 for (;;)
3915 {
3916 op = skipwhite(*arg);
3917 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3918 break;
3919 oplen = (*op == '.' ? 2 : 1);
3920
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003921 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003922 {
3923 char_u buf[3];
3924
3925 vim_strncpy(buf, op, oplen);
3926 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003927 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003928 }
3929
3930 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003931 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003932 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003933
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003934 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02003935 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003936 return FAIL;
3937
Bram Moolenaara5565e42020-05-09 15:44:01 +02003938 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003939 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02003940 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
3941 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
3942 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
3943 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003944 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003945 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
3946 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003947
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003948 // concat/subtract/add constant numbers
3949 if (*op == '+')
3950 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
3951 else if (*op == '-')
3952 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
3953 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003954 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003955 // concatenate constant strings
3956 char_u *s1 = tv1->vval.v_string;
3957 char_u *s2 = tv2->vval.v_string;
3958 size_t len1 = STRLEN(s1);
3959
3960 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
3961 if (tv1->vval.v_string == NULL)
3962 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003963 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003964 return FAIL;
3965 }
3966 mch_memmove(tv1->vval.v_string, s1, len1);
3967 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003968 vim_free(s1);
3969 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003970 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02003971 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003972 }
3973 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003974 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003975 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003976 if (*op == '.')
3977 {
3978 if (may_generate_2STRING(-2, cctx) == FAIL
3979 || may_generate_2STRING(-1, cctx) == FAIL)
3980 return FAIL;
3981 generate_instr_drop(cctx, ISN_CONCAT, 1);
3982 }
3983 else
3984 generate_two_op(cctx, op);
3985 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003986 }
3987
3988 return OK;
3989}
3990
3991/*
3992 * expr5a == expr5b
3993 * expr5a =~ expr5b
3994 * expr5a != expr5b
3995 * expr5a !~ expr5b
3996 * expr5a > expr5b
3997 * expr5a >= expr5b
3998 * expr5a < expr5b
3999 * expr5a <= expr5b
4000 * expr5a is expr5b
4001 * expr5a isnot expr5b
4002 *
4003 * Produces instructions:
4004 * EVAL expr5a Push result of "expr5a"
4005 * EVAL expr5b Push result of "expr5b"
4006 * COMPARE one of the compare instructions
4007 */
4008 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004009compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004010{
4011 exptype_T type = EXPR_UNKNOWN;
4012 char_u *p;
4013 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004014 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004015 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004016
4017 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004018 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004019 return FAIL;
4020
4021 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004022 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004023
4024 /*
4025 * If there is a comparative operator, use it.
4026 */
4027 if (type != EXPR_UNKNOWN)
4028 {
4029 int ic = FALSE; // Default: do not ignore case
4030
4031 if (type_is && (p[len] == '?' || p[len] == '#'))
4032 {
4033 semsg(_(e_invexpr2), *arg);
4034 return FAIL;
4035 }
4036 // extra question mark appended: ignore case
4037 if (p[len] == '?')
4038 {
4039 ic = TRUE;
4040 ++len;
4041 }
4042 // extra '#' appended: match case (ignored)
4043 else if (p[len] == '#')
4044 ++len;
4045 // nothing appended: match case
4046
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004047 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004048 {
4049 char_u buf[7];
4050
4051 vim_strncpy(buf, p, len);
4052 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004053 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004054 }
4055
4056 // get the second variable
4057 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004058 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004059 return FAIL;
4060
Bram Moolenaara5565e42020-05-09 15:44:01 +02004061 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004062 return FAIL;
4063
Bram Moolenaara5565e42020-05-09 15:44:01 +02004064 if (ppconst->pp_used == ppconst_used + 2)
4065 {
4066 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
4067 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
4068 int ret;
4069
4070 // Both sides are a constant, compute the result now.
4071 // First check for a valid combination of types, this is more
4072 // strict than typval_compare().
4073 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
4074 ret = FAIL;
4075 else
4076 {
4077 ret = typval_compare(tv1, tv2, type, ic);
4078 tv1->v_type = VAR_BOOL;
4079 tv1->vval.v_number = tv1->vval.v_number
4080 ? VVAL_TRUE : VVAL_FALSE;
4081 clear_tv(tv2);
4082 --ppconst->pp_used;
4083 }
4084 return ret;
4085 }
4086
4087 generate_ppconst(cctx, ppconst);
4088 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004089 }
4090
4091 return OK;
4092}
4093
Bram Moolenaar7f141552020-05-09 17:35:53 +02004094static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
4095
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004096/*
4097 * Compile || or &&.
4098 */
4099 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004100compile_and_or(
4101 char_u **arg,
4102 cctx_T *cctx,
4103 char *op,
4104 ppconst_T *ppconst,
4105 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004106{
4107 char_u *p = skipwhite(*arg);
4108 int opchar = *op;
4109
4110 if (p[0] == opchar && p[1] == opchar)
4111 {
4112 garray_T *instr = &cctx->ctx_instr;
4113 garray_T end_ga;
4114
4115 /*
4116 * Repeat until there is no following "||" or "&&"
4117 */
4118 ga_init2(&end_ga, sizeof(int), 10);
4119 while (p[0] == opchar && p[1] == opchar)
4120 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004121 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
4122 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004123 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004124 return FAIL;
4125 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004126
Bram Moolenaara5565e42020-05-09 15:44:01 +02004127 // TODO: use ppconst if the value is a constant
4128 generate_ppconst(cctx, ppconst);
4129
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004130 if (ga_grow(&end_ga, 1) == FAIL)
4131 {
4132 ga_clear(&end_ga);
4133 return FAIL;
4134 }
4135 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
4136 ++end_ga.ga_len;
4137 generate_JUMP(cctx, opchar == '|'
4138 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
4139
4140 // eval the next expression
4141 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004142 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004143 return FAIL;
4144
Bram Moolenaara5565e42020-05-09 15:44:01 +02004145 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
4146 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004147 {
4148 ga_clear(&end_ga);
4149 return FAIL;
4150 }
4151 p = skipwhite(*arg);
4152 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004153 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004154
4155 // Fill in the end label in all jumps.
4156 while (end_ga.ga_len > 0)
4157 {
4158 isn_T *isn;
4159
4160 --end_ga.ga_len;
4161 isn = ((isn_T *)instr->ga_data)
4162 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
4163 isn->isn_arg.jump.jump_where = instr->ga_len;
4164 }
4165 ga_clear(&end_ga);
4166 }
4167
4168 return OK;
4169}
4170
4171/*
4172 * expr4a && expr4a && expr4a logical AND
4173 *
4174 * Produces instructions:
4175 * EVAL expr4a Push result of "expr4a"
4176 * JUMP_AND_KEEP_IF_FALSE end
4177 * EVAL expr4b Push result of "expr4b"
4178 * JUMP_AND_KEEP_IF_FALSE end
4179 * EVAL expr4c Push result of "expr4c"
4180 * end:
4181 */
4182 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004183compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004184{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004185 int ppconst_used = ppconst->pp_used;
4186
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004187 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004188 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004189 return FAIL;
4190
4191 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004192 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004193}
4194
4195/*
4196 * expr3a || expr3b || expr3c logical OR
4197 *
4198 * Produces instructions:
4199 * EVAL expr3a Push result of "expr3a"
4200 * JUMP_AND_KEEP_IF_TRUE end
4201 * EVAL expr3b Push result of "expr3b"
4202 * JUMP_AND_KEEP_IF_TRUE end
4203 * EVAL expr3c Push result of "expr3c"
4204 * end:
4205 */
4206 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004207compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004208{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004209 int ppconst_used = ppconst->pp_used;
4210
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004211 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004212 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004213 return FAIL;
4214
4215 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004216 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004217}
4218
4219/*
4220 * Toplevel expression: expr2 ? expr1a : expr1b
4221 *
4222 * Produces instructions:
4223 * EVAL expr2 Push result of "expr"
4224 * JUMP_IF_FALSE alt jump if false
4225 * EVAL expr1a
4226 * JUMP_ALWAYS end
4227 * alt: EVAL expr1b
4228 * end:
4229 */
4230 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004231compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004232{
4233 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004234 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004235
Bram Moolenaar61a89812020-05-07 16:58:17 +02004236 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02004237 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004238 return FAIL;
4239
4240 p = skipwhite(*arg);
4241 if (*p == '?')
4242 {
4243 garray_T *instr = &cctx->ctx_instr;
4244 garray_T *stack = &cctx->ctx_type_stack;
4245 int alt_idx = instr->ga_len;
4246 int end_idx;
4247 isn_T *isn;
4248 type_T *type1;
4249 type_T *type2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004250 int has_const_expr = FALSE;
4251 int const_value = FALSE;
4252 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004253
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004254 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4255 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004256 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004257 return FAIL;
4258 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004259
Bram Moolenaara5565e42020-05-09 15:44:01 +02004260 if (ppconst->pp_used == ppconst_used + 1)
4261 {
4262 // the condition is a constant, we know whether the ? or the :
4263 // expression is to be evaluated.
4264 has_const_expr = TRUE;
4265 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
4266 clear_tv(&ppconst->pp_tv[ppconst_used]);
4267 --ppconst->pp_used;
4268 cctx->ctx_skip = save_skip == TRUE || !const_value;
4269 }
4270 else
4271 {
4272 generate_ppconst(cctx, ppconst);
4273 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4274 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004275
4276 // evaluate the second expression; any type is accepted
4277 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004278 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004279 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004280 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004281 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004282
Bram Moolenaara5565e42020-05-09 15:44:01 +02004283 if (!has_const_expr)
4284 {
4285 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004286
Bram Moolenaara5565e42020-05-09 15:44:01 +02004287 // remember the type and drop it
4288 --stack->ga_len;
4289 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004290
Bram Moolenaara5565e42020-05-09 15:44:01 +02004291 end_idx = instr->ga_len;
4292 generate_JUMP(cctx, JUMP_ALWAYS, 0);
4293
4294 // jump here from JUMP_IF_FALSE
4295 isn = ((isn_T *)instr->ga_data) + alt_idx;
4296 isn->isn_arg.jump.jump_where = instr->ga_len;
4297 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004298
4299 // Check for the ":".
4300 p = skipwhite(*arg);
4301 if (*p != ':')
4302 {
4303 emsg(_(e_missing_colon));
4304 return FAIL;
4305 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004306 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4307 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004308 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004309 return FAIL;
4310 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004311
4312 // evaluate the third expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004313 if (has_const_expr)
4314 cctx->ctx_skip = save_skip == TRUE || const_value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004315 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004316 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004317 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004318 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004319 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004320
Bram Moolenaara5565e42020-05-09 15:44:01 +02004321 if (!has_const_expr)
4322 {
4323 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004324
Bram Moolenaara5565e42020-05-09 15:44:01 +02004325 // If the types differ, the result has a more generic type.
4326 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4327 common_type(type1, type2, &type2, cctx->ctx_type_list);
4328
4329 // jump here from JUMP_ALWAYS
4330 isn = ((isn_T *)instr->ga_data) + end_idx;
4331 isn->isn_arg.jump.jump_where = instr->ga_len;
4332 }
4333
4334 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004335 }
4336 return OK;
4337}
4338
4339/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004340 * Toplevel expression.
4341 */
4342 static int
4343compile_expr0(char_u **arg, cctx_T *cctx)
4344{
4345 ppconst_T ppconst;
4346
4347 CLEAR_FIELD(ppconst);
4348 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
4349 {
4350 clear_ppconst(&ppconst);
4351 return FAIL;
4352 }
4353 if (generate_ppconst(cctx, &ppconst) == FAIL)
4354 return FAIL;
4355 return OK;
4356}
4357
4358/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004359 * compile "return [expr]"
4360 */
4361 static char_u *
4362compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
4363{
4364 char_u *p = arg;
4365 garray_T *stack = &cctx->ctx_type_stack;
4366 type_T *stack_type;
4367
4368 if (*p != NUL && *p != '|' && *p != '\n')
4369 {
4370 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02004371 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004372 return NULL;
4373
4374 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4375 if (set_return_type)
4376 cctx->ctx_ufunc->uf_ret_type = stack_type;
4377 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
4378 == FAIL)
4379 return NULL;
4380 }
4381 else
4382 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004383 // "set_return_type" cannot be TRUE, only used for a lambda which
4384 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02004385 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
4386 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004387 {
4388 emsg(_("E1003: Missing return value"));
4389 return NULL;
4390 }
4391
4392 // No argument, return zero.
4393 generate_PUSHNR(cctx, 0);
4394 }
4395
4396 if (generate_instr(cctx, ISN_RETURN) == NULL)
4397 return NULL;
4398
4399 // "return val | endif" is possible
4400 return skipwhite(p);
4401}
4402
4403/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02004404 * Get a line from the compilation context, compatible with exarg_T getline().
4405 * Return a pointer to the line in allocated memory.
4406 * Return NULL for end-of-file or some error.
4407 */
4408 static char_u *
4409exarg_getline(
4410 int c UNUSED,
4411 void *cookie,
4412 int indent UNUSED,
4413 int do_concat UNUSED)
4414{
4415 cctx_T *cctx = (cctx_T *)cookie;
4416
4417 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
4418 {
4419 iemsg("Heredoc got to end");
4420 return NULL;
4421 }
4422 ++cctx->ctx_lnum;
4423 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4424 [cctx->ctx_lnum]);
4425}
4426
4427/*
4428 * Compile a nested :def command.
4429 */
4430 static char_u *
4431compile_nested_function(exarg_T *eap, cctx_T *cctx)
4432{
4433 char_u *name_start = eap->arg;
4434 char_u *name_end = to_name_end(eap->arg, FALSE);
4435 char_u *name = get_lambda_name();
4436 lvar_T *lvar;
4437 ufunc_T *ufunc;
4438
4439 eap->arg = name_end;
4440 eap->getline = exarg_getline;
4441 eap->cookie = cctx;
4442 eap->skip = cctx->ctx_skip == TRUE;
4443 eap->forceit = FALSE;
4444 ufunc = def_function(eap, name, cctx);
4445
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004446 if (ufunc == NULL || ufunc->uf_dfunc_idx < 0)
Bram Moolenaar04b12692020-05-04 23:24:44 +02004447 return NULL;
4448
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004449 // Define a local variable for the function reference.
Bram Moolenaar04b12692020-05-04 23:24:44 +02004450 lvar = reserve_local(cctx, name_start, name_end - name_start,
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004451 TRUE, ufunc->uf_func_type);
4452
4453 if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL
4454 || generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL) == FAIL)
4455 return NULL;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004456
Bram Moolenaar61a89812020-05-07 16:58:17 +02004457 // TODO: warning for trailing text?
Bram Moolenaar04b12692020-05-04 23:24:44 +02004458 return (char_u *)"";
4459}
4460
4461/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004462 * Return the length of an assignment operator, or zero if there isn't one.
4463 */
4464 int
4465assignment_len(char_u *p, int *heredoc)
4466{
4467 if (*p == '=')
4468 {
4469 if (p[1] == '<' && p[2] == '<')
4470 {
4471 *heredoc = TRUE;
4472 return 3;
4473 }
4474 return 1;
4475 }
4476 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
4477 return 2;
4478 if (STRNCMP(p, "..=", 3) == 0)
4479 return 3;
4480 return 0;
4481}
4482
4483// words that cannot be used as a variable
4484static char *reserved[] = {
4485 "true",
4486 "false",
4487 NULL
4488};
4489
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004490typedef enum {
4491 dest_local,
4492 dest_option,
4493 dest_env,
4494 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004495 dest_buffer,
4496 dest_window,
4497 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004498 dest_vimvar,
4499 dest_script,
4500 dest_reg,
4501} assign_dest_T;
4502
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004503/*
4504 * compile "let var [= expr]", "const var = expr" and "var = expr"
4505 * "arg" points to "var".
4506 */
4507 static char_u *
4508compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4509{
4510 char_u *p;
4511 char_u *ret = NULL;
4512 int var_count = 0;
4513 int semicolon = 0;
4514 size_t varlen;
4515 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004516 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004517 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004518 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004519 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004520 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004521 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004522 int oplen = 0;
4523 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004524 type_T *type = &t_any;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004525 lvar_T *lvar = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004526 char_u *name;
4527 char_u *sp;
4528 int has_type = FALSE;
4529 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4530 int instr_count = -1;
4531
4532 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4533 if (p == NULL)
4534 return NULL;
4535 if (var_count > 0)
4536 {
4537 // TODO: let [var, var] = list
4538 emsg("Cannot handle a list yet");
4539 return NULL;
4540 }
4541
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004542 // "a: type" is declaring variable "a" with a type, not "a:".
4543 if (is_decl && p == arg + 2 && p[-1] == ':')
4544 --p;
4545
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004546 varlen = p - arg;
4547 name = vim_strnsave(arg, (int)varlen);
4548 if (name == NULL)
4549 return NULL;
4550
Bram Moolenaar080457c2020-03-03 21:53:32 +01004551 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004552 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004553 if (*arg == '&')
4554 {
4555 int cc;
4556 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004557
Bram Moolenaar080457c2020-03-03 21:53:32 +01004558 dest = dest_option;
4559 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004560 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004561 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004562 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004563 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004564 if (is_decl)
4565 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004566 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004567 goto theend;
4568 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004569 p = arg;
4570 p = find_option_end(&p, &opt_flags);
4571 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004572 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004573 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004574 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004575 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004576 }
4577 cc = *p;
4578 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004579 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004580 *p = cc;
4581 if (opt_type == -3)
4582 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004583 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004584 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004585 }
4586 if (opt_type == -2 || opt_type == 0)
4587 type = &t_string;
4588 else
4589 type = &t_number; // both number and boolean option
4590 }
4591 else if (*arg == '$')
4592 {
4593 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004594 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004595 if (is_decl)
4596 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004597 semsg(_("E1065: Cannot declare an environment variable: %s"),
4598 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004599 goto theend;
4600 }
4601 }
4602 else if (*arg == '@')
4603 {
4604 if (!valid_yank_reg(arg[1], TRUE))
4605 {
4606 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004607 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004608 }
4609 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004610 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004611 if (is_decl)
4612 {
4613 semsg(_("E1066: Cannot declare a register: %s"), name);
4614 goto theend;
4615 }
4616 }
4617 else if (STRNCMP(arg, "g:", 2) == 0)
4618 {
4619 dest = dest_global;
4620 if (is_decl)
4621 {
4622 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4623 goto theend;
4624 }
4625 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004626 else if (STRNCMP(arg, "b:", 2) == 0)
4627 {
4628 dest = dest_buffer;
4629 if (is_decl)
4630 {
4631 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4632 goto theend;
4633 }
4634 }
4635 else if (STRNCMP(arg, "w:", 2) == 0)
4636 {
4637 dest = dest_window;
4638 if (is_decl)
4639 {
4640 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4641 goto theend;
4642 }
4643 }
4644 else if (STRNCMP(arg, "t:", 2) == 0)
4645 {
4646 dest = dest_tab;
4647 if (is_decl)
4648 {
4649 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4650 goto theend;
4651 }
4652 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004653 else if (STRNCMP(arg, "v:", 2) == 0)
4654 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004655 typval_T *vtv;
4656 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004657
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004658 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004659 if (vimvaridx < 0)
4660 {
4661 semsg(_(e_var_notfound), arg);
4662 goto theend;
4663 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004664 // We use the current value of "sandbox" here, is that OK?
4665 if (var_check_ro(di_flags, name, FALSE))
4666 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004667 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004668 vtv = get_vim_var_tv(vimvaridx);
4669 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004670 if (is_decl)
4671 {
4672 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4673 goto theend;
4674 }
4675 }
4676 else
4677 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004678 int idx;
4679
Bram Moolenaar080457c2020-03-03 21:53:32 +01004680 for (idx = 0; reserved[idx] != NULL; ++idx)
4681 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004682 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004683 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004684 goto theend;
4685 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004686
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004687 lvar = lookup_local(arg, varlen, cctx);
4688 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004689 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004690 if (is_decl)
4691 {
4692 semsg(_("E1017: Variable already declared: %s"), name);
4693 goto theend;
4694 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004695 else if (lvar->lv_const)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004696 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004697 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4698 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004699 }
4700 }
4701 else if (STRNCMP(arg, "s:", 2) == 0
4702 || lookup_script(arg, varlen) == OK
4703 || find_imported(arg, varlen, cctx) != NULL)
4704 {
4705 dest = dest_script;
4706 if (is_decl)
4707 {
4708 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004709 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004710 goto theend;
4711 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004712 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004713 else if (name[1] == ':' && name[2] != NUL)
4714 {
4715 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4716 goto theend;
4717 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004718 }
4719 }
4720
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004721 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004722 {
4723 if (is_decl && *p == ':')
4724 {
4725 // parse optional type: "let var: type = expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004726 if (!VIM_ISWHITE(p[1]))
4727 {
4728 semsg(_(e_white_after), ":");
4729 goto theend;
4730 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004731 p = skipwhite(p + 1);
4732 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004733 has_type = TRUE;
4734 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004735 else if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004736 type = lvar->lv_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004737 }
4738
4739 sp = p;
4740 p = skipwhite(p);
4741 op = p;
4742 oplen = assignment_len(p, &heredoc);
4743 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4744 {
4745 char_u buf[4];
4746
4747 vim_strncpy(buf, op, oplen);
4748 semsg(_(e_white_both), buf);
4749 }
4750
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004751 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004752 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004753 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004754 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004755 goto theend;
4756 }
4757
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004758 if (lvar == NULL && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004759 {
4760 if (oplen > 1 && !heredoc)
4761 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004762 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004763 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4764 name);
4765 goto theend;
4766 }
4767
4768 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004769 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004770 goto theend;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004771 lvar = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4772 if (lvar == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004773 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004774 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004775 }
4776
4777 if (heredoc)
4778 {
4779 list_T *l;
4780 listitem_T *li;
4781
4782 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02004783 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004784 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004785 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004786
4787 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004788 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004789 {
4790 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4791 li->li_tv.vval.v_string = NULL;
4792 }
4793 generate_NEWLIST(cctx, l->lv_len);
4794 type = &t_list_string;
4795 list_free(l);
4796 p += STRLEN(p);
4797 }
4798 else if (oplen > 0)
4799 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004800 int r;
4801 type_T *stacktype;
4802 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004803
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004804 // for "+=", "*=", "..=" etc. first load the current value
4805 if (*op != '=')
4806 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004807 switch (dest)
4808 {
4809 case dest_option:
4810 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004811 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004812 break;
4813 case dest_global:
4814 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4815 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004816 case dest_buffer:
4817 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4818 break;
4819 case dest_window:
4820 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4821 break;
4822 case dest_tab:
4823 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4824 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004825 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004826 compile_load_scriptvar(cctx,
4827 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004828 break;
4829 case dest_env:
4830 // Include $ in the name here
4831 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4832 break;
4833 case dest_reg:
4834 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4835 break;
4836 case dest_vimvar:
4837 generate_LOADV(cctx, name + 2, TRUE);
4838 break;
4839 case dest_local:
Bram Moolenaarb68b3462020-05-06 21:06:30 +02004840 if (lvar->lv_from_outer)
4841 generate_LOAD(cctx, ISN_LOADOUTER, lvar->lv_idx,
4842 NULL, type);
4843 else
4844 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004845 break;
4846 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004847 }
4848
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004849 // Compile the expression. Temporarily hide the new local variable
4850 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004851 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004852 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004853 instr_count = instr->ga_len;
4854 p = skipwhite(p + oplen);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004855 r = compile_expr0(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004856 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004857 ++cctx->ctx_locals.ga_len;
4858 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004859 goto theend;
4860
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004861 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004862 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004863 stack = &cctx->ctx_type_stack;
4864 stacktype = stack->ga_len == 0 ? &t_void
4865 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004866 if (lvar != NULL && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004867 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004868 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004869 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004870 if (stacktype->tt_type == VAR_VOID)
4871 {
4872 emsg(_("E1031: Cannot use void value"));
4873 goto theend;
4874 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004875 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004876 {
4877 // An empty list or dict has a &t_void member, for a
4878 // variable that implies &t_any.
4879 if (stacktype == &t_list_empty)
4880 lvar->lv_type = &t_list_any;
4881 else if (stacktype == &t_dict_empty)
4882 lvar->lv_type = &t_dict_any;
4883 else
4884 lvar->lv_type = stacktype;
4885 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004886 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004887 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4888 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004889 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004890 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004891 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004892 }
4893 }
4894 else if (cmdidx == CMD_const)
4895 {
4896 emsg(_("E1021: const requires a value"));
4897 goto theend;
4898 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004899 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004900 {
4901 emsg(_("E1022: type or initialization required"));
4902 goto theend;
4903 }
4904 else
4905 {
4906 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004907 if (ga_grow(instr, 1) == FAIL)
4908 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004909 switch (type->tt_type)
4910 {
4911 case VAR_BOOL:
4912 generate_PUSHBOOL(cctx, VVAL_FALSE);
4913 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004914 case VAR_FLOAT:
4915#ifdef FEAT_FLOAT
4916 generate_PUSHF(cctx, 0.0);
4917#endif
4918 break;
4919 case VAR_STRING:
4920 generate_PUSHS(cctx, NULL);
4921 break;
4922 case VAR_BLOB:
4923 generate_PUSHBLOB(cctx, NULL);
4924 break;
4925 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004926 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004927 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004928 case VAR_LIST:
4929 generate_NEWLIST(cctx, 0);
4930 break;
4931 case VAR_DICT:
4932 generate_NEWDICT(cctx, 0);
4933 break;
4934 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004935 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004936 break;
4937 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004938 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004939 break;
4940 case VAR_NUMBER:
4941 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004942 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004943 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004944 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004945 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004946 generate_PUSHNR(cctx, 0);
4947 break;
4948 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004949 }
4950
4951 if (oplen > 0 && *op != '=')
4952 {
4953 type_T *expected = &t_number;
4954 garray_T *stack = &cctx->ctx_type_stack;
4955 type_T *stacktype;
4956
4957 // TODO: if type is known use float or any operation
4958
4959 if (*op == '.')
4960 expected = &t_string;
4961 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4962 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4963 goto theend;
4964
4965 if (*op == '.')
4966 generate_instr_drop(cctx, ISN_CONCAT, 1);
4967 else
4968 {
4969 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4970
4971 if (isn == NULL)
4972 goto theend;
4973 switch (*op)
4974 {
4975 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4976 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4977 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4978 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4979 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4980 }
4981 }
4982 }
4983
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004984 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004985 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004986 case dest_option:
4987 generate_STOREOPT(cctx, name + 1, opt_flags);
4988 break;
4989 case dest_global:
4990 // include g: with the name, easier to execute that way
4991 generate_STORE(cctx, ISN_STOREG, 0, name);
4992 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004993 case dest_buffer:
4994 // include b: with the name, easier to execute that way
4995 generate_STORE(cctx, ISN_STOREB, 0, name);
4996 break;
4997 case dest_window:
4998 // include w: with the name, easier to execute that way
4999 generate_STORE(cctx, ISN_STOREW, 0, name);
5000 break;
5001 case dest_tab:
5002 // include t: with the name, easier to execute that way
5003 generate_STORE(cctx, ISN_STORET, 0, name);
5004 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005005 case dest_env:
5006 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5007 break;
5008 case dest_reg:
5009 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5010 break;
5011 case dest_vimvar:
5012 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5013 break;
5014 case dest_script:
5015 {
5016 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
5017 imported_T *import = NULL;
5018 int sid = current_sctx.sc_sid;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005019 int idx;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005020
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005021 if (name[1] != ':')
5022 {
5023 import = find_imported(name, 0, cctx);
5024 if (import != NULL)
5025 sid = import->imp_sid;
5026 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005027
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005028 idx = get_script_item_idx(sid, rawname, TRUE);
5029 // TODO: specific type
5030 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005031 {
5032 char_u *name_s = name;
5033
5034 // Include s: in the name for store_var()
5035 if (name[1] != ':')
5036 {
5037 int len = (int)STRLEN(name) + 3;
5038
5039 name_s = alloc(len);
5040 if (name_s == NULL)
5041 name_s = name;
5042 else
5043 vim_snprintf((char *)name_s, len, "s:%s", name);
5044 }
5045 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
5046 if (name_s != name)
5047 vim_free(name_s);
5048 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005049 else
5050 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
5051 sid, idx, &t_any);
5052 }
5053 break;
5054 case dest_local:
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005055 if (lvar != NULL)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005056 {
5057 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005058
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005059 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
5060 // into ISN_STORENR
Bram Moolenaarb68b3462020-05-06 21:06:30 +02005061 if (!lvar->lv_from_outer && instr->ga_len == instr_count + 1
5062 && isn->isn_type == ISN_PUSHNR)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005063 {
5064 varnumber_T val = isn->isn_arg.number;
5065 garray_T *stack = &cctx->ctx_type_stack;
5066
5067 isn->isn_type = ISN_STORENR;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005068 isn->isn_arg.storenr.stnr_idx = lvar->lv_idx;
Bram Moolenaara471eea2020-03-04 22:20:26 +01005069 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005070 if (stack->ga_len > 0)
5071 --stack->ga_len;
5072 }
Bram Moolenaarb68b3462020-05-06 21:06:30 +02005073 else if (lvar->lv_from_outer)
5074 generate_STORE(cctx, ISN_STOREOUTER, lvar->lv_idx, NULL);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005075 else
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005076 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005077 }
5078 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005079 }
5080 ret = p;
5081
5082theend:
5083 vim_free(name);
5084 return ret;
5085}
5086
5087/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005088 * Check if "name" can be "unlet".
5089 */
5090 int
5091check_vim9_unlet(char_u *name)
5092{
5093 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
5094 {
5095 semsg(_("E1081: Cannot unlet %s"), name);
5096 return FAIL;
5097 }
5098 return OK;
5099}
5100
5101/*
5102 * Callback passed to ex_unletlock().
5103 */
5104 static int
5105compile_unlet(
5106 lval_T *lvp,
5107 char_u *name_end,
5108 exarg_T *eap,
5109 int deep UNUSED,
5110 void *coookie)
5111{
5112 cctx_T *cctx = coookie;
5113
5114 if (lvp->ll_tv == NULL)
5115 {
5116 char_u *p = lvp->ll_name;
5117 int cc = *name_end;
5118 int ret = OK;
5119
5120 // Normal name. Only supports g:, w:, t: and b: namespaces.
5121 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005122 if (*p == '$')
5123 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
5124 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005125 ret = FAIL;
5126 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005127 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005128
5129 *name_end = cc;
5130 return ret;
5131 }
5132
5133 // TODO: unlet {list}[idx]
5134 // TODO: unlet {dict}[key]
5135 emsg("Sorry, :unlet not fully implemented yet");
5136 return FAIL;
5137}
5138
5139/*
5140 * compile "unlet var", "lock var" and "unlock var"
5141 * "arg" points to "var".
5142 */
5143 static char_u *
5144compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
5145{
5146 char_u *p = arg;
5147
5148 if (eap->cmdidx != CMD_unlet)
5149 {
5150 emsg("Sorry, :lock and unlock not implemented yet");
5151 return NULL;
5152 }
5153
5154 if (*p == '!')
5155 {
5156 p = skipwhite(p + 1);
5157 eap->forceit = TRUE;
5158 }
5159
5160 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
5161 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5162}
5163
5164/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005165 * Compile an :import command.
5166 */
5167 static char_u *
5168compile_import(char_u *arg, cctx_T *cctx)
5169{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01005170 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005171}
5172
5173/*
5174 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
5175 */
5176 static int
5177compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
5178{
5179 garray_T *instr = &cctx->ctx_instr;
5180 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
5181
5182 if (endlabel == NULL)
5183 return FAIL;
5184 endlabel->el_next = *el;
5185 *el = endlabel;
5186 endlabel->el_end_label = instr->ga_len;
5187
5188 generate_JUMP(cctx, when, 0);
5189 return OK;
5190}
5191
5192 static void
5193compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
5194{
5195 garray_T *instr = &cctx->ctx_instr;
5196
5197 while (*el != NULL)
5198 {
5199 endlabel_T *cur = (*el);
5200 isn_T *isn;
5201
5202 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
5203 isn->isn_arg.jump.jump_where = instr->ga_len;
5204 *el = cur->el_next;
5205 vim_free(cur);
5206 }
5207}
5208
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005209 static void
5210compile_free_jump_to_end(endlabel_T **el)
5211{
5212 while (*el != NULL)
5213 {
5214 endlabel_T *cur = (*el);
5215
5216 *el = cur->el_next;
5217 vim_free(cur);
5218 }
5219}
5220
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005221/*
5222 * Create a new scope and set up the generic items.
5223 */
5224 static scope_T *
5225new_scope(cctx_T *cctx, scopetype_T type)
5226{
5227 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
5228
5229 if (scope == NULL)
5230 return NULL;
5231 scope->se_outer = cctx->ctx_scope;
5232 cctx->ctx_scope = scope;
5233 scope->se_type = type;
5234 scope->se_local_count = cctx->ctx_locals.ga_len;
5235 return scope;
5236}
5237
5238/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005239 * Free the current scope and go back to the outer scope.
5240 */
5241 static void
5242drop_scope(cctx_T *cctx)
5243{
5244 scope_T *scope = cctx->ctx_scope;
5245
5246 if (scope == NULL)
5247 {
5248 iemsg("calling drop_scope() without a scope");
5249 return;
5250 }
5251 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005252 switch (scope->se_type)
5253 {
5254 case IF_SCOPE:
5255 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
5256 case FOR_SCOPE:
5257 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
5258 case WHILE_SCOPE:
5259 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
5260 case TRY_SCOPE:
5261 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
5262 case NO_SCOPE:
5263 case BLOCK_SCOPE:
5264 break;
5265 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005266 vim_free(scope);
5267}
5268
5269/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005270 * compile "if expr"
5271 *
5272 * "if expr" Produces instructions:
5273 * EVAL expr Push result of "expr"
5274 * JUMP_IF_FALSE end
5275 * ... body ...
5276 * end:
5277 *
5278 * "if expr | else" Produces instructions:
5279 * EVAL expr Push result of "expr"
5280 * JUMP_IF_FALSE else
5281 * ... body ...
5282 * JUMP_ALWAYS end
5283 * else:
5284 * ... body ...
5285 * end:
5286 *
5287 * "if expr1 | elseif expr2 | else" Produces instructions:
5288 * EVAL expr Push result of "expr"
5289 * JUMP_IF_FALSE elseif
5290 * ... body ...
5291 * JUMP_ALWAYS end
5292 * elseif:
5293 * EVAL expr Push result of "expr"
5294 * JUMP_IF_FALSE else
5295 * ... body ...
5296 * JUMP_ALWAYS end
5297 * else:
5298 * ... body ...
5299 * end:
5300 */
5301 static char_u *
5302compile_if(char_u *arg, cctx_T *cctx)
5303{
5304 char_u *p = arg;
5305 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005306 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005307 scope_T *scope;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005308 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005309
Bram Moolenaara5565e42020-05-09 15:44:01 +02005310 CLEAR_FIELD(ppconst);
5311 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005312 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02005313 clear_ppconst(&ppconst);
5314 return NULL;
5315 }
5316 if (instr->ga_len == instr_count && ppconst.pp_used == 1)
5317 {
5318 // The expression results in a constant.
5319 // TODO: how about nesting?
5320 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? FALSE : TRUE;
5321 clear_ppconst(&ppconst);
5322 }
5323 else
5324 {
5325 // Not a constant, generate instructions for the expression.
5326 cctx->ctx_skip = MAYBE;
5327 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005328 return NULL;
5329 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005330
5331 scope = new_scope(cctx, IF_SCOPE);
5332 if (scope == NULL)
5333 return NULL;
5334
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005335 if (cctx->ctx_skip == MAYBE)
5336 {
5337 // "where" is set when ":elseif", "else" or ":endif" is found
5338 scope->se_u.se_if.is_if_label = instr->ga_len;
5339 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5340 }
5341 else
5342 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005343
5344 return p;
5345}
5346
5347 static char_u *
5348compile_elseif(char_u *arg, cctx_T *cctx)
5349{
5350 char_u *p = arg;
5351 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005352 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005353 isn_T *isn;
5354 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005355 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005356
5357 if (scope == NULL || scope->se_type != IF_SCOPE)
5358 {
5359 emsg(_(e_elseif_without_if));
5360 return NULL;
5361 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005362 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005363
Bram Moolenaar158906c2020-02-06 20:39:45 +01005364 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005365 {
5366 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005367 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005368 return NULL;
5369 // previous "if" or "elseif" jumps here
5370 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5371 isn->isn_arg.jump.jump_where = instr->ga_len;
5372 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005373
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005374 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02005375 CLEAR_FIELD(ppconst);
5376 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005377 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02005378 clear_ppconst(&ppconst);
5379 return NULL;
5380 }
5381 if (instr->ga_len == instr_count && ppconst.pp_used == 1)
5382 {
5383 // The expression results in a constant.
5384 // TODO: how about nesting?
5385 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? FALSE : TRUE;
5386 clear_ppconst(&ppconst);
5387 scope->se_u.se_if.is_if_label = -1;
5388 }
5389 else
5390 {
5391 // Not a constant, generate instructions for the expression.
5392 cctx->ctx_skip = MAYBE;
5393 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005394 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005395
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005396 // "where" is set when ":elseif", "else" or ":endif" is found
5397 scope->se_u.se_if.is_if_label = instr->ga_len;
5398 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5399 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005400
5401 return p;
5402}
5403
5404 static char_u *
5405compile_else(char_u *arg, cctx_T *cctx)
5406{
5407 char_u *p = arg;
5408 garray_T *instr = &cctx->ctx_instr;
5409 isn_T *isn;
5410 scope_T *scope = cctx->ctx_scope;
5411
5412 if (scope == NULL || scope->se_type != IF_SCOPE)
5413 {
5414 emsg(_(e_else_without_if));
5415 return NULL;
5416 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005417 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005418
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005419 // jump from previous block to the end, unless the else block is empty
5420 if (cctx->ctx_skip == MAYBE)
5421 {
5422 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005423 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005424 return NULL;
5425 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005426
Bram Moolenaar158906c2020-02-06 20:39:45 +01005427 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005428 {
5429 if (scope->se_u.se_if.is_if_label >= 0)
5430 {
5431 // previous "if" or "elseif" jumps here
5432 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5433 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005434 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005435 }
5436 }
5437
5438 if (cctx->ctx_skip != MAYBE)
5439 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005440
5441 return p;
5442}
5443
5444 static char_u *
5445compile_endif(char_u *arg, cctx_T *cctx)
5446{
5447 scope_T *scope = cctx->ctx_scope;
5448 ifscope_T *ifscope;
5449 garray_T *instr = &cctx->ctx_instr;
5450 isn_T *isn;
5451
5452 if (scope == NULL || scope->se_type != IF_SCOPE)
5453 {
5454 emsg(_(e_endif_without_if));
5455 return NULL;
5456 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005457 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005458 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005459
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005460 if (scope->se_u.se_if.is_if_label >= 0)
5461 {
5462 // previous "if" or "elseif" jumps here
5463 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5464 isn->isn_arg.jump.jump_where = instr->ga_len;
5465 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005466 // Fill in the "end" label in jumps at the end of the blocks.
5467 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005468 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005469
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005470 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005471 return arg;
5472}
5473
5474/*
5475 * compile "for var in expr"
5476 *
5477 * Produces instructions:
5478 * PUSHNR -1
5479 * STORE loop-idx Set index to -1
5480 * EVAL expr Push result of "expr"
5481 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5482 * - if beyond end, jump to "end"
5483 * - otherwise get item from list and push it
5484 * STORE var Store item in "var"
5485 * ... body ...
5486 * JUMP top Jump back to repeat
5487 * end: DROP Drop the result of "expr"
5488 *
5489 */
5490 static char_u *
5491compile_for(char_u *arg, cctx_T *cctx)
5492{
5493 char_u *p;
5494 size_t varlen;
5495 garray_T *instr = &cctx->ctx_instr;
5496 garray_T *stack = &cctx->ctx_type_stack;
5497 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005498 lvar_T *loop_lvar; // loop iteration variable
5499 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005500 type_T *vartype;
5501
5502 // TODO: list of variables: "for [key, value] in dict"
5503 // parse "var"
5504 for (p = arg; eval_isnamec1(*p); ++p)
5505 ;
5506 varlen = p - arg;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005507 var_lvar = lookup_local(arg, varlen, cctx);
5508 if (var_lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005509 {
5510 semsg(_("E1023: variable already defined: %s"), arg);
5511 return NULL;
5512 }
5513
5514 // consume "in"
5515 p = skipwhite(p);
5516 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5517 {
5518 emsg(_(e_missing_in));
5519 return NULL;
5520 }
5521 p = skipwhite(p + 2);
5522
5523
5524 scope = new_scope(cctx, FOR_SCOPE);
5525 if (scope == NULL)
5526 return NULL;
5527
5528 // Reserve a variable to store the loop iteration counter.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005529 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5530 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005531 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005532 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005533 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005534 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005535 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005536
5537 // Reserve a variable to store "var"
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005538 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5539 if (var_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005540 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005541 // out of memory or used as an argument
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005542 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005543 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005544 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005545
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005546 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005547
5548 // compile "expr", it remains on the stack until "endfor"
5549 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005550 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005551 {
5552 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005553 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005554 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005555
5556 // now we know the type of "var"
5557 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5558 if (vartype->tt_type != VAR_LIST)
5559 {
5560 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005561 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005562 return NULL;
5563 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005564 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005565 var_lvar->lv_type = vartype->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005566
5567 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005568 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005569
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005570 generate_FOR(cctx, loop_lvar->lv_idx);
5571 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005572
5573 return arg;
5574}
5575
5576/*
5577 * compile "endfor"
5578 */
5579 static char_u *
5580compile_endfor(char_u *arg, cctx_T *cctx)
5581{
5582 garray_T *instr = &cctx->ctx_instr;
5583 scope_T *scope = cctx->ctx_scope;
5584 forscope_T *forscope;
5585 isn_T *isn;
5586
5587 if (scope == NULL || scope->se_type != FOR_SCOPE)
5588 {
5589 emsg(_(e_for));
5590 return NULL;
5591 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005592 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005593 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005594 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005595
5596 // At end of ":for" scope jump back to the FOR instruction.
5597 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5598
5599 // Fill in the "end" label in the FOR statement so it can jump here
5600 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5601 isn->isn_arg.forloop.for_end = instr->ga_len;
5602
5603 // Fill in the "end" label any BREAK statements
5604 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5605
5606 // Below the ":for" scope drop the "expr" list from the stack.
5607 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5608 return NULL;
5609
5610 vim_free(scope);
5611
5612 return arg;
5613}
5614
5615/*
5616 * compile "while expr"
5617 *
5618 * Produces instructions:
5619 * top: EVAL expr Push result of "expr"
5620 * JUMP_IF_FALSE end jump if false
5621 * ... body ...
5622 * JUMP top Jump back to repeat
5623 * end:
5624 *
5625 */
5626 static char_u *
5627compile_while(char_u *arg, cctx_T *cctx)
5628{
5629 char_u *p = arg;
5630 garray_T *instr = &cctx->ctx_instr;
5631 scope_T *scope;
5632
5633 scope = new_scope(cctx, WHILE_SCOPE);
5634 if (scope == NULL)
5635 return NULL;
5636
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005637 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005638
5639 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02005640 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005641 return NULL;
5642
5643 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005644 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005645 JUMP_IF_FALSE, cctx) == FAIL)
5646 return FAIL;
5647
5648 return p;
5649}
5650
5651/*
5652 * compile "endwhile"
5653 */
5654 static char_u *
5655compile_endwhile(char_u *arg, cctx_T *cctx)
5656{
5657 scope_T *scope = cctx->ctx_scope;
5658
5659 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5660 {
5661 emsg(_(e_while));
5662 return NULL;
5663 }
5664 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005665 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005666
5667 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005668 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005669
5670 // Fill in the "end" label in the WHILE statement so it can jump here.
5671 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005672 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005673
5674 vim_free(scope);
5675
5676 return arg;
5677}
5678
5679/*
5680 * compile "continue"
5681 */
5682 static char_u *
5683compile_continue(char_u *arg, cctx_T *cctx)
5684{
5685 scope_T *scope = cctx->ctx_scope;
5686
5687 for (;;)
5688 {
5689 if (scope == NULL)
5690 {
5691 emsg(_(e_continue));
5692 return NULL;
5693 }
5694 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5695 break;
5696 scope = scope->se_outer;
5697 }
5698
5699 // Jump back to the FOR or WHILE instruction.
5700 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005701 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5702 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005703 return arg;
5704}
5705
5706/*
5707 * compile "break"
5708 */
5709 static char_u *
5710compile_break(char_u *arg, cctx_T *cctx)
5711{
5712 scope_T *scope = cctx->ctx_scope;
5713 endlabel_T **el;
5714
5715 for (;;)
5716 {
5717 if (scope == NULL)
5718 {
5719 emsg(_(e_break));
5720 return NULL;
5721 }
5722 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5723 break;
5724 scope = scope->se_outer;
5725 }
5726
5727 // Jump to the end of the FOR or WHILE loop.
5728 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005729 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005730 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005731 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005732 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5733 return FAIL;
5734
5735 return arg;
5736}
5737
5738/*
5739 * compile "{" start of block
5740 */
5741 static char_u *
5742compile_block(char_u *arg, cctx_T *cctx)
5743{
5744 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5745 return NULL;
5746 return skipwhite(arg + 1);
5747}
5748
5749/*
5750 * compile end of block: drop one scope
5751 */
5752 static void
5753compile_endblock(cctx_T *cctx)
5754{
5755 scope_T *scope = cctx->ctx_scope;
5756
5757 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005758 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005759 vim_free(scope);
5760}
5761
5762/*
5763 * compile "try"
5764 * Creates a new scope for the try-endtry, pointing to the first catch and
5765 * finally.
5766 * Creates another scope for the "try" block itself.
5767 * TRY instruction sets up exception handling at runtime.
5768 *
5769 * "try"
5770 * TRY -> catch1, -> finally push trystack entry
5771 * ... try block
5772 * "throw {exception}"
5773 * EVAL {exception}
5774 * THROW create exception
5775 * ... try block
5776 * " catch {expr}"
5777 * JUMP -> finally
5778 * catch1: PUSH exeception
5779 * EVAL {expr}
5780 * MATCH
5781 * JUMP nomatch -> catch2
5782 * CATCH remove exception
5783 * ... catch block
5784 * " catch"
5785 * JUMP -> finally
5786 * catch2: CATCH remove exception
5787 * ... catch block
5788 * " finally"
5789 * finally:
5790 * ... finally block
5791 * " endtry"
5792 * ENDTRY pop trystack entry, may rethrow
5793 */
5794 static char_u *
5795compile_try(char_u *arg, cctx_T *cctx)
5796{
5797 garray_T *instr = &cctx->ctx_instr;
5798 scope_T *try_scope;
5799 scope_T *scope;
5800
5801 // scope that holds the jumps that go to catch/finally/endtry
5802 try_scope = new_scope(cctx, TRY_SCOPE);
5803 if (try_scope == NULL)
5804 return NULL;
5805
5806 // "catch" is set when the first ":catch" is found.
5807 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005808 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005809 if (generate_instr(cctx, ISN_TRY) == NULL)
5810 return NULL;
5811
5812 // scope for the try block itself
5813 scope = new_scope(cctx, BLOCK_SCOPE);
5814 if (scope == NULL)
5815 return NULL;
5816
5817 return arg;
5818}
5819
5820/*
5821 * compile "catch {expr}"
5822 */
5823 static char_u *
5824compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5825{
5826 scope_T *scope = cctx->ctx_scope;
5827 garray_T *instr = &cctx->ctx_instr;
5828 char_u *p;
5829 isn_T *isn;
5830
5831 // end block scope from :try or :catch
5832 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5833 compile_endblock(cctx);
5834 scope = cctx->ctx_scope;
5835
5836 // Error if not in a :try scope
5837 if (scope == NULL || scope->se_type != TRY_SCOPE)
5838 {
5839 emsg(_(e_catch));
5840 return NULL;
5841 }
5842
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005843 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005844 {
5845 emsg(_("E1033: catch unreachable after catch-all"));
5846 return NULL;
5847 }
5848
5849 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005850 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005851 JUMP_ALWAYS, cctx) == FAIL)
5852 return NULL;
5853
5854 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005855 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005856 if (isn->isn_arg.try.try_catch == 0)
5857 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005858 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005859 {
5860 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005861 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005862 isn->isn_arg.jump.jump_where = instr->ga_len;
5863 }
5864
5865 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005866 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005867 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005868 scope->se_u.se_try.ts_caught_all = TRUE;
5869 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005870 }
5871 else
5872 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005873 char_u *end;
5874 char_u *pat;
5875 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005876 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005877 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005878
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005879 // Push v:exception, push {expr} and MATCH
5880 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5881
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005882 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005883 if (*end != *p)
5884 {
5885 semsg(_("E1067: Separator mismatch: %s"), p);
5886 vim_free(tofree);
5887 return FAIL;
5888 }
5889 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005890 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005891 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005892 len = (int)(end - tofree);
5893 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005894 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005895 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005896 if (pat == NULL)
5897 return FAIL;
5898 if (generate_PUSHS(cctx, pat) == FAIL)
5899 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005900
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005901 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5902 return NULL;
5903
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005904 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005905 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5906 return NULL;
5907 }
5908
5909 if (generate_instr(cctx, ISN_CATCH) == NULL)
5910 return NULL;
5911
5912 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5913 return NULL;
5914 return p;
5915}
5916
5917 static char_u *
5918compile_finally(char_u *arg, cctx_T *cctx)
5919{
5920 scope_T *scope = cctx->ctx_scope;
5921 garray_T *instr = &cctx->ctx_instr;
5922 isn_T *isn;
5923
5924 // end block scope from :try or :catch
5925 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5926 compile_endblock(cctx);
5927 scope = cctx->ctx_scope;
5928
5929 // Error if not in a :try scope
5930 if (scope == NULL || scope->se_type != TRY_SCOPE)
5931 {
5932 emsg(_(e_finally));
5933 return NULL;
5934 }
5935
5936 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005937 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005938 if (isn->isn_arg.try.try_finally != 0)
5939 {
5940 emsg(_(e_finally_dup));
5941 return NULL;
5942 }
5943
5944 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005945 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005946
Bram Moolenaar585fea72020-04-02 22:33:21 +02005947 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005948 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005949 {
5950 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005951 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005952 isn->isn_arg.jump.jump_where = instr->ga_len;
5953 }
5954
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005955 // TODO: set index in ts_finally_label jumps
5956
5957 return arg;
5958}
5959
5960 static char_u *
5961compile_endtry(char_u *arg, cctx_T *cctx)
5962{
5963 scope_T *scope = cctx->ctx_scope;
5964 garray_T *instr = &cctx->ctx_instr;
5965 isn_T *isn;
5966
5967 // end block scope from :catch or :finally
5968 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5969 compile_endblock(cctx);
5970 scope = cctx->ctx_scope;
5971
5972 // Error if not in a :try scope
5973 if (scope == NULL || scope->se_type != TRY_SCOPE)
5974 {
5975 if (scope == NULL)
5976 emsg(_(e_no_endtry));
5977 else if (scope->se_type == WHILE_SCOPE)
5978 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005979 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005980 emsg(_(e_endfor));
5981 else
5982 emsg(_(e_endif));
5983 return NULL;
5984 }
5985
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005986 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005987 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5988 {
5989 emsg(_("E1032: missing :catch or :finally"));
5990 return NULL;
5991 }
5992
5993 // Fill in the "end" label in jumps at the end of the blocks, if not done
5994 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005995 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005996
5997 // End :catch or :finally scope: set value in ISN_TRY instruction
5998 if (isn->isn_arg.try.try_finally == 0)
5999 isn->isn_arg.try.try_finally = instr->ga_len;
6000 compile_endblock(cctx);
6001
6002 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
6003 return NULL;
6004 return arg;
6005}
6006
6007/*
6008 * compile "throw {expr}"
6009 */
6010 static char_u *
6011compile_throw(char_u *arg, cctx_T *cctx UNUSED)
6012{
6013 char_u *p = skipwhite(arg);
6014
Bram Moolenaara5565e42020-05-09 15:44:01 +02006015 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006016 return NULL;
6017 if (may_generate_2STRING(-1, cctx) == FAIL)
6018 return NULL;
6019 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
6020 return NULL;
6021
6022 return p;
6023}
6024
6025/*
6026 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006027 * compile "echomsg expr"
6028 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01006029 * compile "execute expr"
6030 */
6031 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006032compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006033{
6034 char_u *p = arg;
6035 int count = 0;
6036
6037 for (;;)
6038 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006039 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006040 return NULL;
6041 ++count;
6042 p = skipwhite(p);
6043 if (ends_excmd(*p))
6044 break;
6045 }
6046
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006047 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
6048 generate_ECHO(cctx, cmdidx == CMD_echo, count);
6049 else if (cmdidx == CMD_execute)
6050 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
6051 else if (cmdidx == CMD_echomsg)
6052 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
6053 else
6054 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006055 return p;
6056}
6057
6058/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006059 * A command that is not compiled, execute with legacy code.
6060 */
6061 static char_u *
6062compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
6063{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006064 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006065 int has_expr = FALSE;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006066
6067 if (cctx->ctx_skip == TRUE)
6068 goto theend;
6069
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006070 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
6071 has_expr = (excmd_get_argt(eap->cmdidx) & (EX_XFILE | EX_EXPAND));
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006072 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
6073 {
6074 // expand filename in "syntax include [@group] filename"
6075 has_expr = TRUE;
6076 eap->arg = skipwhite(eap->arg + 7);
6077 if (*eap->arg == '@')
6078 eap->arg = skiptowhite(eap->arg);
6079 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006080
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006081 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006082 {
6083 int count = 0;
6084 char_u *start = skipwhite(line);
6085
6086 // :cmd xxx`=expr1`yyy`=expr2`zzz
6087 // PUSHS ":cmd xxx"
6088 // eval expr1
6089 // PUSHS "yyy"
6090 // eval expr2
6091 // PUSHS "zzz"
6092 // EXECCONCAT 5
6093 for (;;)
6094 {
6095 if (p > start)
6096 {
6097 generate_PUSHS(cctx, vim_strnsave(start, (int)(p - start)));
6098 ++count;
6099 }
6100 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006101 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006102 return NULL;
6103 may_generate_2STRING(-1, cctx);
6104 ++count;
6105 p = skipwhite(p);
6106 if (*p != '`')
6107 {
6108 emsg(_("E1083: missing backtick"));
6109 return NULL;
6110 }
6111 start = p + 1;
6112
6113 p = (char_u *)strstr((char *)start, "`=");
6114 if (p == NULL)
6115 {
6116 if (*skipwhite(start) != NUL)
6117 {
6118 generate_PUSHS(cctx, vim_strsave(start));
6119 ++count;
6120 }
6121 break;
6122 }
6123 }
6124 generate_EXECCONCAT(cctx, count);
6125 }
6126 else
6127 generate_EXEC(cctx, line);
6128
6129theend:
6130 return (char_u *)"";
6131}
6132
6133/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006134 * After ex_function() has collected all the function lines: parse and compile
6135 * the lines into instructions.
6136 * Adds the function to "def_functions".
6137 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
6138 * return statement (used for lambda).
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006139 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006140 * This can be used recursively through compile_lambda(), which may reallocate
6141 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006142 */
6143 void
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006144compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006145{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006146 char_u *line = NULL;
6147 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006148 char *errormsg = NULL; // error message
6149 int had_return = FALSE;
6150 cctx_T cctx;
6151 garray_T *instr;
6152 int called_emsg_before = called_emsg;
6153 int ret = FAIL;
6154 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006155 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006156
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006157 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006158 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01006159
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006160 if (ufunc->uf_dfunc_idx >= 0)
6161 {
6162 // Redefining a function that was compiled before.
6163 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
6164
6165 // Free old instructions.
6166 delete_def_function_contents(dfunc);
6167 }
6168 else
6169 {
6170 // Add the function to "def_functions".
6171 if (ga_grow(&def_functions, 1) == FAIL)
6172 return;
6173 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006174 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006175 dfunc->df_idx = def_functions.ga_len;
6176 ufunc->uf_dfunc_idx = dfunc->df_idx;
6177 dfunc->df_ufunc = ufunc;
6178 ++def_functions.ga_len;
6179 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006180 }
6181
Bram Moolenaara80faa82020-04-12 19:37:17 +02006182 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006183 cctx.ctx_ufunc = ufunc;
6184 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006185 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006186 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
6187 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
6188 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
6189 cctx.ctx_type_list = &ufunc->uf_type_list;
6190 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
6191 instr = &cctx.ctx_instr;
6192
6193 // Most modern script version.
6194 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
6195
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006196 if (ufunc->uf_def_args.ga_len > 0)
6197 {
6198 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006199 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006200 int i;
6201 char_u *arg;
6202 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
6203
6204 // Produce instructions for the default values of optional arguments.
6205 // Store the instruction index in uf_def_arg_idx[] so that we know
6206 // where to start when the function is called, depending on the number
6207 // of arguments.
6208 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
6209 if (ufunc->uf_def_arg_idx == NULL)
6210 goto erret;
6211 for (i = 0; i < count; ++i)
6212 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006213 garray_T *stack = &cctx.ctx_type_stack;
6214 type_T *val_type;
6215 int arg_idx = first_def_arg + i;
6216
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006217 ufunc->uf_def_arg_idx[i] = instr->ga_len;
6218 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaara5565e42020-05-09 15:44:01 +02006219 if (compile_expr0(&arg, &cctx) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006220 goto erret;
6221
6222 // If no type specified use the type of the default value.
6223 // Otherwise check that the default value type matches the
6224 // specified type.
6225 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6226 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
6227 ufunc->uf_arg_types[arg_idx] = val_type;
6228 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
6229 == FAIL)
6230 {
6231 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
6232 arg_idx + 1);
6233 goto erret;
6234 }
6235
6236 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006237 goto erret;
6238 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006239 ufunc->uf_def_arg_idx[count] = instr->ga_len;
6240 }
6241
6242 /*
6243 * Loop over all the lines of the function and generate instructions.
6244 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006245 for (;;)
6246 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006247 exarg_T ea;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006248 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006249
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006250 // Bail out on the first error to avoid a flood of errors and report
6251 // the right line number when inside try/catch.
6252 if (emsg_before != called_emsg)
6253 goto erret;
6254
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006255 if (line != NULL && *line == '|')
6256 // the line continues after a '|'
6257 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02006258 else if (line != NULL && *line != NUL
6259 && !(*line == '#' && (line == cctx.ctx_line_start
6260 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006261 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006262 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006263 goto erret;
6264 }
6265 else
6266 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006267 line = next_line_from_context(&cctx);
6268 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006269 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006270 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006271 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006272 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006273
6274 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006275 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006276 ea.cmdlinep = &line;
6277 ea.cmd = skipwhite(line);
6278
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006279 // Some things can be recognized by the first character.
6280 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006281 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006282 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006283 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006284 if (ea.cmd[1] != '{')
6285 {
6286 line = (char_u *)"";
6287 continue;
6288 }
6289 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006290
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006291 case '}':
6292 {
6293 // "}" ends a block scope
6294 scopetype_T stype = cctx.ctx_scope == NULL
6295 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006296
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006297 if (stype == BLOCK_SCOPE)
6298 {
6299 compile_endblock(&cctx);
6300 line = ea.cmd;
6301 }
6302 else
6303 {
6304 emsg(_("E1025: using } outside of a block scope"));
6305 goto erret;
6306 }
6307 if (line != NULL)
6308 line = skipwhite(ea.cmd + 1);
6309 continue;
6310 }
6311
6312 case '{':
6313 // "{" starts a block scope
6314 // "{'a': 1}->func() is something else
6315 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6316 {
6317 line = compile_block(ea.cmd, &cctx);
6318 continue;
6319 }
6320 break;
6321
6322 case ':':
6323 is_ex_command = TRUE;
6324 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006325 }
6326
6327 /*
6328 * COMMAND MODIFIERS
6329 */
6330 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6331 {
6332 if (errormsg != NULL)
6333 goto erret;
6334 // empty line or comment
6335 line = (char_u *)"";
6336 continue;
6337 }
6338
6339 // Skip ":call" to get to the function name.
6340 if (checkforcmd(&ea.cmd, "call", 3))
6341 ea.cmd = skipwhite(ea.cmd);
6342
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006343 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006344 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006345 // Assuming the command starts with a variable or function name,
6346 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6347 // val".
6348 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6349 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006350 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006351 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006352 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006353 int oplen;
6354 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006355
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006356 oplen = assignment_len(skipwhite(p), &heredoc);
6357 if (oplen > 0)
6358 {
6359 // Recognize an assignment if we recognize the variable
6360 // name:
6361 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006362 // "local = expr" where "local" is a local var.
6363 // "script = expr" where "script" is a script-local var.
6364 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006365 // "&opt = expr"
6366 // "$ENV = expr"
6367 // "@r = expr"
6368 if (*ea.cmd == '&'
6369 || *ea.cmd == '$'
6370 || *ea.cmd == '@'
6371 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006372 || lookup_local(ea.cmd, p - ea.cmd, &cctx) != NULL
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006373 || lookup_script(ea.cmd, p - ea.cmd) == OK
6374 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6375 {
6376 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6377 if (line == NULL)
6378 goto erret;
6379 continue;
6380 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006381 }
6382 }
6383 }
6384
6385 /*
6386 * COMMAND after range
6387 */
6388 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006389 p = find_ex_command(&ea, NULL, is_ex_command ? NULL
6390 : (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006391 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006392
6393 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6394 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006395 if (cctx.ctx_skip == TRUE)
6396 {
6397 line += STRLEN(line);
6398 continue;
6399 }
6400
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006401 // Expression or function call.
6402 if (ea.cmdidx == CMD_eval)
6403 {
6404 p = ea.cmd;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006405 if (compile_expr0(&p, &cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006406 goto erret;
6407
6408 // drop the return value
6409 generate_instr_drop(&cctx, ISN_DROP, 1);
6410 line = p;
6411 continue;
6412 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006413 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006414 iemsg("Command from find_ex_command() not handled");
6415 goto erret;
6416 }
6417
6418 p = skipwhite(p);
6419
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006420 if (cctx.ctx_skip == TRUE
6421 && ea.cmdidx != CMD_elseif
6422 && ea.cmdidx != CMD_else
6423 && ea.cmdidx != CMD_endif)
6424 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006425 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006426 continue;
6427 }
6428
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006429 switch (ea.cmdidx)
6430 {
6431 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006432 ea.arg = p;
6433 line = compile_nested_function(&ea, &cctx);
6434 break;
6435
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006436 case CMD_function:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006437 emsg(_("E1086: Cannot use :function inside :def"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006438 goto erret;
6439
6440 case CMD_return:
6441 line = compile_return(p, set_return_type, &cctx);
6442 had_return = TRUE;
6443 break;
6444
6445 case CMD_let:
6446 case CMD_const:
6447 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6448 break;
6449
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006450 case CMD_unlet:
6451 case CMD_unlockvar:
6452 case CMD_lockvar:
6453 line = compile_unletlock(p, &ea, &cctx);
6454 break;
6455
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006456 case CMD_import:
6457 line = compile_import(p, &cctx);
6458 break;
6459
6460 case CMD_if:
6461 line = compile_if(p, &cctx);
6462 break;
6463 case CMD_elseif:
6464 line = compile_elseif(p, &cctx);
6465 break;
6466 case CMD_else:
6467 line = compile_else(p, &cctx);
6468 break;
6469 case CMD_endif:
6470 line = compile_endif(p, &cctx);
6471 break;
6472
6473 case CMD_while:
6474 line = compile_while(p, &cctx);
6475 break;
6476 case CMD_endwhile:
6477 line = compile_endwhile(p, &cctx);
6478 break;
6479
6480 case CMD_for:
6481 line = compile_for(p, &cctx);
6482 break;
6483 case CMD_endfor:
6484 line = compile_endfor(p, &cctx);
6485 break;
6486 case CMD_continue:
6487 line = compile_continue(p, &cctx);
6488 break;
6489 case CMD_break:
6490 line = compile_break(p, &cctx);
6491 break;
6492
6493 case CMD_try:
6494 line = compile_try(p, &cctx);
6495 break;
6496 case CMD_catch:
6497 line = compile_catch(p, &cctx);
6498 break;
6499 case CMD_finally:
6500 line = compile_finally(p, &cctx);
6501 break;
6502 case CMD_endtry:
6503 line = compile_endtry(p, &cctx);
6504 break;
6505 case CMD_throw:
6506 line = compile_throw(p, &cctx);
6507 break;
6508
6509 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006510 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006511 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006512 case CMD_echomsg:
6513 case CMD_echoerr:
6514 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006515 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006516
6517 default:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006518 // TODO: other commands with an expression argument
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006519 // Not recognized, execute with do_cmdline_cmd().
6520 ea.arg = p;
6521 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006522 break;
6523 }
6524 if (line == NULL)
6525 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006526 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006527
6528 if (cctx.ctx_type_stack.ga_len < 0)
6529 {
6530 iemsg("Type stack underflow");
6531 goto erret;
6532 }
6533 }
6534
6535 if (cctx.ctx_scope != NULL)
6536 {
6537 if (cctx.ctx_scope->se_type == IF_SCOPE)
6538 emsg(_(e_endif));
6539 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6540 emsg(_(e_endwhile));
6541 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6542 emsg(_(e_endfor));
6543 else
6544 emsg(_("E1026: Missing }"));
6545 goto erret;
6546 }
6547
6548 if (!had_return)
6549 {
6550 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6551 {
6552 emsg(_("E1027: Missing return statement"));
6553 goto erret;
6554 }
6555
6556 // Return zero if there is no return at the end.
6557 generate_PUSHNR(&cctx, 0);
6558 generate_instr(&cctx, ISN_RETURN);
6559 }
6560
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006561 {
6562 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6563 + ufunc->uf_dfunc_idx;
6564 dfunc->df_deleted = FALSE;
6565 dfunc->df_instr = instr->ga_data;
6566 dfunc->df_instr_count = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006567 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02006568 dfunc->df_closure_count = cctx.ctx_closure_count;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006569 if (cctx.ctx_outer_used)
6570 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006571 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006572
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006573 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006574 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006575 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006576
6577 // Create a type for the function, with the return type and any
6578 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006579 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6580 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006581 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006582 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006583 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6584 argcount, &ufunc->uf_type_list);
6585 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006586 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006587 argcount + varargs,
6588 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006589 {
6590 ret = FAIL;
6591 goto erret;
6592 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006593 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6594 ufunc->uf_func_type->tt_min_argcount =
6595 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006596 if (ufunc->uf_arg_types == NULL)
6597 {
6598 int i;
6599
6600 // lambda does not have argument types.
6601 for (i = 0; i < argcount; ++i)
6602 ufunc->uf_func_type->tt_args[i] = &t_any;
6603 }
6604 else
6605 mch_memmove(ufunc->uf_func_type->tt_args,
6606 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006607 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006608 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006609 ufunc->uf_func_type->tt_args[argcount] =
6610 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006611 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6612 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006613 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006614 else
6615 // No arguments, can use a predefined type.
6616 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6617 argcount, &ufunc->uf_type_list);
6618
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006619 }
6620
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006621 ret = OK;
6622
6623erret:
6624 if (ret == FAIL)
6625 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006626 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006627 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6628 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006629
6630 for (idx = 0; idx < instr->ga_len; ++idx)
6631 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006632 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006633
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006634 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006635 if (!dfunc->df_deleted)
6636 --def_functions.ga_len;
6637
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006638 while (cctx.ctx_scope != NULL)
6639 drop_scope(&cctx);
6640
Bram Moolenaar20431c92020-03-20 18:39:46 +01006641 // Don't execute this function body.
6642 ga_clear_strings(&ufunc->uf_lines);
6643
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006644 if (errormsg != NULL)
6645 emsg(errormsg);
6646 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006647 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006648 }
6649
6650 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006651 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006652 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006653 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006654}
6655
6656/*
6657 * Delete an instruction, free what it contains.
6658 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006659 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006660delete_instr(isn_T *isn)
6661{
6662 switch (isn->isn_type)
6663 {
6664 case ISN_EXEC:
6665 case ISN_LOADENV:
6666 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006667 case ISN_LOADB:
6668 case ISN_LOADW:
6669 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006670 case ISN_LOADOPT:
6671 case ISN_MEMBER:
6672 case ISN_PUSHEXC:
6673 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006674 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006675 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006676 case ISN_STOREB:
6677 case ISN_STOREW:
6678 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006679 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006680 vim_free(isn->isn_arg.string);
6681 break;
6682
6683 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006684 case ISN_STORES:
6685 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006686 break;
6687
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006688 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006689 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006690 vim_free(isn->isn_arg.unlet.ul_name);
6691 break;
6692
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006693 case ISN_STOREOPT:
6694 vim_free(isn->isn_arg.storeopt.so_name);
6695 break;
6696
6697 case ISN_PUSHBLOB: // push blob isn_arg.blob
6698 blob_unref(isn->isn_arg.blob);
6699 break;
6700
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006701 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006702#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006703 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006704#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006705 break;
6706
6707 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006708#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006709 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006710#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006711 break;
6712
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006713 case ISN_UCALL:
6714 vim_free(isn->isn_arg.ufunc.cuf_name);
6715 break;
6716
Bram Moolenaar221fcc72020-05-05 19:46:20 +02006717 case ISN_FUNCREF:
6718 {
6719 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6720 + isn->isn_arg.funcref.fr_func;
6721 func_ptr_unref(dfunc->df_ufunc);
6722 }
6723 break;
6724
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006725 case ISN_2BOOL:
6726 case ISN_2STRING:
6727 case ISN_ADDBLOB:
6728 case ISN_ADDLIST:
6729 case ISN_BCALL:
6730 case ISN_CATCH:
6731 case ISN_CHECKNR:
6732 case ISN_CHECKTYPE:
6733 case ISN_COMPAREANY:
6734 case ISN_COMPAREBLOB:
6735 case ISN_COMPAREBOOL:
6736 case ISN_COMPAREDICT:
6737 case ISN_COMPAREFLOAT:
6738 case ISN_COMPAREFUNC:
6739 case ISN_COMPARELIST:
6740 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006741 case ISN_COMPARESPECIAL:
6742 case ISN_COMPARESTRING:
6743 case ISN_CONCAT:
6744 case ISN_DCALL:
6745 case ISN_DROP:
6746 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006747 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006748 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006749 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006750 case ISN_EXECCONCAT:
6751 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006752 case ISN_FOR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006753 case ISN_INDEX:
6754 case ISN_JUMP:
6755 case ISN_LOAD:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006756 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006757 case ISN_LOADSCRIPT:
6758 case ISN_LOADREG:
6759 case ISN_LOADV:
6760 case ISN_NEGATENR:
6761 case ISN_NEWDICT:
6762 case ISN_NEWLIST:
6763 case ISN_OPNR:
6764 case ISN_OPFLOAT:
6765 case ISN_OPANY:
6766 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006767 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006768 case ISN_PUSHF:
6769 case ISN_PUSHNR:
6770 case ISN_PUSHBOOL:
6771 case ISN_PUSHSPEC:
6772 case ISN_RETURN:
6773 case ISN_STORE:
Bram Moolenaarb68b3462020-05-06 21:06:30 +02006774 case ISN_STOREOUTER:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006775 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006776 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006777 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006778 case ISN_STORESCRIPT:
6779 case ISN_THROW:
6780 case ISN_TRY:
6781 // nothing allocated
6782 break;
6783 }
6784}
6785
6786/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006787 * Free all instructions for "dfunc".
6788 */
6789 static void
6790delete_def_function_contents(dfunc_T *dfunc)
6791{
6792 int idx;
6793
6794 ga_clear(&dfunc->df_def_args_isn);
6795
6796 if (dfunc->df_instr != NULL)
6797 {
6798 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6799 delete_instr(dfunc->df_instr + idx);
6800 VIM_CLEAR(dfunc->df_instr);
6801 }
6802
6803 dfunc->df_deleted = TRUE;
6804}
6805
6806/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006807 * When a user function is deleted, delete any associated def function.
6808 */
6809 void
6810delete_def_function(ufunc_T *ufunc)
6811{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006812 if (ufunc->uf_dfunc_idx >= 0)
6813 {
6814 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6815 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006816
Bram Moolenaar20431c92020-03-20 18:39:46 +01006817 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006818 }
6819}
6820
6821#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006822/*
6823 * Free all functions defined with ":def".
6824 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006825 void
6826free_def_functions(void)
6827{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006828 int idx;
6829
6830 for (idx = 0; idx < def_functions.ga_len; ++idx)
6831 {
6832 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6833
6834 delete_def_function_contents(dfunc);
6835 }
6836
6837 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006838}
6839#endif
6840
6841
6842#endif // FEAT_EVAL