blob: 09e71aca357637028ef90b92cdf8a36f2b897f57 [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/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001561 * Generate an ISN_STRINGMEMBER instruction.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001562 */
1563 static int
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02001564generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001565{
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 Moolenaar1cc2a942020-05-10 19:10:31 +02001571 if ((isn = generate_instr(cctx, ISN_STRINGMEMBER)) == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001572 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 Moolenaar1cc2a942020-05-10 19:10:31 +02003488 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003489 type_T **typep;
3490
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003491 // list index: list[123]
3492 // list member: dict[key]
3493 // TODO: blob index
3494 // TODO: more arguments
3495 // TODO: recognize list or dict at runtime
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003496 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003497 return FAIL;
3498
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003499 *arg = skipwhite(*arg + 1);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003500 if (compile_expr0(arg, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003501 return FAIL;
3502
3503 if (**arg != ']')
3504 {
3505 emsg(_(e_missbrac));
3506 return FAIL;
3507 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003508 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003509
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003510 typep = ((type_T **)stack->ga_data) + stack->ga_len - 2;
3511 if ((*typep)->tt_type == VAR_LIST || (*typep) == &t_any)
Bram Moolenaarb13af502020-02-17 21:12:08 +01003512 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003513 if ((*typep)->tt_type == VAR_LIST)
3514 *typep = (*typep)->tt_member;
3515 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3516 return FAIL;
3517 }
3518 else if ((*typep)->tt_type == VAR_DICT)
3519 {
3520 *typep = (*typep)->tt_member;
3521 if (may_generate_2STRING(-1, cctx) == FAIL)
3522 return FAIL;
3523 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
3524 return FAIL;
3525 }
3526 else
3527 {
3528 emsg(_(e_listdictblobreq));
Bram Moolenaarb13af502020-02-17 21:12:08 +01003529 return FAIL;
3530 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003531 }
3532 else if (**arg == '.' && (*arg)[1] != '.')
3533 {
3534 char_u *p;
3535
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003536 if (generate_ppconst(cctx, ppconst) == FAIL)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003537 return FAIL;
3538
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003539 ++*arg;
3540 p = *arg;
3541 // dictionary member: dict.name
3542 if (eval_isnamec1(*p))
3543 while (eval_isnamec(*p))
3544 MB_PTR_ADV(p);
3545 if (p == *arg)
3546 {
3547 semsg(_(e_syntax_at), *arg);
3548 return FAIL;
3549 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02003550 if (generate_STRINGMEMBER(cctx, *arg, p - *arg) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003551 return FAIL;
3552 *arg = p;
3553 }
3554 else
3555 break;
3556 }
3557
3558 // TODO - see handle_subscript():
3559 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3560 // Don't do this when "Func" is already a partial that was bound
3561 // explicitly (pt_auto is FALSE).
3562
3563 return OK;
3564}
3565
3566/*
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003567 * Compile an expression at "*arg" and add instructions to "cctx->ctx_instr".
3568 * "arg" is advanced until after the expression, skipping white space.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003569 *
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003570 * If the value is a constant "ppconst->pp_ret" will be set.
3571 * Before instructions are generated, any values in "ppconst" will generated.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003572 *
3573 * This is the compiling equivalent of eval1(), eval2(), etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003574 */
3575
3576/*
3577 * number number constant
3578 * 0zFFFFFFFF Blob constant
3579 * "string" string constant
3580 * 'string' literal string constant
3581 * &option-name option value
3582 * @r register contents
3583 * identifier variable value
3584 * function() function call
3585 * $VAR environment variable
3586 * (expression) nested expression
3587 * [expr, expr] List
3588 * {key: val, key: val} Dictionary
3589 * #{key: val, key: val} Dictionary with literal keys
3590 *
3591 * Also handle:
3592 * ! in front logical NOT
3593 * - in front unary minus
3594 * + in front unary plus (ignored)
3595 * trailing (arg) funcref/partial call
3596 * trailing [] subscript in String or List
3597 * trailing .name entry in Dictionary
3598 * trailing ->name() method call
3599 */
3600 static int
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003601compile_expr7(
3602 char_u **arg,
3603 cctx_T *cctx,
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003604 ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003605{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003606 char_u *start_leader, *end_leader;
3607 int ret = OK;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003608 typval_T *rettv = &ppconst->pp_tv[ppconst->pp_used];
Bram Moolenaar1c747212020-05-09 18:28:34 +02003609 int used_before = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003610
3611 /*
3612 * Skip '!', '-' and '+' characters. They are handled later.
3613 */
3614 start_leader = *arg;
3615 while (**arg == '!' || **arg == '-' || **arg == '+')
3616 *arg = skipwhite(*arg + 1);
3617 end_leader = *arg;
3618
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003619 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003620 switch (**arg)
3621 {
3622 /*
3623 * Number constant.
3624 */
3625 case '0': // also for blob starting with 0z
3626 case '1':
3627 case '2':
3628 case '3':
3629 case '4':
3630 case '5':
3631 case '6':
3632 case '7':
3633 case '8':
3634 case '9':
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003635 case '.': if (get_number_tv(arg, rettv, TRUE, FALSE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003636 return FAIL;
3637 break;
3638
3639 /*
3640 * String constant: "string".
3641 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003642 case '"': if (get_string_tv(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003643 return FAIL;
3644 break;
3645
3646 /*
3647 * Literal string constant: 'str''ing'.
3648 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003649 case '\'': if (get_lit_string_tv(arg, rettv, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003650 return FAIL;
3651 break;
3652
3653 /*
3654 * Constant Vim variable.
3655 */
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003656 case 'v': get_vim_constant(arg, rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003657 ret = NOTDONE;
3658 break;
3659
3660 /*
Bram Moolenaara5565e42020-05-09 15:44:01 +02003661 * "true" constant
3662 */
3663 case 't': if (STRNCMP(*arg, "true", 4) == 0
3664 && !eval_isnamec((*arg)[4]))
3665 {
3666 *arg += 4;
3667 rettv->v_type = VAR_BOOL;
3668 rettv->vval.v_number = VVAL_TRUE;
3669 }
3670 else
3671 ret = NOTDONE;
3672 break;
3673
3674 /*
3675 * "false" constant
3676 */
3677 case 'f': if (STRNCMP(*arg, "false", 5) == 0
3678 && !eval_isnamec((*arg)[5]))
3679 {
3680 *arg += 5;
3681 rettv->v_type = VAR_BOOL;
3682 rettv->vval.v_number = VVAL_FALSE;
3683 }
3684 else
3685 ret = NOTDONE;
3686 break;
3687
3688 /*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003689 * List: [expr, expr]
3690 */
3691 case '[': ret = compile_list(arg, cctx);
3692 break;
3693
3694 /*
3695 * Dictionary: #{key: val, key: val}
3696 */
3697 case '#': if ((*arg)[1] == '{')
3698 {
3699 ++*arg;
3700 ret = compile_dict(arg, cctx, TRUE);
3701 }
3702 else
3703 ret = NOTDONE;
3704 break;
3705
3706 /*
3707 * Lambda: {arg, arg -> expr}
3708 * Dictionary: {'key': val, 'key': val}
3709 */
3710 case '{': {
3711 char_u *start = skipwhite(*arg + 1);
3712
3713 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003714 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003715 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003716 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003717 if (ret != FAIL && *start == '>')
3718 ret = compile_lambda(arg, cctx);
3719 else
3720 ret = compile_dict(arg, cctx, FALSE);
3721 }
3722 break;
3723
3724 /*
3725 * Option value: &name
3726 */
3727 case '&': ret = compile_get_option(arg, cctx);
3728 break;
3729
3730 /*
3731 * Environment variable: $VAR.
3732 */
3733 case '$': ret = compile_get_env(arg, cctx);
3734 break;
3735
3736 /*
3737 * Register contents: @r.
3738 */
3739 case '@': ret = compile_get_register(arg, cctx);
3740 break;
3741 /*
3742 * nested expression: (expression).
3743 */
3744 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaar1c747212020-05-09 18:28:34 +02003745
3746 // recursive!
3747 if (ppconst->pp_used <= PPSIZE - 10)
3748 {
3749 ret = compile_expr1(arg, cctx, ppconst);
3750 }
3751 else
3752 {
3753 // Not enough space in ppconst, flush constants.
3754 if (generate_ppconst(cctx, ppconst) == FAIL)
3755 return FAIL;
3756 ret = compile_expr0(arg, cctx);
3757 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003758 *arg = skipwhite(*arg);
3759 if (**arg == ')')
3760 ++*arg;
3761 else if (ret == OK)
3762 {
3763 emsg(_(e_missing_close));
3764 ret = FAIL;
3765 }
3766 break;
3767
3768 default: ret = NOTDONE;
3769 break;
3770 }
3771 if (ret == FAIL)
3772 return FAIL;
3773
Bram Moolenaar1c747212020-05-09 18:28:34 +02003774 if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003775 {
3776 // apply the '!', '-' and '+' before the constant
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003777 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003778 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003779 clear_tv(rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003780 return FAIL;
3781 }
3782 start_leader = end_leader; // don't apply again below
3783
Bram Moolenaara5565e42020-05-09 15:44:01 +02003784 if (cctx->ctx_skip == TRUE)
3785 clear_tv(rettv);
3786 else
3787 // A constant expression can possibly be handled compile time,
3788 // return the value instead of generating code.
3789 ++ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003790 }
3791 else if (ret == NOTDONE)
3792 {
3793 char_u *p;
3794 int r;
3795
3796 if (!eval_isnamec1(**arg))
3797 {
3798 semsg(_("E1015: Name expected: %s"), *arg);
3799 return FAIL;
3800 }
3801
3802 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003803 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003804 if (*p == '(')
Bram Moolenaara5565e42020-05-09 15:44:01 +02003805 {
3806 r = compile_call(arg, p - *arg, cctx, ppconst, 0);
3807 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003808 else
Bram Moolenaara5565e42020-05-09 15:44:01 +02003809 {
3810 if (generate_ppconst(cctx, ppconst) == FAIL)
3811 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003812 r = compile_load(arg, p, cctx, TRUE);
Bram Moolenaara5565e42020-05-09 15:44:01 +02003813 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003814 if (r == FAIL)
3815 return FAIL;
3816 }
3817
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02003818 // Handle following "[]", ".member", etc.
3819 // Then deal with prefixed '-', '+' and '!', if not done already.
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003820 if (compile_subscript(arg, cctx, &start_leader, end_leader,
Bram Moolenaara5565e42020-05-09 15:44:01 +02003821 ppconst) == FAIL)
3822 return FAIL;
3823 if (ppconst->pp_used > 0)
3824 {
3825 // apply the '!', '-' and '+' before the constant
3826 rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
3827 if (apply_leader(rettv, start_leader, end_leader) == FAIL)
3828 return FAIL;
3829 return OK;
3830 }
3831 if (compile_leader(cctx, start_leader, end_leader) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003832 return FAIL;
Bram Moolenaar5c2fe642020-05-07 23:20:21 +02003833 return OK;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003834}
3835
3836/*
3837 * * number multiplication
3838 * / number division
3839 * % number modulo
3840 */
3841 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003842compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003843{
3844 char_u *op;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003845 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003846
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003847 // get the first expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003848 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003849 return FAIL;
3850
3851 /*
3852 * Repeat computing, until no "*", "/" or "%" is following.
3853 */
3854 for (;;)
3855 {
3856 op = skipwhite(*arg);
3857 if (*op != '*' && *op != '/' && *op != '%')
3858 break;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003859
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003860 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003861 {
3862 char_u buf[3];
3863
3864 vim_strncpy(buf, op, 1);
3865 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003866 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003867 }
3868 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003869 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003870 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003871
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003872 // get the second expression
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003873 if (compile_expr7(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003874 return FAIL;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003875
3876 if (ppconst->pp_used == ppconst_used + 2
3877 && ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
3878 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003879 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003880 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
3881 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003882 varnumber_T res = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003883
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003884 // both are numbers: compute the result
3885 switch (*op)
3886 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003887 case '*': res = tv1->vval.v_number * tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003888 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003889 case '/': res = tv1->vval.v_number / tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003890 break;
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003891 case '%': res = tv1->vval.v_number % tv2->vval.v_number;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003892 break;
3893 }
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003894 tv1->vval.v_number = res;
3895 --ppconst->pp_used;
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003896 }
3897 else
3898 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003899 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003900 generate_two_op(cctx, op);
3901 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003902 }
3903
3904 return OK;
3905}
3906
3907/*
3908 * + number addition
3909 * - number subtraction
3910 * .. string concatenation
3911 */
3912 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02003913compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003914{
3915 char_u *op;
3916 int oplen;
Bram Moolenaara5565e42020-05-09 15:44:01 +02003917 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003918
3919 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02003920 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003921 return FAIL;
3922
3923 /*
3924 * Repeat computing, until no "+", "-" or ".." is following.
3925 */
3926 for (;;)
3927 {
3928 op = skipwhite(*arg);
3929 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3930 break;
3931 oplen = (*op == '.' ? 2 : 1);
3932
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003933 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003934 {
3935 char_u buf[3];
3936
3937 vim_strncpy(buf, op, oplen);
3938 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003939 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003940 }
3941
3942 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003943 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003944 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003945
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003946 // get the second expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02003947 if (compile_expr6(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003948 return FAIL;
3949
Bram Moolenaara5565e42020-05-09 15:44:01 +02003950 if (ppconst->pp_used == ppconst_used + 2
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003951 && (*op == '.'
Bram Moolenaara5565e42020-05-09 15:44:01 +02003952 ? (ppconst->pp_tv[ppconst_used].v_type == VAR_STRING
3953 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_STRING)
3954 : (ppconst->pp_tv[ppconst_used].v_type == VAR_NUMBER
3955 && ppconst->pp_tv[ppconst_used + 1].v_type == VAR_NUMBER)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003956 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003957 typval_T *tv1 = &ppconst->pp_tv[ppconst_used];
3958 typval_T *tv2 = &ppconst->pp_tv[ppconst_used + 1];
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003959
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003960 // concat/subtract/add constant numbers
3961 if (*op == '+')
3962 tv1->vval.v_number = tv1->vval.v_number + tv2->vval.v_number;
3963 else if (*op == '-')
3964 tv1->vval.v_number = tv1->vval.v_number - tv2->vval.v_number;
3965 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003966 {
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003967 // concatenate constant strings
3968 char_u *s1 = tv1->vval.v_string;
3969 char_u *s2 = tv2->vval.v_string;
3970 size_t len1 = STRLEN(s1);
3971
3972 tv1->vval.v_string = alloc((int)(len1 + STRLEN(s2) + 1));
3973 if (tv1->vval.v_string == NULL)
3974 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003975 clear_ppconst(ppconst);
Bram Moolenaar7d131b02020-05-08 19:10:34 +02003976 return FAIL;
3977 }
3978 mch_memmove(tv1->vval.v_string, s1, len1);
3979 STRCPY(tv1->vval.v_string + len1, s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003980 vim_free(s1);
3981 vim_free(s2);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003982 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02003983 --ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003984 }
3985 else
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003986 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02003987 generate_ppconst(cctx, ppconst);
Bram Moolenaarf0eefce2020-05-07 22:19:01 +02003988 if (*op == '.')
3989 {
3990 if (may_generate_2STRING(-2, cctx) == FAIL
3991 || may_generate_2STRING(-1, cctx) == FAIL)
3992 return FAIL;
3993 generate_instr_drop(cctx, ISN_CONCAT, 1);
3994 }
3995 else
3996 generate_two_op(cctx, op);
3997 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003998 }
3999
4000 return OK;
4001}
4002
4003/*
4004 * expr5a == expr5b
4005 * expr5a =~ expr5b
4006 * expr5a != expr5b
4007 * expr5a !~ expr5b
4008 * expr5a > expr5b
4009 * expr5a >= expr5b
4010 * expr5a < expr5b
4011 * expr5a <= expr5b
4012 * expr5a is expr5b
4013 * expr5a isnot expr5b
4014 *
4015 * Produces instructions:
4016 * EVAL expr5a Push result of "expr5a"
4017 * EVAL expr5b Push result of "expr5b"
4018 * COMPARE one of the compare instructions
4019 */
4020 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004021compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004022{
4023 exptype_T type = EXPR_UNKNOWN;
4024 char_u *p;
4025 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004026 int type_is = FALSE;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004027 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004028
4029 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004030 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004031 return FAIL;
4032
4033 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004034 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004035
4036 /*
4037 * If there is a comparative operator, use it.
4038 */
4039 if (type != EXPR_UNKNOWN)
4040 {
4041 int ic = FALSE; // Default: do not ignore case
4042
4043 if (type_is && (p[len] == '?' || p[len] == '#'))
4044 {
4045 semsg(_(e_invexpr2), *arg);
4046 return FAIL;
4047 }
4048 // extra question mark appended: ignore case
4049 if (p[len] == '?')
4050 {
4051 ic = TRUE;
4052 ++len;
4053 }
4054 // extra '#' appended: match case (ignored)
4055 else if (p[len] == '#')
4056 ++len;
4057 // nothing appended: match case
4058
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004059 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004060 {
4061 char_u buf[7];
4062
4063 vim_strncpy(buf, p, len);
4064 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004065 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004066 }
4067
4068 // get the second variable
4069 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004070 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004071 return FAIL;
4072
Bram Moolenaara5565e42020-05-09 15:44:01 +02004073 if (compile_expr5(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004074 return FAIL;
4075
Bram Moolenaara5565e42020-05-09 15:44:01 +02004076 if (ppconst->pp_used == ppconst_used + 2)
4077 {
4078 typval_T * tv1 = &ppconst->pp_tv[ppconst->pp_used - 2];
4079 typval_T *tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
4080 int ret;
4081
4082 // Both sides are a constant, compute the result now.
4083 // First check for a valid combination of types, this is more
4084 // strict than typval_compare().
4085 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
4086 ret = FAIL;
4087 else
4088 {
4089 ret = typval_compare(tv1, tv2, type, ic);
4090 tv1->v_type = VAR_BOOL;
4091 tv1->vval.v_number = tv1->vval.v_number
4092 ? VVAL_TRUE : VVAL_FALSE;
4093 clear_tv(tv2);
4094 --ppconst->pp_used;
4095 }
4096 return ret;
4097 }
4098
4099 generate_ppconst(cctx, ppconst);
4100 return generate_COMPARE(cctx, type, ic);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004101 }
4102
4103 return OK;
4104}
4105
Bram Moolenaar7f141552020-05-09 17:35:53 +02004106static int compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
4107
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004108/*
4109 * Compile || or &&.
4110 */
4111 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004112compile_and_or(
4113 char_u **arg,
4114 cctx_T *cctx,
4115 char *op,
4116 ppconst_T *ppconst,
4117 int ppconst_used UNUSED)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004118{
4119 char_u *p = skipwhite(*arg);
4120 int opchar = *op;
4121
4122 if (p[0] == opchar && p[1] == opchar)
4123 {
4124 garray_T *instr = &cctx->ctx_instr;
4125 garray_T end_ga;
4126
4127 /*
4128 * Repeat until there is no following "||" or "&&"
4129 */
4130 ga_init2(&end_ga, sizeof(int), 10);
4131 while (p[0] == opchar && p[1] == opchar)
4132 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004133 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
4134 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004135 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004136 return FAIL;
4137 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004138
Bram Moolenaara5565e42020-05-09 15:44:01 +02004139 // TODO: use ppconst if the value is a constant
4140 generate_ppconst(cctx, ppconst);
4141
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004142 if (ga_grow(&end_ga, 1) == FAIL)
4143 {
4144 ga_clear(&end_ga);
4145 return FAIL;
4146 }
4147 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
4148 ++end_ga.ga_len;
4149 generate_JUMP(cctx, opchar == '|'
4150 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
4151
4152 // eval the next expression
4153 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004154 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004155 return FAIL;
4156
Bram Moolenaara5565e42020-05-09 15:44:01 +02004157 if ((opchar == '|' ? compile_expr3(arg, cctx, ppconst)
4158 : compile_expr4(arg, cctx, ppconst)) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004159 {
4160 ga_clear(&end_ga);
4161 return FAIL;
4162 }
4163 p = skipwhite(*arg);
4164 }
Bram Moolenaara5565e42020-05-09 15:44:01 +02004165 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004166
4167 // Fill in the end label in all jumps.
4168 while (end_ga.ga_len > 0)
4169 {
4170 isn_T *isn;
4171
4172 --end_ga.ga_len;
4173 isn = ((isn_T *)instr->ga_data)
4174 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
4175 isn->isn_arg.jump.jump_where = instr->ga_len;
4176 }
4177 ga_clear(&end_ga);
4178 }
4179
4180 return OK;
4181}
4182
4183/*
4184 * expr4a && expr4a && expr4a logical AND
4185 *
4186 * Produces instructions:
4187 * EVAL expr4a Push result of "expr4a"
4188 * JUMP_AND_KEEP_IF_FALSE end
4189 * EVAL expr4b Push result of "expr4b"
4190 * JUMP_AND_KEEP_IF_FALSE end
4191 * EVAL expr4c Push result of "expr4c"
4192 * end:
4193 */
4194 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004195compile_expr3(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004196{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004197 int ppconst_used = ppconst->pp_used;
4198
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004199 // get the first variable
Bram Moolenaara5565e42020-05-09 15:44:01 +02004200 if (compile_expr4(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004201 return FAIL;
4202
4203 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004204 return compile_and_or(arg, cctx, "&&", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004205}
4206
4207/*
4208 * expr3a || expr3b || expr3c logical OR
4209 *
4210 * Produces instructions:
4211 * EVAL expr3a Push result of "expr3a"
4212 * JUMP_AND_KEEP_IF_TRUE end
4213 * EVAL expr3b Push result of "expr3b"
4214 * JUMP_AND_KEEP_IF_TRUE end
4215 * EVAL expr3c Push result of "expr3c"
4216 * end:
4217 */
4218 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004219compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004220{
Bram Moolenaara5565e42020-05-09 15:44:01 +02004221 int ppconst_used = ppconst->pp_used;
4222
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004223 // eval the first expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004224 if (compile_expr3(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004225 return FAIL;
4226
4227 // || and && work almost the same
Bram Moolenaara5565e42020-05-09 15:44:01 +02004228 return compile_and_or(arg, cctx, "||", ppconst, ppconst_used);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004229}
4230
4231/*
4232 * Toplevel expression: expr2 ? expr1a : expr1b
4233 *
4234 * Produces instructions:
4235 * EVAL expr2 Push result of "expr"
4236 * JUMP_IF_FALSE alt jump if false
4237 * EVAL expr1a
4238 * JUMP_ALWAYS end
4239 * alt: EVAL expr1b
4240 * end:
4241 */
4242 static int
Bram Moolenaara5565e42020-05-09 15:44:01 +02004243compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004244{
4245 char_u *p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004246 int ppconst_used = ppconst->pp_used;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004247
Bram Moolenaar61a89812020-05-07 16:58:17 +02004248 // Evaluate the first expression.
Bram Moolenaara5565e42020-05-09 15:44:01 +02004249 if (compile_expr2(arg, cctx, ppconst) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004250 return FAIL;
4251
4252 p = skipwhite(*arg);
4253 if (*p == '?')
4254 {
4255 garray_T *instr = &cctx->ctx_instr;
4256 garray_T *stack = &cctx->ctx_type_stack;
4257 int alt_idx = instr->ga_len;
4258 int end_idx;
4259 isn_T *isn;
4260 type_T *type1;
4261 type_T *type2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004262 int has_const_expr = FALSE;
4263 int const_value = FALSE;
4264 int save_skip = cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004265
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004266 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4267 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004268 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004269 return FAIL;
4270 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004271
Bram Moolenaara5565e42020-05-09 15:44:01 +02004272 if (ppconst->pp_used == ppconst_used + 1)
4273 {
4274 // the condition is a constant, we know whether the ? or the :
4275 // expression is to be evaluated.
4276 has_const_expr = TRUE;
4277 const_value = tv2bool(&ppconst->pp_tv[ppconst_used]);
4278 clear_tv(&ppconst->pp_tv[ppconst_used]);
4279 --ppconst->pp_used;
4280 cctx->ctx_skip = save_skip == TRUE || !const_value;
4281 }
4282 else
4283 {
4284 generate_ppconst(cctx, ppconst);
4285 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4286 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004287
4288 // evaluate the second expression; any type is accepted
4289 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004290 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004291 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004292 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004293 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004294
Bram Moolenaara5565e42020-05-09 15:44:01 +02004295 if (!has_const_expr)
4296 {
4297 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004298
Bram Moolenaara5565e42020-05-09 15:44:01 +02004299 // remember the type and drop it
4300 --stack->ga_len;
4301 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004302
Bram Moolenaara5565e42020-05-09 15:44:01 +02004303 end_idx = instr->ga_len;
4304 generate_JUMP(cctx, JUMP_ALWAYS, 0);
4305
4306 // jump here from JUMP_IF_FALSE
4307 isn = ((isn_T *)instr->ga_data) + alt_idx;
4308 isn->isn_arg.jump.jump_where = instr->ga_len;
4309 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004310
4311 // Check for the ":".
4312 p = skipwhite(*arg);
4313 if (*p != ':')
4314 {
4315 emsg(_(e_missing_colon));
4316 return FAIL;
4317 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004318 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
4319 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004320 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004321 return FAIL;
4322 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004323
4324 // evaluate the third expression
Bram Moolenaara5565e42020-05-09 15:44:01 +02004325 if (has_const_expr)
4326 cctx->ctx_skip = save_skip == TRUE || const_value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004327 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02004328 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02004329 return FAIL;
Bram Moolenaara5565e42020-05-09 15:44:01 +02004330 if (compile_expr1(arg, cctx, ppconst) == FAIL)
Bram Moolenaara6d53682020-01-28 23:04:06 +01004331 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004332
Bram Moolenaara5565e42020-05-09 15:44:01 +02004333 if (!has_const_expr)
4334 {
4335 generate_ppconst(cctx, ppconst);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004336
Bram Moolenaara5565e42020-05-09 15:44:01 +02004337 // If the types differ, the result has a more generic type.
4338 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4339 common_type(type1, type2, &type2, cctx->ctx_type_list);
4340
4341 // jump here from JUMP_ALWAYS
4342 isn = ((isn_T *)instr->ga_data) + end_idx;
4343 isn->isn_arg.jump.jump_where = instr->ga_len;
4344 }
4345
4346 cctx->ctx_skip = save_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004347 }
4348 return OK;
4349}
4350
4351/*
Bram Moolenaara5565e42020-05-09 15:44:01 +02004352 * Toplevel expression.
4353 */
4354 static int
4355compile_expr0(char_u **arg, cctx_T *cctx)
4356{
4357 ppconst_T ppconst;
4358
4359 CLEAR_FIELD(ppconst);
4360 if (compile_expr1(arg, cctx, &ppconst) == FAIL)
4361 {
4362 clear_ppconst(&ppconst);
4363 return FAIL;
4364 }
4365 if (generate_ppconst(cctx, &ppconst) == FAIL)
4366 return FAIL;
4367 return OK;
4368}
4369
4370/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004371 * compile "return [expr]"
4372 */
4373 static char_u *
4374compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
4375{
4376 char_u *p = arg;
4377 garray_T *stack = &cctx->ctx_type_stack;
4378 type_T *stack_type;
4379
4380 if (*p != NUL && *p != '|' && *p != '\n')
4381 {
4382 // compile return argument into instructions
Bram Moolenaara5565e42020-05-09 15:44:01 +02004383 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004384 return NULL;
4385
4386 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4387 if (set_return_type)
4388 cctx->ctx_ufunc->uf_ret_type = stack_type;
4389 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
4390 == FAIL)
4391 return NULL;
4392 }
4393 else
4394 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004395 // "set_return_type" cannot be TRUE, only used for a lambda which
4396 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02004397 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
4398 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004399 {
4400 emsg(_("E1003: Missing return value"));
4401 return NULL;
4402 }
4403
4404 // No argument, return zero.
4405 generate_PUSHNR(cctx, 0);
4406 }
4407
4408 if (generate_instr(cctx, ISN_RETURN) == NULL)
4409 return NULL;
4410
4411 // "return val | endif" is possible
4412 return skipwhite(p);
4413}
4414
4415/*
Bram Moolenaar04b12692020-05-04 23:24:44 +02004416 * Get a line from the compilation context, compatible with exarg_T getline().
4417 * Return a pointer to the line in allocated memory.
4418 * Return NULL for end-of-file or some error.
4419 */
4420 static char_u *
4421exarg_getline(
4422 int c UNUSED,
4423 void *cookie,
4424 int indent UNUSED,
4425 int do_concat UNUSED)
4426{
4427 cctx_T *cctx = (cctx_T *)cookie;
4428
4429 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
4430 {
4431 iemsg("Heredoc got to end");
4432 return NULL;
4433 }
4434 ++cctx->ctx_lnum;
4435 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4436 [cctx->ctx_lnum]);
4437}
4438
4439/*
4440 * Compile a nested :def command.
4441 */
4442 static char_u *
4443compile_nested_function(exarg_T *eap, cctx_T *cctx)
4444{
4445 char_u *name_start = eap->arg;
4446 char_u *name_end = to_name_end(eap->arg, FALSE);
4447 char_u *name = get_lambda_name();
4448 lvar_T *lvar;
4449 ufunc_T *ufunc;
4450
4451 eap->arg = name_end;
4452 eap->getline = exarg_getline;
4453 eap->cookie = cctx;
4454 eap->skip = cctx->ctx_skip == TRUE;
4455 eap->forceit = FALSE;
Bram Moolenaar09689a02020-05-09 22:50:08 +02004456 ufunc = def_function(eap, name, cctx, TRUE);
Bram Moolenaar04b12692020-05-04 23:24:44 +02004457
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004458 if (ufunc == NULL || ufunc->uf_dfunc_idx < 0)
Bram Moolenaar04b12692020-05-04 23:24:44 +02004459 return NULL;
4460
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004461 // Define a local variable for the function reference.
Bram Moolenaar04b12692020-05-04 23:24:44 +02004462 lvar = reserve_local(cctx, name_start, name_end - name_start,
Bram Moolenaar0e65d3d2020-05-05 17:53:16 +02004463 TRUE, ufunc->uf_func_type);
4464
4465 if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL
4466 || generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL) == FAIL)
4467 return NULL;
Bram Moolenaar04b12692020-05-04 23:24:44 +02004468
Bram Moolenaar61a89812020-05-07 16:58:17 +02004469 // TODO: warning for trailing text?
Bram Moolenaar04b12692020-05-04 23:24:44 +02004470 return (char_u *)"";
4471}
4472
4473/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004474 * Return the length of an assignment operator, or zero if there isn't one.
4475 */
4476 int
4477assignment_len(char_u *p, int *heredoc)
4478{
4479 if (*p == '=')
4480 {
4481 if (p[1] == '<' && p[2] == '<')
4482 {
4483 *heredoc = TRUE;
4484 return 3;
4485 }
4486 return 1;
4487 }
4488 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
4489 return 2;
4490 if (STRNCMP(p, "..=", 3) == 0)
4491 return 3;
4492 return 0;
4493}
4494
4495// words that cannot be used as a variable
4496static char *reserved[] = {
4497 "true",
4498 "false",
4499 NULL
4500};
4501
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004502typedef enum {
4503 dest_local,
4504 dest_option,
4505 dest_env,
4506 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004507 dest_buffer,
4508 dest_window,
4509 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004510 dest_vimvar,
4511 dest_script,
4512 dest_reg,
4513} assign_dest_T;
4514
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004515/*
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004516 * Generate the load instruction for "name".
4517 */
4518 static void
4519generate_loadvar(
4520 cctx_T *cctx,
4521 assign_dest_T dest,
4522 char_u *name,
4523 lvar_T *lvar,
4524 type_T *type)
4525{
4526 switch (dest)
4527 {
4528 case dest_option:
4529 // TODO: check the option exists
4530 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
4531 break;
4532 case dest_global:
4533 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4534 break;
4535 case dest_buffer:
4536 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4537 break;
4538 case dest_window:
4539 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4540 break;
4541 case dest_tab:
4542 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4543 break;
4544 case dest_script:
4545 compile_load_scriptvar(cctx,
4546 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
4547 break;
4548 case dest_env:
4549 // Include $ in the name here
4550 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4551 break;
4552 case dest_reg:
4553 generate_LOAD(cctx, ISN_LOADREG, name[1], NULL, &t_string);
4554 break;
4555 case dest_vimvar:
4556 generate_LOADV(cctx, name + 2, TRUE);
4557 break;
4558 case dest_local:
4559 if (lvar->lv_from_outer)
4560 generate_LOAD(cctx, ISN_LOADOUTER, lvar->lv_idx,
4561 NULL, type);
4562 else
4563 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
4564 break;
4565 }
4566}
4567
4568/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004569 * compile "let var [= expr]", "const var = expr" and "var = expr"
4570 * "arg" points to "var".
4571 */
4572 static char_u *
4573compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4574{
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004575 char_u *var_end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004576 char_u *p;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004577 char_u *end = arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004578 char_u *ret = NULL;
4579 int var_count = 0;
4580 int semicolon = 0;
4581 size_t varlen;
4582 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004583 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004584 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004585 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004586 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004587 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004588 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004589 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004590 int oplen = 0;
4591 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004592 type_T *type = &t_any;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004593 type_T *member_type = &t_any;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004594 lvar_T *lvar = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004595 char_u *name;
4596 char_u *sp;
4597 int has_type = FALSE;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004598 int has_index = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004599 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4600 int instr_count = -1;
4601
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004602 var_end = skip_var_list(arg, FALSE, &var_count, &semicolon);
4603 if (var_end == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004604 return NULL;
4605 if (var_count > 0)
4606 {
4607 // TODO: let [var, var] = list
4608 emsg("Cannot handle a list yet");
4609 return NULL;
4610 }
4611
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004612 p = (*arg == '&' || *arg == '$' || *arg == '@') ? arg + 1 : arg;
4613 p = to_name_end(p, TRUE);
4614
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004615 // "a: type" is declaring variable "a" with a type, not "a:".
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004616 if (is_decl && var_end == arg + 2 && var_end[-1] == ':')
4617 --var_end;
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004618 if (is_decl && p == arg + 2 && p[-1] == ':')
4619 --p;
4620
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004621 varlen = p - arg;
4622 name = vim_strnsave(arg, (int)varlen);
4623 if (name == NULL)
4624 return NULL;
4625
Bram Moolenaar080457c2020-03-03 21:53:32 +01004626 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004627 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004628 if (*arg == '&')
4629 {
4630 int cc;
4631 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004632
Bram Moolenaar080457c2020-03-03 21:53:32 +01004633 dest = dest_option;
4634 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004635 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004636 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004637 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004638 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004639 if (is_decl)
4640 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004641 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004642 goto theend;
4643 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004644 p = arg;
4645 p = find_option_end(&p, &opt_flags);
4646 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004647 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004648 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004649 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004650 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004651 }
4652 cc = *p;
4653 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004654 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004655 *p = cc;
4656 if (opt_type == -3)
4657 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004658 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004659 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004660 }
4661 if (opt_type == -2 || opt_type == 0)
4662 type = &t_string;
4663 else
4664 type = &t_number; // both number and boolean option
4665 }
4666 else if (*arg == '$')
4667 {
4668 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004669 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004670 if (is_decl)
4671 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004672 semsg(_("E1065: Cannot declare an environment variable: %s"),
4673 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004674 goto theend;
4675 }
4676 }
4677 else if (*arg == '@')
4678 {
4679 if (!valid_yank_reg(arg[1], TRUE))
4680 {
4681 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004682 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004683 }
4684 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004685 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004686 if (is_decl)
4687 {
4688 semsg(_("E1066: Cannot declare a register: %s"), name);
4689 goto theend;
4690 }
4691 }
4692 else if (STRNCMP(arg, "g:", 2) == 0)
4693 {
4694 dest = dest_global;
4695 if (is_decl)
4696 {
4697 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4698 goto theend;
4699 }
4700 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004701 else if (STRNCMP(arg, "b:", 2) == 0)
4702 {
4703 dest = dest_buffer;
4704 if (is_decl)
4705 {
4706 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4707 goto theend;
4708 }
4709 }
4710 else if (STRNCMP(arg, "w:", 2) == 0)
4711 {
4712 dest = dest_window;
4713 if (is_decl)
4714 {
4715 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4716 goto theend;
4717 }
4718 }
4719 else if (STRNCMP(arg, "t:", 2) == 0)
4720 {
4721 dest = dest_tab;
4722 if (is_decl)
4723 {
4724 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4725 goto theend;
4726 }
4727 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004728 else if (STRNCMP(arg, "v:", 2) == 0)
4729 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004730 typval_T *vtv;
4731 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004732
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004733 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004734 if (vimvaridx < 0)
4735 {
4736 semsg(_(e_var_notfound), arg);
4737 goto theend;
4738 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004739 // We use the current value of "sandbox" here, is that OK?
4740 if (var_check_ro(di_flags, name, FALSE))
4741 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004742 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004743 vtv = get_vim_var_tv(vimvaridx);
4744 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004745 if (is_decl)
4746 {
4747 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4748 goto theend;
4749 }
4750 }
4751 else
4752 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004753 int idx;
4754
Bram Moolenaar080457c2020-03-03 21:53:32 +01004755 for (idx = 0; reserved[idx] != NULL; ++idx)
4756 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004757 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004758 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004759 goto theend;
4760 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004761
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004762 lvar = lookup_local(arg, varlen, cctx);
4763 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004764 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004765 if (is_decl)
4766 {
4767 semsg(_("E1017: Variable already declared: %s"), name);
4768 goto theend;
4769 }
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004770 else if (lvar->lv_const)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004771 {
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02004772 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4773 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004774 }
4775 }
4776 else if (STRNCMP(arg, "s:", 2) == 0
4777 || lookup_script(arg, varlen) == OK
4778 || find_imported(arg, varlen, cctx) != NULL)
4779 {
4780 dest = dest_script;
4781 if (is_decl)
4782 {
4783 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004784 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004785 goto theend;
4786 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004787 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004788 else if (name[1] == ':' && name[2] != NUL)
4789 {
4790 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4791 goto theend;
4792 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004793 else if (!is_decl)
4794 {
4795 semsg(_("E1089: unknown variable: %s"), name);
4796 goto theend;
4797 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004798 }
4799 }
4800
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004801 // handle "a:name" as a name, not index "name" on "a"
4802 if (varlen > 1 || arg[varlen] != ':')
4803 p = var_end;
4804
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004805 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004806 {
4807 if (is_decl && *p == ':')
4808 {
4809 // parse optional type: "let var: type = expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004810 if (!VIM_ISWHITE(p[1]))
4811 {
4812 semsg(_(e_white_after), ":");
4813 goto theend;
4814 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004815 p = skipwhite(p + 1);
4816 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004817 has_type = TRUE;
4818 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004819 else if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004820 type = lvar->lv_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004821 }
4822
4823 sp = p;
4824 p = skipwhite(p);
4825 op = p;
4826 oplen = assignment_len(p, &heredoc);
4827 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4828 {
4829 char_u buf[4];
4830
4831 vim_strncpy(buf, op, oplen);
4832 semsg(_(e_white_both), buf);
4833 }
4834
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004835 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004836 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004837 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004838 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004839 goto theend;
4840 }
4841
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004842 if (lvar == NULL && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004843 {
4844 if (oplen > 1 && !heredoc)
4845 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004846 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004847 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4848 name);
4849 goto theend;
4850 }
4851
4852 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004853 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004854 goto theend;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004855 lvar = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4856 if (lvar == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004857 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004858 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004859 }
4860
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004861 member_type = type;
4862 if (var_end > arg + varlen)
4863 {
4864 if (is_decl)
4865 {
4866 emsg(_("E1087: cannot use an index when declaring a variable"));
4867 goto theend;
4868 }
4869
4870 // Something follows after the variable: "var[idx]".
4871 if (arg[varlen] == '[')
4872 {
4873 has_index = TRUE;
4874 if (type->tt_member == NULL)
4875 {
4876 semsg(_("E1088: cannot use an index on %s"), name);
4877 goto theend;
4878 }
4879 member_type = type->tt_member;
4880 }
4881 else
4882 {
4883 semsg("Not supported yet: %s", arg);
4884 goto theend;
4885 }
4886 }
4887
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004888 if (heredoc)
4889 {
4890 list_T *l;
4891 listitem_T *li;
4892
4893 // [let] varname =<< [trim] {end}
Bram Moolenaar04b12692020-05-04 23:24:44 +02004894 eap->getline = exarg_getline;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004895 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004896 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004897
4898 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004899 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004900 {
4901 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4902 li->li_tv.vval.v_string = NULL;
4903 }
4904 generate_NEWLIST(cctx, l->lv_len);
4905 type = &t_list_string;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004906 member_type = &t_list_string;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004907 list_free(l);
4908 p += STRLEN(p);
4909 }
4910 else if (oplen > 0)
4911 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004912 int r;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004913
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004914 // for "+=", "*=", "..=" etc. first load the current value
4915 if (*op != '=')
4916 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004917 generate_loadvar(cctx, dest, name, lvar, type);
4918
4919 if (has_index)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004920 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004921 // TODO: get member from list or dict
4922 emsg("Index with operation not supported yet");
4923 goto theend;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004924 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004925 }
4926
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004927 // Compile the expression. Temporarily hide the new local variable
4928 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004929 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004930 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004931 instr_count = instr->ga_len;
4932 p = skipwhite(p + oplen);
Bram Moolenaara5565e42020-05-09 15:44:01 +02004933 r = compile_expr0(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004934 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004935 ++cctx->ctx_locals.ga_len;
4936 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004937 goto theend;
4938
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004939 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004940 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004941 type_T *stacktype;
4942
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004943 stacktype = stack->ga_len == 0 ? &t_void
4944 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004945 if (lvar != NULL && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004946 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004947 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004948 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004949 if (stacktype->tt_type == VAR_VOID)
4950 {
4951 emsg(_("E1031: Cannot use void value"));
4952 goto theend;
4953 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004954 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004955 {
4956 // An empty list or dict has a &t_void member, for a
4957 // variable that implies &t_any.
4958 if (stacktype == &t_list_empty)
4959 lvar->lv_type = &t_list_any;
4960 else if (stacktype == &t_dict_empty)
4961 lvar->lv_type = &t_dict_any;
4962 else
4963 lvar->lv_type = stacktype;
4964 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004965 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004966 else
4967 {
4968 type_T *use_type = lvar->lv_type;
4969
4970 if (has_index)
4971 {
4972 use_type = use_type->tt_member;
4973 if (use_type == NULL)
4974 use_type = &t_void;
4975 }
4976 if (need_type(stacktype, use_type, -1, cctx) == FAIL)
4977 goto theend;
4978 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004979 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02004980 else if (*p != '=' && check_type(member_type, stacktype, TRUE)
4981 == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004982 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004983 }
4984 }
4985 else if (cmdidx == CMD_const)
4986 {
4987 emsg(_("E1021: const requires a value"));
4988 goto theend;
4989 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004990 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004991 {
4992 emsg(_("E1022: type or initialization required"));
4993 goto theend;
4994 }
4995 else
4996 {
4997 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004998 if (ga_grow(instr, 1) == FAIL)
4999 goto theend;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005000 switch (member_type->tt_type)
Bram Moolenaar04d05222020-02-06 22:06:54 +01005001 {
5002 case VAR_BOOL:
5003 generate_PUSHBOOL(cctx, VVAL_FALSE);
5004 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01005005 case VAR_FLOAT:
5006#ifdef FEAT_FLOAT
5007 generate_PUSHF(cctx, 0.0);
5008#endif
5009 break;
5010 case VAR_STRING:
5011 generate_PUSHS(cctx, NULL);
5012 break;
5013 case VAR_BLOB:
5014 generate_PUSHBLOB(cctx, NULL);
5015 break;
5016 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005017 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01005018 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01005019 case VAR_LIST:
5020 generate_NEWLIST(cctx, 0);
5021 break;
5022 case VAR_DICT:
5023 generate_NEWDICT(cctx, 0);
5024 break;
5025 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005026 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01005027 break;
5028 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005029 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01005030 break;
5031 case VAR_NUMBER:
5032 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02005033 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02005034 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01005035 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02005036 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01005037 generate_PUSHNR(cctx, 0);
5038 break;
5039 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005040 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005041 end = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005042
5043 if (oplen > 0 && *op != '=')
5044 {
5045 type_T *expected = &t_number;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005046 type_T *stacktype;
5047
5048 // TODO: if type is known use float or any operation
5049
5050 if (*op == '.')
5051 expected = &t_string;
5052 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5053 if (need_type(stacktype, expected, -1, cctx) == FAIL)
5054 goto theend;
5055
5056 if (*op == '.')
5057 generate_instr_drop(cctx, ISN_CONCAT, 1);
5058 else
5059 {
5060 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
5061
5062 if (isn == NULL)
5063 goto theend;
5064 switch (*op)
5065 {
5066 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
5067 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
5068 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
5069 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
5070 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
5071 }
5072 }
5073 }
5074
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005075 if (has_index)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005076 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005077 int r;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005078
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005079 // Compile the "idx" in "var[idx]".
5080 if (new_local)
5081 --cctx->ctx_locals.ga_len;
5082 p = skipwhite(arg + varlen + 1);
5083 r = compile_expr0(&p, cctx);
5084 if (new_local)
5085 ++cctx->ctx_locals.ga_len;
5086 if (r == FAIL)
5087 goto theend;
5088 if (*skipwhite(p) != ']')
5089 {
5090 emsg(_(e_missbrac));
5091 goto theend;
5092 }
5093 if (type->tt_type == VAR_DICT
5094 && may_generate_2STRING(-1, cctx) == FAIL)
5095 goto theend;
5096 if (type->tt_type == VAR_LIST
5097 && ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type
5098 != VAR_NUMBER)
5099 {
5100 emsg(_(e_number_exp));
5101 goto theend;
5102 }
5103
5104 // Load the dict or list. On the stack we then have:
5105 // - value
5106 // - index
5107 // - variable
5108 generate_loadvar(cctx, dest, name, lvar, type);
5109
5110 if (type->tt_type == VAR_LIST)
5111 {
5112 if (generate_instr_drop(cctx, ISN_STORELIST, 3) == FAIL)
5113 return FAIL;
5114 }
5115 else if (type->tt_type == VAR_DICT)
5116 {
5117 if (generate_instr_drop(cctx, ISN_STOREDICT, 3) == FAIL)
5118 return FAIL;
5119 }
5120 else
5121 {
5122 emsg(_(e_listreq));
5123 goto theend;
5124 }
5125 }
5126 else
5127 {
5128 switch (dest)
5129 {
5130 case dest_option:
5131 generate_STOREOPT(cctx, name + 1, opt_flags);
5132 break;
5133 case dest_global:
5134 // include g: with the name, easier to execute that way
5135 generate_STORE(cctx, ISN_STOREG, 0, name);
5136 break;
5137 case dest_buffer:
5138 // include b: with the name, easier to execute that way
5139 generate_STORE(cctx, ISN_STOREB, 0, name);
5140 break;
5141 case dest_window:
5142 // include w: with the name, easier to execute that way
5143 generate_STORE(cctx, ISN_STOREW, 0, name);
5144 break;
5145 case dest_tab:
5146 // include t: with the name, easier to execute that way
5147 generate_STORE(cctx, ISN_STORET, 0, name);
5148 break;
5149 case dest_env:
5150 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
5151 break;
5152 case dest_reg:
5153 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
5154 break;
5155 case dest_vimvar:
5156 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
5157 break;
5158 case dest_script:
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005159 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005160 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
5161 imported_T *import = NULL;
5162 int sid = current_sctx.sc_sid;
5163 int idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005164
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005165 if (name[1] != ':')
5166 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005167 import = find_imported(name, 0, cctx);
5168 if (import != NULL)
5169 sid = import->imp_sid;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005170 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005171
5172 idx = get_script_item_idx(sid, rawname, TRUE);
5173 // TODO: specific type
5174 if (idx < 0)
5175 {
5176 char_u *name_s = name;
5177
5178 // Include s: in the name for store_var()
5179 if (name[1] != ':')
5180 {
5181 int len = (int)STRLEN(name) + 3;
5182
5183 name_s = alloc(len);
5184 if (name_s == NULL)
5185 name_s = name;
5186 else
5187 vim_snprintf((char *)name_s, len, "s:%s", name);
5188 }
5189 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid,
5190 &t_any);
5191 if (name_s != name)
5192 vim_free(name_s);
5193 }
5194 else
5195 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005196 sid, idx, &t_any);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01005197 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005198 break;
5199 case dest_local:
5200 if (lvar != NULL)
5201 {
5202 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
5203
5204 // optimization: turn "var = 123" from ISN_PUSHNR +
5205 // ISN_STORE into ISN_STORENR
5206 if (!lvar->lv_from_outer && instr->ga_len == instr_count + 1
5207 && isn->isn_type == ISN_PUSHNR)
5208 {
5209 varnumber_T val = isn->isn_arg.number;
5210
5211 isn->isn_type = ISN_STORENR;
5212 isn->isn_arg.storenr.stnr_idx = lvar->lv_idx;
5213 isn->isn_arg.storenr.stnr_val = val;
5214 if (stack->ga_len > 0)
5215 --stack->ga_len;
5216 }
5217 else if (lvar->lv_from_outer)
5218 generate_STORE(cctx, ISN_STOREOUTER, lvar->lv_idx,
5219 NULL);
5220 else
5221 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
5222 }
5223 break;
5224 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005225 }
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02005226 ret = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005227
5228theend:
5229 vim_free(name);
5230 return ret;
5231}
5232
5233/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005234 * Check if "name" can be "unlet".
5235 */
5236 int
5237check_vim9_unlet(char_u *name)
5238{
5239 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
5240 {
5241 semsg(_("E1081: Cannot unlet %s"), name);
5242 return FAIL;
5243 }
5244 return OK;
5245}
5246
5247/*
5248 * Callback passed to ex_unletlock().
5249 */
5250 static int
5251compile_unlet(
5252 lval_T *lvp,
5253 char_u *name_end,
5254 exarg_T *eap,
5255 int deep UNUSED,
5256 void *coookie)
5257{
5258 cctx_T *cctx = coookie;
5259
5260 if (lvp->ll_tv == NULL)
5261 {
5262 char_u *p = lvp->ll_name;
5263 int cc = *name_end;
5264 int ret = OK;
5265
5266 // Normal name. Only supports g:, w:, t: and b: namespaces.
5267 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005268 if (*p == '$')
5269 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
5270 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005271 ret = FAIL;
5272 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02005273 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02005274
5275 *name_end = cc;
5276 return ret;
5277 }
5278
5279 // TODO: unlet {list}[idx]
5280 // TODO: unlet {dict}[key]
5281 emsg("Sorry, :unlet not fully implemented yet");
5282 return FAIL;
5283}
5284
5285/*
5286 * compile "unlet var", "lock var" and "unlock var"
5287 * "arg" points to "var".
5288 */
5289 static char_u *
5290compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
5291{
5292 char_u *p = arg;
5293
5294 if (eap->cmdidx != CMD_unlet)
5295 {
5296 emsg("Sorry, :lock and unlock not implemented yet");
5297 return NULL;
5298 }
5299
5300 if (*p == '!')
5301 {
5302 p = skipwhite(p + 1);
5303 eap->forceit = TRUE;
5304 }
5305
5306 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
5307 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
5308}
5309
5310/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005311 * Compile an :import command.
5312 */
5313 static char_u *
5314compile_import(char_u *arg, cctx_T *cctx)
5315{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01005316 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005317}
5318
5319/*
5320 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
5321 */
5322 static int
5323compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
5324{
5325 garray_T *instr = &cctx->ctx_instr;
5326 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
5327
5328 if (endlabel == NULL)
5329 return FAIL;
5330 endlabel->el_next = *el;
5331 *el = endlabel;
5332 endlabel->el_end_label = instr->ga_len;
5333
5334 generate_JUMP(cctx, when, 0);
5335 return OK;
5336}
5337
5338 static void
5339compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
5340{
5341 garray_T *instr = &cctx->ctx_instr;
5342
5343 while (*el != NULL)
5344 {
5345 endlabel_T *cur = (*el);
5346 isn_T *isn;
5347
5348 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
5349 isn->isn_arg.jump.jump_where = instr->ga_len;
5350 *el = cur->el_next;
5351 vim_free(cur);
5352 }
5353}
5354
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005355 static void
5356compile_free_jump_to_end(endlabel_T **el)
5357{
5358 while (*el != NULL)
5359 {
5360 endlabel_T *cur = (*el);
5361
5362 *el = cur->el_next;
5363 vim_free(cur);
5364 }
5365}
5366
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005367/*
5368 * Create a new scope and set up the generic items.
5369 */
5370 static scope_T *
5371new_scope(cctx_T *cctx, scopetype_T type)
5372{
5373 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
5374
5375 if (scope == NULL)
5376 return NULL;
5377 scope->se_outer = cctx->ctx_scope;
5378 cctx->ctx_scope = scope;
5379 scope->se_type = type;
5380 scope->se_local_count = cctx->ctx_locals.ga_len;
5381 return scope;
5382}
5383
5384/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005385 * Free the current scope and go back to the outer scope.
5386 */
5387 static void
5388drop_scope(cctx_T *cctx)
5389{
5390 scope_T *scope = cctx->ctx_scope;
5391
5392 if (scope == NULL)
5393 {
5394 iemsg("calling drop_scope() without a scope");
5395 return;
5396 }
5397 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005398 switch (scope->se_type)
5399 {
5400 case IF_SCOPE:
5401 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
5402 case FOR_SCOPE:
5403 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
5404 case WHILE_SCOPE:
5405 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
5406 case TRY_SCOPE:
5407 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
5408 case NO_SCOPE:
5409 case BLOCK_SCOPE:
5410 break;
5411 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005412 vim_free(scope);
5413}
5414
5415/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005416 * compile "if expr"
5417 *
5418 * "if expr" Produces instructions:
5419 * EVAL expr Push result of "expr"
5420 * JUMP_IF_FALSE end
5421 * ... body ...
5422 * end:
5423 *
5424 * "if expr | else" Produces instructions:
5425 * EVAL expr Push result of "expr"
5426 * JUMP_IF_FALSE else
5427 * ... body ...
5428 * JUMP_ALWAYS end
5429 * else:
5430 * ... body ...
5431 * end:
5432 *
5433 * "if expr1 | elseif expr2 | else" Produces instructions:
5434 * EVAL expr Push result of "expr"
5435 * JUMP_IF_FALSE elseif
5436 * ... body ...
5437 * JUMP_ALWAYS end
5438 * elseif:
5439 * EVAL expr Push result of "expr"
5440 * JUMP_IF_FALSE else
5441 * ... body ...
5442 * JUMP_ALWAYS end
5443 * else:
5444 * ... body ...
5445 * end:
5446 */
5447 static char_u *
5448compile_if(char_u *arg, cctx_T *cctx)
5449{
5450 char_u *p = arg;
5451 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005452 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005453 scope_T *scope;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005454 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005455
Bram Moolenaara5565e42020-05-09 15:44:01 +02005456 CLEAR_FIELD(ppconst);
5457 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005458 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02005459 clear_ppconst(&ppconst);
5460 return NULL;
5461 }
5462 if (instr->ga_len == instr_count && ppconst.pp_used == 1)
5463 {
5464 // The expression results in a constant.
5465 // TODO: how about nesting?
5466 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? FALSE : TRUE;
5467 clear_ppconst(&ppconst);
5468 }
5469 else
5470 {
5471 // Not a constant, generate instructions for the expression.
5472 cctx->ctx_skip = MAYBE;
5473 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005474 return NULL;
5475 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005476
5477 scope = new_scope(cctx, IF_SCOPE);
5478 if (scope == NULL)
5479 return NULL;
5480
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005481 if (cctx->ctx_skip == MAYBE)
5482 {
5483 // "where" is set when ":elseif", "else" or ":endif" is found
5484 scope->se_u.se_if.is_if_label = instr->ga_len;
5485 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5486 }
5487 else
5488 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005489
5490 return p;
5491}
5492
5493 static char_u *
5494compile_elseif(char_u *arg, cctx_T *cctx)
5495{
5496 char_u *p = arg;
5497 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005498 int instr_count = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005499 isn_T *isn;
5500 scope_T *scope = cctx->ctx_scope;
Bram Moolenaar7f141552020-05-09 17:35:53 +02005501 ppconst_T ppconst;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005502
5503 if (scope == NULL || scope->se_type != IF_SCOPE)
5504 {
5505 emsg(_(e_elseif_without_if));
5506 return NULL;
5507 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005508 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005509
Bram Moolenaar158906c2020-02-06 20:39:45 +01005510 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005511 {
5512 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005513 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005514 return NULL;
5515 // previous "if" or "elseif" jumps here
5516 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5517 isn->isn_arg.jump.jump_where = instr->ga_len;
5518 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005519
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005520 // compile "expr"; if we know it evaluates to FALSE skip the block
Bram Moolenaar7f141552020-05-09 17:35:53 +02005521 CLEAR_FIELD(ppconst);
5522 if (compile_expr1(&p, cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005523 {
Bram Moolenaar7f141552020-05-09 17:35:53 +02005524 clear_ppconst(&ppconst);
5525 return NULL;
5526 }
5527 if (instr->ga_len == instr_count && ppconst.pp_used == 1)
5528 {
5529 // The expression results in a constant.
5530 // TODO: how about nesting?
5531 cctx->ctx_skip = tv2bool(&ppconst.pp_tv[0]) ? FALSE : TRUE;
5532 clear_ppconst(&ppconst);
5533 scope->se_u.se_if.is_if_label = -1;
5534 }
5535 else
5536 {
5537 // Not a constant, generate instructions for the expression.
5538 cctx->ctx_skip = MAYBE;
5539 if (generate_ppconst(cctx, &ppconst) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005540 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005541
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005542 // "where" is set when ":elseif", "else" or ":endif" is found
5543 scope->se_u.se_if.is_if_label = instr->ga_len;
5544 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5545 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005546
5547 return p;
5548}
5549
5550 static char_u *
5551compile_else(char_u *arg, cctx_T *cctx)
5552{
5553 char_u *p = arg;
5554 garray_T *instr = &cctx->ctx_instr;
5555 isn_T *isn;
5556 scope_T *scope = cctx->ctx_scope;
5557
5558 if (scope == NULL || scope->se_type != IF_SCOPE)
5559 {
5560 emsg(_(e_else_without_if));
5561 return NULL;
5562 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005563 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005564
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005565 // jump from previous block to the end, unless the else block is empty
5566 if (cctx->ctx_skip == MAYBE)
5567 {
5568 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005569 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005570 return NULL;
5571 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005572
Bram Moolenaar158906c2020-02-06 20:39:45 +01005573 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005574 {
5575 if (scope->se_u.se_if.is_if_label >= 0)
5576 {
5577 // previous "if" or "elseif" jumps here
5578 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5579 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005580 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005581 }
5582 }
5583
5584 if (cctx->ctx_skip != MAYBE)
5585 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005586
5587 return p;
5588}
5589
5590 static char_u *
5591compile_endif(char_u *arg, cctx_T *cctx)
5592{
5593 scope_T *scope = cctx->ctx_scope;
5594 ifscope_T *ifscope;
5595 garray_T *instr = &cctx->ctx_instr;
5596 isn_T *isn;
5597
5598 if (scope == NULL || scope->se_type != IF_SCOPE)
5599 {
5600 emsg(_(e_endif_without_if));
5601 return NULL;
5602 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005603 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005604 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005605
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005606 if (scope->se_u.se_if.is_if_label >= 0)
5607 {
5608 // previous "if" or "elseif" jumps here
5609 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5610 isn->isn_arg.jump.jump_where = instr->ga_len;
5611 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005612 // Fill in the "end" label in jumps at the end of the blocks.
5613 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005614 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005615
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005616 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005617 return arg;
5618}
5619
5620/*
5621 * compile "for var in expr"
5622 *
5623 * Produces instructions:
5624 * PUSHNR -1
5625 * STORE loop-idx Set index to -1
5626 * EVAL expr Push result of "expr"
5627 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5628 * - if beyond end, jump to "end"
5629 * - otherwise get item from list and push it
5630 * STORE var Store item in "var"
5631 * ... body ...
5632 * JUMP top Jump back to repeat
5633 * end: DROP Drop the result of "expr"
5634 *
5635 */
5636 static char_u *
5637compile_for(char_u *arg, cctx_T *cctx)
5638{
5639 char_u *p;
5640 size_t varlen;
5641 garray_T *instr = &cctx->ctx_instr;
5642 garray_T *stack = &cctx->ctx_type_stack;
5643 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005644 lvar_T *loop_lvar; // loop iteration variable
5645 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005646 type_T *vartype;
5647
5648 // TODO: list of variables: "for [key, value] in dict"
5649 // parse "var"
5650 for (p = arg; eval_isnamec1(*p); ++p)
5651 ;
5652 varlen = p - arg;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005653 var_lvar = lookup_local(arg, varlen, cctx);
5654 if (var_lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005655 {
5656 semsg(_("E1023: variable already defined: %s"), arg);
5657 return NULL;
5658 }
5659
5660 // consume "in"
5661 p = skipwhite(p);
5662 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5663 {
5664 emsg(_(e_missing_in));
5665 return NULL;
5666 }
5667 p = skipwhite(p + 2);
5668
5669
5670 scope = new_scope(cctx, FOR_SCOPE);
5671 if (scope == NULL)
5672 return NULL;
5673
5674 // Reserve a variable to store the loop iteration counter.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005675 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5676 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005677 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005678 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005679 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005680 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005681 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005682
5683 // Reserve a variable to store "var"
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005684 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5685 if (var_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005686 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005687 // out of memory or used as an argument
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005688 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005689 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005690 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005691
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005692 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005693
5694 // compile "expr", it remains on the stack until "endfor"
5695 arg = p;
Bram Moolenaara5565e42020-05-09 15:44:01 +02005696 if (compile_expr0(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005697 {
5698 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005699 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005700 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005701
5702 // now we know the type of "var"
5703 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5704 if (vartype->tt_type != VAR_LIST)
5705 {
5706 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005707 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005708 return NULL;
5709 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005710 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005711 var_lvar->lv_type = vartype->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005712
5713 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005714 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005715
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005716 generate_FOR(cctx, loop_lvar->lv_idx);
5717 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005718
5719 return arg;
5720}
5721
5722/*
5723 * compile "endfor"
5724 */
5725 static char_u *
5726compile_endfor(char_u *arg, cctx_T *cctx)
5727{
5728 garray_T *instr = &cctx->ctx_instr;
5729 scope_T *scope = cctx->ctx_scope;
5730 forscope_T *forscope;
5731 isn_T *isn;
5732
5733 if (scope == NULL || scope->se_type != FOR_SCOPE)
5734 {
5735 emsg(_(e_for));
5736 return NULL;
5737 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005738 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005739 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005740 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005741
5742 // At end of ":for" scope jump back to the FOR instruction.
5743 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5744
5745 // Fill in the "end" label in the FOR statement so it can jump here
5746 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5747 isn->isn_arg.forloop.for_end = instr->ga_len;
5748
5749 // Fill in the "end" label any BREAK statements
5750 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5751
5752 // Below the ":for" scope drop the "expr" list from the stack.
5753 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5754 return NULL;
5755
5756 vim_free(scope);
5757
5758 return arg;
5759}
5760
5761/*
5762 * compile "while expr"
5763 *
5764 * Produces instructions:
5765 * top: EVAL expr Push result of "expr"
5766 * JUMP_IF_FALSE end jump if false
5767 * ... body ...
5768 * JUMP top Jump back to repeat
5769 * end:
5770 *
5771 */
5772 static char_u *
5773compile_while(char_u *arg, cctx_T *cctx)
5774{
5775 char_u *p = arg;
5776 garray_T *instr = &cctx->ctx_instr;
5777 scope_T *scope;
5778
5779 scope = new_scope(cctx, WHILE_SCOPE);
5780 if (scope == NULL)
5781 return NULL;
5782
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005783 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005784
5785 // compile "expr"
Bram Moolenaara5565e42020-05-09 15:44:01 +02005786 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005787 return NULL;
5788
5789 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005790 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005791 JUMP_IF_FALSE, cctx) == FAIL)
5792 return FAIL;
5793
5794 return p;
5795}
5796
5797/*
5798 * compile "endwhile"
5799 */
5800 static char_u *
5801compile_endwhile(char_u *arg, cctx_T *cctx)
5802{
5803 scope_T *scope = cctx->ctx_scope;
5804
5805 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5806 {
5807 emsg(_(e_while));
5808 return NULL;
5809 }
5810 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005811 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005812
5813 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005814 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005815
5816 // Fill in the "end" label in the WHILE statement so it can jump here.
5817 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005818 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005819
5820 vim_free(scope);
5821
5822 return arg;
5823}
5824
5825/*
5826 * compile "continue"
5827 */
5828 static char_u *
5829compile_continue(char_u *arg, cctx_T *cctx)
5830{
5831 scope_T *scope = cctx->ctx_scope;
5832
5833 for (;;)
5834 {
5835 if (scope == NULL)
5836 {
5837 emsg(_(e_continue));
5838 return NULL;
5839 }
5840 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5841 break;
5842 scope = scope->se_outer;
5843 }
5844
5845 // Jump back to the FOR or WHILE instruction.
5846 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005847 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5848 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005849 return arg;
5850}
5851
5852/*
5853 * compile "break"
5854 */
5855 static char_u *
5856compile_break(char_u *arg, cctx_T *cctx)
5857{
5858 scope_T *scope = cctx->ctx_scope;
5859 endlabel_T **el;
5860
5861 for (;;)
5862 {
5863 if (scope == NULL)
5864 {
5865 emsg(_(e_break));
5866 return NULL;
5867 }
5868 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5869 break;
5870 scope = scope->se_outer;
5871 }
5872
5873 // Jump to the end of the FOR or WHILE loop.
5874 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005875 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005876 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005877 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005878 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5879 return FAIL;
5880
5881 return arg;
5882}
5883
5884/*
5885 * compile "{" start of block
5886 */
5887 static char_u *
5888compile_block(char_u *arg, cctx_T *cctx)
5889{
5890 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5891 return NULL;
5892 return skipwhite(arg + 1);
5893}
5894
5895/*
5896 * compile end of block: drop one scope
5897 */
5898 static void
5899compile_endblock(cctx_T *cctx)
5900{
5901 scope_T *scope = cctx->ctx_scope;
5902
5903 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005904 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005905 vim_free(scope);
5906}
5907
5908/*
5909 * compile "try"
5910 * Creates a new scope for the try-endtry, pointing to the first catch and
5911 * finally.
5912 * Creates another scope for the "try" block itself.
5913 * TRY instruction sets up exception handling at runtime.
5914 *
5915 * "try"
5916 * TRY -> catch1, -> finally push trystack entry
5917 * ... try block
5918 * "throw {exception}"
5919 * EVAL {exception}
5920 * THROW create exception
5921 * ... try block
5922 * " catch {expr}"
5923 * JUMP -> finally
5924 * catch1: PUSH exeception
5925 * EVAL {expr}
5926 * MATCH
5927 * JUMP nomatch -> catch2
5928 * CATCH remove exception
5929 * ... catch block
5930 * " catch"
5931 * JUMP -> finally
5932 * catch2: CATCH remove exception
5933 * ... catch block
5934 * " finally"
5935 * finally:
5936 * ... finally block
5937 * " endtry"
5938 * ENDTRY pop trystack entry, may rethrow
5939 */
5940 static char_u *
5941compile_try(char_u *arg, cctx_T *cctx)
5942{
5943 garray_T *instr = &cctx->ctx_instr;
5944 scope_T *try_scope;
5945 scope_T *scope;
5946
5947 // scope that holds the jumps that go to catch/finally/endtry
5948 try_scope = new_scope(cctx, TRY_SCOPE);
5949 if (try_scope == NULL)
5950 return NULL;
5951
5952 // "catch" is set when the first ":catch" is found.
5953 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005954 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005955 if (generate_instr(cctx, ISN_TRY) == NULL)
5956 return NULL;
5957
5958 // scope for the try block itself
5959 scope = new_scope(cctx, BLOCK_SCOPE);
5960 if (scope == NULL)
5961 return NULL;
5962
5963 return arg;
5964}
5965
5966/*
5967 * compile "catch {expr}"
5968 */
5969 static char_u *
5970compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5971{
5972 scope_T *scope = cctx->ctx_scope;
5973 garray_T *instr = &cctx->ctx_instr;
5974 char_u *p;
5975 isn_T *isn;
5976
5977 // end block scope from :try or :catch
5978 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5979 compile_endblock(cctx);
5980 scope = cctx->ctx_scope;
5981
5982 // Error if not in a :try scope
5983 if (scope == NULL || scope->se_type != TRY_SCOPE)
5984 {
5985 emsg(_(e_catch));
5986 return NULL;
5987 }
5988
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005989 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005990 {
5991 emsg(_("E1033: catch unreachable after catch-all"));
5992 return NULL;
5993 }
5994
5995 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005996 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005997 JUMP_ALWAYS, cctx) == FAIL)
5998 return NULL;
5999
6000 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006001 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006002 if (isn->isn_arg.try.try_catch == 0)
6003 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006004 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006005 {
6006 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006007 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006008 isn->isn_arg.jump.jump_where = instr->ga_len;
6009 }
6010
6011 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02006012 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006013 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006014 scope->se_u.se_try.ts_caught_all = TRUE;
6015 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006016 }
6017 else
6018 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006019 char_u *end;
6020 char_u *pat;
6021 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006022 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006023 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006024
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006025 // Push v:exception, push {expr} and MATCH
6026 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
6027
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006028 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006029 if (*end != *p)
6030 {
6031 semsg(_("E1067: Separator mismatch: %s"), p);
6032 vim_free(tofree);
6033 return FAIL;
6034 }
6035 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01006036 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006037 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006038 len = (int)(end - tofree);
6039 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006040 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02006041 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01006042 if (pat == NULL)
6043 return FAIL;
6044 if (generate_PUSHS(cctx, pat) == FAIL)
6045 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006046
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006047 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
6048 return NULL;
6049
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006050 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006051 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
6052 return NULL;
6053 }
6054
6055 if (generate_instr(cctx, ISN_CATCH) == NULL)
6056 return NULL;
6057
6058 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
6059 return NULL;
6060 return p;
6061}
6062
6063 static char_u *
6064compile_finally(char_u *arg, cctx_T *cctx)
6065{
6066 scope_T *scope = cctx->ctx_scope;
6067 garray_T *instr = &cctx->ctx_instr;
6068 isn_T *isn;
6069
6070 // end block scope from :try or :catch
6071 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6072 compile_endblock(cctx);
6073 scope = cctx->ctx_scope;
6074
6075 // Error if not in a :try scope
6076 if (scope == NULL || scope->se_type != TRY_SCOPE)
6077 {
6078 emsg(_(e_finally));
6079 return NULL;
6080 }
6081
6082 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006083 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006084 if (isn->isn_arg.try.try_finally != 0)
6085 {
6086 emsg(_(e_finally_dup));
6087 return NULL;
6088 }
6089
6090 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006091 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006092
Bram Moolenaar585fea72020-04-02 22:33:21 +02006093 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006094 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006095 {
6096 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006097 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006098 isn->isn_arg.jump.jump_where = instr->ga_len;
6099 }
6100
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006101 // TODO: set index in ts_finally_label jumps
6102
6103 return arg;
6104}
6105
6106 static char_u *
6107compile_endtry(char_u *arg, cctx_T *cctx)
6108{
6109 scope_T *scope = cctx->ctx_scope;
6110 garray_T *instr = &cctx->ctx_instr;
6111 isn_T *isn;
6112
6113 // end block scope from :catch or :finally
6114 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
6115 compile_endblock(cctx);
6116 scope = cctx->ctx_scope;
6117
6118 // Error if not in a :try scope
6119 if (scope == NULL || scope->se_type != TRY_SCOPE)
6120 {
6121 if (scope == NULL)
6122 emsg(_(e_no_endtry));
6123 else if (scope->se_type == WHILE_SCOPE)
6124 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01006125 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006126 emsg(_(e_endfor));
6127 else
6128 emsg(_(e_endif));
6129 return NULL;
6130 }
6131
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006132 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006133 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
6134 {
6135 emsg(_("E1032: missing :catch or :finally"));
6136 return NULL;
6137 }
6138
6139 // Fill in the "end" label in jumps at the end of the blocks, if not done
6140 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01006141 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006142
6143 // End :catch or :finally scope: set value in ISN_TRY instruction
6144 if (isn->isn_arg.try.try_finally == 0)
6145 isn->isn_arg.try.try_finally = instr->ga_len;
6146 compile_endblock(cctx);
6147
6148 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
6149 return NULL;
6150 return arg;
6151}
6152
6153/*
6154 * compile "throw {expr}"
6155 */
6156 static char_u *
6157compile_throw(char_u *arg, cctx_T *cctx UNUSED)
6158{
6159 char_u *p = skipwhite(arg);
6160
Bram Moolenaara5565e42020-05-09 15:44:01 +02006161 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006162 return NULL;
6163 if (may_generate_2STRING(-1, cctx) == FAIL)
6164 return NULL;
6165 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
6166 return NULL;
6167
6168 return p;
6169}
6170
6171/*
6172 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006173 * compile "echomsg expr"
6174 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01006175 * compile "execute expr"
6176 */
6177 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006178compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006179{
6180 char_u *p = arg;
6181 int count = 0;
6182
6183 for (;;)
6184 {
Bram Moolenaara5565e42020-05-09 15:44:01 +02006185 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01006186 return NULL;
6187 ++count;
6188 p = skipwhite(p);
6189 if (ends_excmd(*p))
6190 break;
6191 }
6192
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006193 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
6194 generate_ECHO(cctx, cmdidx == CMD_echo, count);
6195 else if (cmdidx == CMD_execute)
6196 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
6197 else if (cmdidx == CMD_echomsg)
6198 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
6199 else
6200 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006201 return p;
6202}
6203
6204/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006205 * A command that is not compiled, execute with legacy code.
6206 */
6207 static char_u *
6208compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
6209{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006210 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006211 int has_expr = FALSE;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006212
6213 if (cctx->ctx_skip == TRUE)
6214 goto theend;
6215
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02006216 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
6217 has_expr = (excmd_get_argt(eap->cmdidx) & (EX_XFILE | EX_EXPAND));
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006218 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
6219 {
6220 // expand filename in "syntax include [@group] filename"
6221 has_expr = TRUE;
6222 eap->arg = skipwhite(eap->arg + 7);
6223 if (*eap->arg == '@')
6224 eap->arg = skiptowhite(eap->arg);
6225 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006226
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02006227 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006228 {
6229 int count = 0;
6230 char_u *start = skipwhite(line);
6231
6232 // :cmd xxx`=expr1`yyy`=expr2`zzz
6233 // PUSHS ":cmd xxx"
6234 // eval expr1
6235 // PUSHS "yyy"
6236 // eval expr2
6237 // PUSHS "zzz"
6238 // EXECCONCAT 5
6239 for (;;)
6240 {
6241 if (p > start)
6242 {
6243 generate_PUSHS(cctx, vim_strnsave(start, (int)(p - start)));
6244 ++count;
6245 }
6246 p += 2;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006247 if (compile_expr0(&p, cctx) == FAIL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006248 return NULL;
6249 may_generate_2STRING(-1, cctx);
6250 ++count;
6251 p = skipwhite(p);
6252 if (*p != '`')
6253 {
6254 emsg(_("E1083: missing backtick"));
6255 return NULL;
6256 }
6257 start = p + 1;
6258
6259 p = (char_u *)strstr((char *)start, "`=");
6260 if (p == NULL)
6261 {
6262 if (*skipwhite(start) != NUL)
6263 {
6264 generate_PUSHS(cctx, vim_strsave(start));
6265 ++count;
6266 }
6267 break;
6268 }
6269 }
6270 generate_EXECCONCAT(cctx, count);
6271 }
6272 else
6273 generate_EXEC(cctx, line);
6274
6275theend:
6276 return (char_u *)"";
6277}
6278
6279/*
Bram Moolenaar09689a02020-05-09 22:50:08 +02006280 * Add a function to the list of :def functions.
6281 * This "sets ufunc->uf_dfunc_idx" but the function isn't compiled yet.
6282 */
6283 int
6284add_def_function(ufunc_T *ufunc)
6285{
6286 dfunc_T *dfunc;
6287
6288 // Add the function to "def_functions".
6289 if (ga_grow(&def_functions, 1) == FAIL)
6290 return FAIL;
6291 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
6292 CLEAR_POINTER(dfunc);
6293 dfunc->df_idx = def_functions.ga_len;
6294 ufunc->uf_dfunc_idx = dfunc->df_idx;
6295 dfunc->df_ufunc = ufunc;
6296 ++def_functions.ga_len;
6297 return OK;
6298}
6299
6300/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006301 * After ex_function() has collected all the function lines: parse and compile
6302 * the lines into instructions.
6303 * Adds the function to "def_functions".
6304 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
6305 * return statement (used for lambda).
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006306 * "outer_cctx" is set for a nested function.
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006307 * This can be used recursively through compile_lambda(), which may reallocate
6308 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006309 */
6310 void
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006311compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006312{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006313 char_u *line = NULL;
6314 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006315 char *errormsg = NULL; // error message
6316 int had_return = FALSE;
6317 cctx_T cctx;
6318 garray_T *instr;
6319 int called_emsg_before = called_emsg;
6320 int ret = FAIL;
6321 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006322 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006323
Bram Moolenaar09689a02020-05-09 22:50:08 +02006324 if (ufunc->uf_dfunc_idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006325 {
Bram Moolenaar09689a02020-05-09 22:50:08 +02006326 // Redefining a function that was compiled before.
6327 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6328 + ufunc->uf_dfunc_idx;
6329 // Free old instructions.
6330 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006331 }
Bram Moolenaar09689a02020-05-09 22:50:08 +02006332 else if (add_def_function(ufunc) == FAIL)
6333 return;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006334
Bram Moolenaara80faa82020-04-12 19:37:17 +02006335 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006336 cctx.ctx_ufunc = ufunc;
6337 cctx.ctx_lnum = -1;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006338 cctx.ctx_outer = outer_cctx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006339 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
6340 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
6341 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
6342 cctx.ctx_type_list = &ufunc->uf_type_list;
6343 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
6344 instr = &cctx.ctx_instr;
6345
6346 // Most modern script version.
6347 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
6348
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006349 if (ufunc->uf_def_args.ga_len > 0)
6350 {
6351 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006352 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006353 int i;
6354 char_u *arg;
6355 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
6356
6357 // Produce instructions for the default values of optional arguments.
6358 // Store the instruction index in uf_def_arg_idx[] so that we know
6359 // where to start when the function is called, depending on the number
6360 // of arguments.
6361 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
6362 if (ufunc->uf_def_arg_idx == NULL)
6363 goto erret;
6364 for (i = 0; i < count; ++i)
6365 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006366 garray_T *stack = &cctx.ctx_type_stack;
6367 type_T *val_type;
6368 int arg_idx = first_def_arg + i;
6369
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006370 ufunc->uf_def_arg_idx[i] = instr->ga_len;
6371 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaara5565e42020-05-09 15:44:01 +02006372 if (compile_expr0(&arg, &cctx) == FAIL)
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006373 goto erret;
6374
6375 // If no type specified use the type of the default value.
6376 // Otherwise check that the default value type matches the
6377 // specified type.
6378 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6379 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
6380 ufunc->uf_arg_types[arg_idx] = val_type;
6381 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
6382 == FAIL)
6383 {
6384 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
6385 arg_idx + 1);
6386 goto erret;
6387 }
6388
6389 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006390 goto erret;
6391 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006392 ufunc->uf_def_arg_idx[count] = instr->ga_len;
6393 }
6394
6395 /*
6396 * Loop over all the lines of the function and generate instructions.
6397 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006398 for (;;)
6399 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006400 exarg_T ea;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006401 int starts_with_colon = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006402
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006403 // Bail out on the first error to avoid a flood of errors and report
6404 // the right line number when inside try/catch.
6405 if (emsg_before != called_emsg)
6406 goto erret;
6407
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006408 if (line != NULL && *line == '|')
6409 // the line continues after a '|'
6410 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02006411 else if (line != NULL && *line != NUL
6412 && !(*line == '#' && (line == cctx.ctx_line_start
6413 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006414 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006415 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006416 goto erret;
6417 }
6418 else
6419 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006420 line = next_line_from_context(&cctx);
6421 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006422 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006423 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006424 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006425 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006426
6427 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006428 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006429 ea.cmdlinep = &line;
6430 ea.cmd = skipwhite(line);
6431
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006432 // Some things can be recognized by the first character.
6433 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006434 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006435 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006436 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006437 if (ea.cmd[1] != '{')
6438 {
6439 line = (char_u *)"";
6440 continue;
6441 }
6442 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006443
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006444 case '}':
6445 {
6446 // "}" ends a block scope
6447 scopetype_T stype = cctx.ctx_scope == NULL
6448 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006449
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006450 if (stype == BLOCK_SCOPE)
6451 {
6452 compile_endblock(&cctx);
6453 line = ea.cmd;
6454 }
6455 else
6456 {
6457 emsg(_("E1025: using } outside of a block scope"));
6458 goto erret;
6459 }
6460 if (line != NULL)
6461 line = skipwhite(ea.cmd + 1);
6462 continue;
6463 }
6464
6465 case '{':
6466 // "{" starts a block scope
6467 // "{'a': 1}->func() is something else
6468 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6469 {
6470 line = compile_block(ea.cmd, &cctx);
6471 continue;
6472 }
6473 break;
6474
6475 case ':':
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006476 starts_with_colon = TRUE;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006477 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006478 }
6479
6480 /*
6481 * COMMAND MODIFIERS
6482 */
6483 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6484 {
6485 if (errormsg != NULL)
6486 goto erret;
6487 // empty line or comment
6488 line = (char_u *)"";
6489 continue;
6490 }
6491
6492 // Skip ":call" to get to the function name.
6493 if (checkforcmd(&ea.cmd, "call", 3))
6494 ea.cmd = skipwhite(ea.cmd);
6495
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006496 if (!starts_with_colon)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006497 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006498 char_u *pskip;
6499
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006500 // Assuming the command starts with a variable or function name,
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006501 // find what follows.
6502 // Skip over "var.member", "var[idx]" and the like.
6503 // Also "&opt = val", "$ENV = val" and "@r = val".
6504 pskip = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006505 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006506 p = to_name_end(pskip, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006507 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006508 {
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006509 char_u *var_end;
6510 int oplen;
6511 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006512
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006513 var_end = find_name_end(pskip, NULL, NULL,
6514 FNE_CHECK_START | FNE_INCL_BR);
6515 oplen = assignment_len(skipwhite(var_end), &heredoc);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006516 if (oplen > 0)
6517 {
6518 // Recognize an assignment if we recognize the variable
6519 // name:
6520 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006521 // "local = expr" where "local" is a local var.
6522 // "script = expr" where "script" is a script-local var.
6523 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006524 // "&opt = expr"
6525 // "$ENV = expr"
6526 // "@r = expr"
6527 if (*ea.cmd == '&'
6528 || *ea.cmd == '$'
6529 || *ea.cmd == '@'
6530 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006531 || lookup_local(ea.cmd, p - ea.cmd, &cctx) != NULL
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006532 || lookup_script(ea.cmd, p - ea.cmd) == OK
6533 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6534 {
6535 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6536 if (line == NULL)
6537 goto erret;
6538 continue;
6539 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006540 }
6541 }
6542 }
6543
6544 /*
6545 * COMMAND after range
6546 */
6547 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006548 p = find_ex_command(&ea, NULL, starts_with_colon ? NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006549 : (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006550 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006551
6552 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6553 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006554 if (cctx.ctx_skip == TRUE)
6555 {
6556 line += STRLEN(line);
6557 continue;
6558 }
6559
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006560 // Expression or function call.
6561 if (ea.cmdidx == CMD_eval)
6562 {
6563 p = ea.cmd;
Bram Moolenaara5565e42020-05-09 15:44:01 +02006564 if (compile_expr0(&p, &cctx) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006565 goto erret;
6566
6567 // drop the return value
6568 generate_instr_drop(&cctx, ISN_DROP, 1);
6569 line = p;
6570 continue;
6571 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006572 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006573 iemsg("Command from find_ex_command() not handled");
6574 goto erret;
6575 }
6576
6577 p = skipwhite(p);
6578
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006579 if (cctx.ctx_skip == TRUE
6580 && ea.cmdidx != CMD_elseif
6581 && ea.cmdidx != CMD_else
6582 && ea.cmdidx != CMD_endif)
6583 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006584 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006585 continue;
6586 }
6587
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006588 switch (ea.cmdidx)
6589 {
6590 case CMD_def:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006591 ea.arg = p;
6592 line = compile_nested_function(&ea, &cctx);
6593 break;
6594
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006595 case CMD_function:
Bram Moolenaar04b12692020-05-04 23:24:44 +02006596 emsg(_("E1086: Cannot use :function inside :def"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006597 goto erret;
6598
6599 case CMD_return:
6600 line = compile_return(p, set_return_type, &cctx);
6601 had_return = TRUE;
6602 break;
6603
6604 case CMD_let:
6605 case CMD_const:
6606 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6607 break;
6608
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006609 case CMD_unlet:
6610 case CMD_unlockvar:
6611 case CMD_lockvar:
6612 line = compile_unletlock(p, &ea, &cctx);
6613 break;
6614
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006615 case CMD_import:
6616 line = compile_import(p, &cctx);
6617 break;
6618
6619 case CMD_if:
6620 line = compile_if(p, &cctx);
6621 break;
6622 case CMD_elseif:
6623 line = compile_elseif(p, &cctx);
6624 break;
6625 case CMD_else:
6626 line = compile_else(p, &cctx);
6627 break;
6628 case CMD_endif:
6629 line = compile_endif(p, &cctx);
6630 break;
6631
6632 case CMD_while:
6633 line = compile_while(p, &cctx);
6634 break;
6635 case CMD_endwhile:
6636 line = compile_endwhile(p, &cctx);
6637 break;
6638
6639 case CMD_for:
6640 line = compile_for(p, &cctx);
6641 break;
6642 case CMD_endfor:
6643 line = compile_endfor(p, &cctx);
6644 break;
6645 case CMD_continue:
6646 line = compile_continue(p, &cctx);
6647 break;
6648 case CMD_break:
6649 line = compile_break(p, &cctx);
6650 break;
6651
6652 case CMD_try:
6653 line = compile_try(p, &cctx);
6654 break;
6655 case CMD_catch:
6656 line = compile_catch(p, &cctx);
6657 break;
6658 case CMD_finally:
6659 line = compile_finally(p, &cctx);
6660 break;
6661 case CMD_endtry:
6662 line = compile_endtry(p, &cctx);
6663 break;
6664 case CMD_throw:
6665 line = compile_throw(p, &cctx);
6666 break;
6667
6668 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006669 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006670 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006671 case CMD_echomsg:
6672 case CMD_echoerr:
6673 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006674 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006675
6676 default:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006677 // TODO: other commands with an expression argument
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006678 // Not recognized, execute with do_cmdline_cmd().
6679 ea.arg = p;
6680 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006681 break;
6682 }
6683 if (line == NULL)
6684 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006685 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006686
6687 if (cctx.ctx_type_stack.ga_len < 0)
6688 {
6689 iemsg("Type stack underflow");
6690 goto erret;
6691 }
6692 }
6693
6694 if (cctx.ctx_scope != NULL)
6695 {
6696 if (cctx.ctx_scope->se_type == IF_SCOPE)
6697 emsg(_(e_endif));
6698 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6699 emsg(_(e_endwhile));
6700 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6701 emsg(_(e_endfor));
6702 else
6703 emsg(_("E1026: Missing }"));
6704 goto erret;
6705 }
6706
6707 if (!had_return)
6708 {
6709 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6710 {
6711 emsg(_("E1027: Missing return statement"));
6712 goto erret;
6713 }
6714
6715 // Return zero if there is no return at the end.
6716 generate_PUSHNR(&cctx, 0);
6717 generate_instr(&cctx, ISN_RETURN);
6718 }
6719
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006720 {
6721 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6722 + ufunc->uf_dfunc_idx;
6723 dfunc->df_deleted = FALSE;
6724 dfunc->df_instr = instr->ga_data;
6725 dfunc->df_instr_count = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006726 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaarbf67ea12020-05-02 17:52:42 +02006727 dfunc->df_closure_count = cctx.ctx_closure_count;
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006728 if (cctx.ctx_outer_used)
6729 ufunc->uf_flags |= FC_CLOSURE;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006730 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006731
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006732 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006733 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006734 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006735
6736 // Create a type for the function, with the return type and any
6737 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006738 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6739 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006740 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006741 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006742 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6743 argcount, &ufunc->uf_type_list);
6744 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006745 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006746 argcount + varargs,
6747 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006748 {
6749 ret = FAIL;
6750 goto erret;
6751 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006752 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6753 ufunc->uf_func_type->tt_min_argcount =
6754 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006755 if (ufunc->uf_arg_types == NULL)
6756 {
6757 int i;
6758
6759 // lambda does not have argument types.
6760 for (i = 0; i < argcount; ++i)
6761 ufunc->uf_func_type->tt_args[i] = &t_any;
6762 }
6763 else
6764 mch_memmove(ufunc->uf_func_type->tt_args,
6765 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006766 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006767 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006768 ufunc->uf_func_type->tt_args[argcount] =
6769 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006770 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6771 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006772 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006773 else
6774 // No arguments, can use a predefined type.
6775 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6776 argcount, &ufunc->uf_type_list);
6777
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006778 }
6779
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006780 ret = OK;
6781
6782erret:
6783 if (ret == FAIL)
6784 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006785 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006786 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6787 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006788
6789 for (idx = 0; idx < instr->ga_len; ++idx)
6790 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006791 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006792
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006793 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006794 if (!dfunc->df_deleted)
6795 --def_functions.ga_len;
6796
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006797 while (cctx.ctx_scope != NULL)
6798 drop_scope(&cctx);
6799
Bram Moolenaar20431c92020-03-20 18:39:46 +01006800 // Don't execute this function body.
6801 ga_clear_strings(&ufunc->uf_lines);
6802
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006803 if (errormsg != NULL)
6804 emsg(errormsg);
6805 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006806 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006807 }
6808
6809 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006810 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006811 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006812 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006813}
6814
6815/*
6816 * Delete an instruction, free what it contains.
6817 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006818 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006819delete_instr(isn_T *isn)
6820{
6821 switch (isn->isn_type)
6822 {
6823 case ISN_EXEC:
6824 case ISN_LOADENV:
6825 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006826 case ISN_LOADB:
6827 case ISN_LOADW:
6828 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006829 case ISN_LOADOPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006830 case ISN_STRINGMEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006831 case ISN_PUSHEXC:
6832 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006833 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006834 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006835 case ISN_STOREB:
6836 case ISN_STOREW:
6837 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006838 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006839 vim_free(isn->isn_arg.string);
6840 break;
6841
6842 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006843 case ISN_STORES:
6844 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006845 break;
6846
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006847 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006848 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006849 vim_free(isn->isn_arg.unlet.ul_name);
6850 break;
6851
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006852 case ISN_STOREOPT:
6853 vim_free(isn->isn_arg.storeopt.so_name);
6854 break;
6855
6856 case ISN_PUSHBLOB: // push blob isn_arg.blob
6857 blob_unref(isn->isn_arg.blob);
6858 break;
6859
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006860 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006861#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006862 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006863#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006864 break;
6865
6866 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006867#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006868 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006869#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006870 break;
6871
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006872 case ISN_UCALL:
6873 vim_free(isn->isn_arg.ufunc.cuf_name);
6874 break;
6875
Bram Moolenaar221fcc72020-05-05 19:46:20 +02006876 case ISN_FUNCREF:
6877 {
6878 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6879 + isn->isn_arg.funcref.fr_func;
6880 func_ptr_unref(dfunc->df_ufunc);
6881 }
6882 break;
6883
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006884 case ISN_2BOOL:
6885 case ISN_2STRING:
6886 case ISN_ADDBLOB:
6887 case ISN_ADDLIST:
6888 case ISN_BCALL:
6889 case ISN_CATCH:
6890 case ISN_CHECKNR:
6891 case ISN_CHECKTYPE:
6892 case ISN_COMPAREANY:
6893 case ISN_COMPAREBLOB:
6894 case ISN_COMPAREBOOL:
6895 case ISN_COMPAREDICT:
6896 case ISN_COMPAREFLOAT:
6897 case ISN_COMPAREFUNC:
6898 case ISN_COMPARELIST:
6899 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006900 case ISN_COMPARESPECIAL:
6901 case ISN_COMPARESTRING:
6902 case ISN_CONCAT:
6903 case ISN_DCALL:
6904 case ISN_DROP:
6905 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006906 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006907 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006908 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006909 case ISN_EXECCONCAT:
6910 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006911 case ISN_FOR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006912 case ISN_INDEX:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006913 case ISN_MEMBER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006914 case ISN_JUMP:
6915 case ISN_LOAD:
Bram Moolenaarc8cd2b32020-05-01 19:29:08 +02006916 case ISN_LOADOUTER:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006917 case ISN_LOADSCRIPT:
6918 case ISN_LOADREG:
6919 case ISN_LOADV:
6920 case ISN_NEGATENR:
6921 case ISN_NEWDICT:
6922 case ISN_NEWLIST:
6923 case ISN_OPNR:
6924 case ISN_OPFLOAT:
6925 case ISN_OPANY:
6926 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006927 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006928 case ISN_PUSHF:
6929 case ISN_PUSHNR:
6930 case ISN_PUSHBOOL:
6931 case ISN_PUSHSPEC:
6932 case ISN_RETURN:
6933 case ISN_STORE:
Bram Moolenaarb68b3462020-05-06 21:06:30 +02006934 case ISN_STOREOUTER:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006935 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006936 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006937 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006938 case ISN_STORESCRIPT:
Bram Moolenaar1cc2a942020-05-10 19:10:31 +02006939 case ISN_STOREDICT:
6940 case ISN_STORELIST:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006941 case ISN_THROW:
6942 case ISN_TRY:
6943 // nothing allocated
6944 break;
6945 }
6946}
6947
6948/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006949 * Free all instructions for "dfunc".
6950 */
6951 static void
6952delete_def_function_contents(dfunc_T *dfunc)
6953{
6954 int idx;
6955
6956 ga_clear(&dfunc->df_def_args_isn);
6957
6958 if (dfunc->df_instr != NULL)
6959 {
6960 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6961 delete_instr(dfunc->df_instr + idx);
6962 VIM_CLEAR(dfunc->df_instr);
6963 }
6964
6965 dfunc->df_deleted = TRUE;
6966}
6967
6968/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006969 * When a user function is deleted, delete any associated def function.
6970 */
6971 void
6972delete_def_function(ufunc_T *ufunc)
6973{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006974 if (ufunc->uf_dfunc_idx >= 0)
6975 {
6976 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6977 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006978
Bram Moolenaar20431c92020-03-20 18:39:46 +01006979 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006980 }
6981}
6982
6983#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006984/*
6985 * Free all functions defined with ":def".
6986 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006987 void
6988free_def_functions(void)
6989{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006990 int idx;
6991
6992 for (idx = 0; idx < def_functions.ga_len; ++idx)
6993 {
6994 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6995
6996 delete_def_function_contents(dfunc);
6997 }
6998
6999 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007000}
7001#endif
7002
7003
7004#endif // FEAT_EVAL