blob: 90f7d2841331e73934dbb3fe66247067d656db7c [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;
100 int lv_const; // when TRUE cannot be assigned to
101 int lv_arg; // when TRUE this is an argument
102} lvar_T;
103
104/*
105 * Context for compiling lines of Vim script.
106 * Stores info about the local variables and condition stack.
107 */
108struct cctx_S {
109 ufunc_T *ctx_ufunc; // current function
110 int ctx_lnum; // line number in current function
111 garray_T ctx_instr; // generated instructions
112
113 garray_T ctx_locals; // currently visible local variables
114 int ctx_max_local; // maximum number of locals at one time
115
116 garray_T ctx_imports; // imported items
117
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100118 int ctx_skip; // when TRUE skip commands, when FALSE skip
119 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100120 scope_T *ctx_scope; // current scope, NULL at toplevel
121
122 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200123 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100124};
125
126static char e_var_notfound[] = N_("E1001: variable not found: %s");
127static char e_syntax_at[] = N_("E1002: Syntax error at %s");
128
129static int compile_expr1(char_u **arg, cctx_T *cctx);
130static int compile_expr2(char_u **arg, cctx_T *cctx);
131static int compile_expr3(char_u **arg, cctx_T *cctx);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100132static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200133static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
134static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100135
136/*
137 * Lookup variable "name" in the local scope and return the index.
138 */
139 static int
140lookup_local(char_u *name, size_t len, cctx_T *cctx)
141{
142 int idx;
143
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100144 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100145 return -1;
146 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
147 {
148 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
149
150 if (STRNCMP(name, lvar->lv_name, len) == 0
151 && STRLEN(lvar->lv_name) == len)
152 return idx;
153 }
154 return -1;
155}
156
157/*
158 * Lookup an argument in the current function.
159 * Returns the argument index or -1 if not found.
160 */
161 static int
162lookup_arg(char_u *name, size_t len, cctx_T *cctx)
163{
164 int idx;
165
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100166 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100167 return -1;
168 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
169 {
170 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
171
172 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
173 return idx;
174 }
175 return -1;
176}
177
178/*
179 * Lookup a vararg argument in the current function.
180 * Returns TRUE if there is a match.
181 */
182 static int
183lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
184{
185 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
186
187 return len > 0 && va_name != NULL
188 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
189}
190
191/*
192 * Lookup a variable in the current script.
193 * Returns OK or FAIL.
194 */
195 static int
196lookup_script(char_u *name, size_t len)
197{
198 int cc;
199 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
200 dictitem_T *di;
201
202 cc = name[len];
203 name[len] = NUL;
204 di = find_var_in_ht(ht, 0, name, TRUE);
205 name[len] = cc;
206 return di == NULL ? FAIL: OK;
207}
208
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100209/*
210 * Check if "p[len]" is already defined, either in script "import_sid" or in
211 * compilation context "cctx".
212 * Return FAIL and give an error if it defined.
213 */
214 int
215check_defined(char_u *p, int len, cctx_T *cctx)
216{
217 if (lookup_script(p, len) == OK
218 || (cctx != NULL
219 && (lookup_local(p, len, cctx) >= 0
220 || find_imported(p, len, cctx) != NULL)))
221 {
222 semsg("E1073: imported name already defined: %s", p);
223 return FAIL;
224 }
225 return OK;
226}
227
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200228/*
229 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
230 * be freed later.
231 */
232 static type_T *
233alloc_type(garray_T *type_gap)
234{
235 type_T *type;
236
237 if (ga_grow(type_gap, 1) == FAIL)
238 return NULL;
239 type = ALLOC_CLEAR_ONE(type_T);
240 if (type != NULL)
241 {
242 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
243 ++type_gap->ga_len;
244 }
245 return type;
246}
247
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100248 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200249get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100250{
251 type_T *type;
252
253 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200254 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100255 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200256 if (member_type->tt_type == VAR_VOID
257 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100258 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100259 if (member_type->tt_type == VAR_BOOL)
260 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100261 if (member_type->tt_type == VAR_NUMBER)
262 return &t_list_number;
263 if (member_type->tt_type == VAR_STRING)
264 return &t_list_string;
265
266 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200267 type = alloc_type(type_gap);
268 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100269 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100270 type->tt_type = VAR_LIST;
271 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200272 type->tt_argcount = 0;
273 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100274 return type;
275}
276
277 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200278get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100279{
280 type_T *type;
281
282 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200283 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100284 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200285 if (member_type->tt_type == VAR_VOID
286 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100287 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100288 if (member_type->tt_type == VAR_BOOL)
289 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100290 if (member_type->tt_type == VAR_NUMBER)
291 return &t_dict_number;
292 if (member_type->tt_type == VAR_STRING)
293 return &t_dict_string;
294
295 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200296 type = alloc_type(type_gap);
297 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100298 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100299 type->tt_type = VAR_DICT;
300 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200301 type->tt_argcount = 0;
302 type->tt_args = NULL;
303 return type;
304}
305
306/*
307 * Get a function type, based on the return type "ret_type".
308 * If "argcount" is -1 or 0 a predefined type can be used.
309 * If "argcount" > 0 always create a new type, so that arguments can be added.
310 */
311 static type_T *
312get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
313{
314 type_T *type;
315
316 // recognize commonly used types
317 if (argcount <= 0)
318 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200319 if (ret_type == &t_unknown)
320 {
321 // (argcount == 0) is not possible
322 return &t_func_unknown;
323 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200324 if (ret_type == &t_void)
325 {
326 if (argcount == 0)
327 return &t_func_0_void;
328 else
329 return &t_func_void;
330 }
331 if (ret_type == &t_any)
332 {
333 if (argcount == 0)
334 return &t_func_0_any;
335 else
336 return &t_func_any;
337 }
338 if (ret_type == &t_number)
339 {
340 if (argcount == 0)
341 return &t_func_0_number;
342 else
343 return &t_func_number;
344 }
345 if (ret_type == &t_string)
346 {
347 if (argcount == 0)
348 return &t_func_0_string;
349 else
350 return &t_func_string;
351 }
352 }
353
354 // Not a common type or has arguments, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200355 type = alloc_type(type_gap);
356 if (type == NULL)
Bram Moolenaard77a8522020-04-03 21:59:57 +0200357 return &t_any;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200358 type->tt_type = VAR_FUNC;
359 type->tt_member = ret_type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200360 type->tt_argcount = argcount;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200361 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100362 return type;
363}
364
Bram Moolenaara8c17702020-04-01 21:17:24 +0200365/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200366 * For a function type, reserve space for "argcount" argument types (including
367 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200368 */
369 static int
370func_type_add_arg_types(
371 type_T *functype,
372 int argcount,
373 int min_argcount,
374 garray_T *type_gap)
375{
376 if (ga_grow(type_gap, 1) == FAIL)
377 return FAIL;
378 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
379 if (functype->tt_args == NULL)
380 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200381 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
382 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200383 ++type_gap->ga_len;
384
385 functype->tt_argcount = argcount;
386 functype->tt_min_argcount = min_argcount;
387 return OK;
388}
389
390/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200391 * Return the type_T for a typval. Only for primitive types.
392 */
393 static type_T *
394typval2type(typval_T *tv)
395{
396 if (tv->v_type == VAR_NUMBER)
397 return &t_number;
398 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200399 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200400 if (tv->v_type == VAR_STRING)
401 return &t_string;
402 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
403 return &t_list_string;
404 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
405 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200406 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200407}
408
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100409/////////////////////////////////////////////////////////////////////
410// Following generate_ functions expect the caller to call ga_grow().
411
Bram Moolenaar080457c2020-03-03 21:53:32 +0100412#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
413#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
414
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100415/*
416 * Generate an instruction without arguments.
417 * Returns a pointer to the new instruction, NULL if failed.
418 */
419 static isn_T *
420generate_instr(cctx_T *cctx, isntype_T isn_type)
421{
422 garray_T *instr = &cctx->ctx_instr;
423 isn_T *isn;
424
Bram Moolenaar080457c2020-03-03 21:53:32 +0100425 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100426 if (ga_grow(instr, 1) == FAIL)
427 return NULL;
428 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
429 isn->isn_type = isn_type;
430 isn->isn_lnum = cctx->ctx_lnum + 1;
431 ++instr->ga_len;
432
433 return isn;
434}
435
436/*
437 * Generate an instruction without arguments.
438 * "drop" will be removed from the stack.
439 * Returns a pointer to the new instruction, NULL if failed.
440 */
441 static isn_T *
442generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
443{
444 garray_T *stack = &cctx->ctx_type_stack;
445
Bram Moolenaar080457c2020-03-03 21:53:32 +0100446 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100447 stack->ga_len -= drop;
448 return generate_instr(cctx, isn_type);
449}
450
451/*
452 * Generate instruction "isn_type" and put "type" on the type stack.
453 */
454 static isn_T *
455generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
456{
457 isn_T *isn;
458 garray_T *stack = &cctx->ctx_type_stack;
459
460 if ((isn = generate_instr(cctx, isn_type)) == NULL)
461 return NULL;
462
463 if (ga_grow(stack, 1) == FAIL)
464 return NULL;
465 ((type_T **)stack->ga_data)[stack->ga_len] = type;
466 ++stack->ga_len;
467
468 return isn;
469}
470
471/*
472 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
473 */
474 static int
475may_generate_2STRING(int offset, cctx_T *cctx)
476{
477 isn_T *isn;
478 garray_T *stack = &cctx->ctx_type_stack;
479 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
480
481 if ((*type)->tt_type == VAR_STRING)
482 return OK;
483 *type = &t_string;
484
485 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
486 return FAIL;
487 isn->isn_arg.number = offset;
488
489 return OK;
490}
491
492 static int
493check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
494{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200495 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100496 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200497 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100498 {
499 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100500 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100501 else
502 semsg(_("E1036: %c requires number or float arguments"), *op);
503 return FAIL;
504 }
505 return OK;
506}
507
508/*
509 * Generate an instruction with two arguments. The instruction depends on the
510 * type of the arguments.
511 */
512 static int
513generate_two_op(cctx_T *cctx, char_u *op)
514{
515 garray_T *stack = &cctx->ctx_type_stack;
516 type_T *type1;
517 type_T *type2;
518 vartype_T vartype;
519 isn_T *isn;
520
Bram Moolenaar080457c2020-03-03 21:53:32 +0100521 RETURN_OK_IF_SKIP(cctx);
522
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100523 // Get the known type of the two items on the stack. If they are matching
524 // use a type-specific instruction. Otherwise fall back to runtime type
525 // checking.
526 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
527 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200528 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100529 if (type1->tt_type == type2->tt_type
530 && (type1->tt_type == VAR_NUMBER
531 || type1->tt_type == VAR_LIST
532#ifdef FEAT_FLOAT
533 || type1->tt_type == VAR_FLOAT
534#endif
535 || type1->tt_type == VAR_BLOB))
536 vartype = type1->tt_type;
537
538 switch (*op)
539 {
540 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200541 && type1->tt_type != VAR_ANY
542 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100543 && check_number_or_float(
544 type1->tt_type, type2->tt_type, op) == FAIL)
545 return FAIL;
546 isn = generate_instr_drop(cctx,
547 vartype == VAR_NUMBER ? ISN_OPNR
548 : vartype == VAR_LIST ? ISN_ADDLIST
549 : vartype == VAR_BLOB ? ISN_ADDBLOB
550#ifdef FEAT_FLOAT
551 : vartype == VAR_FLOAT ? ISN_OPFLOAT
552#endif
553 : ISN_OPANY, 1);
554 if (isn != NULL)
555 isn->isn_arg.op.op_type = EXPR_ADD;
556 break;
557
558 case '-':
559 case '*':
560 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
561 op) == FAIL)
562 return FAIL;
563 if (vartype == VAR_NUMBER)
564 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
565#ifdef FEAT_FLOAT
566 else if (vartype == VAR_FLOAT)
567 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
568#endif
569 else
570 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
571 if (isn != NULL)
572 isn->isn_arg.op.op_type = *op == '*'
573 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
574 break;
575
Bram Moolenaar4c683752020-04-05 21:38:23 +0200576 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100577 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200578 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100579 && type2->tt_type != VAR_NUMBER))
580 {
581 emsg(_("E1035: % requires number arguments"));
582 return FAIL;
583 }
584 isn = generate_instr_drop(cctx,
585 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
586 if (isn != NULL)
587 isn->isn_arg.op.op_type = EXPR_REM;
588 break;
589 }
590
591 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200592 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100593 {
594 type_T *type = &t_any;
595
596#ifdef FEAT_FLOAT
597 // float+number and number+float results in float
598 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
599 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
600 type = &t_float;
601#endif
602 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
603 }
604
605 return OK;
606}
607
608/*
609 * Generate an ISN_COMPARE* instruction with a boolean result.
610 */
611 static int
612generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
613{
614 isntype_T isntype = ISN_DROP;
615 isn_T *isn;
616 garray_T *stack = &cctx->ctx_type_stack;
617 vartype_T type1;
618 vartype_T type2;
619
Bram Moolenaar080457c2020-03-03 21:53:32 +0100620 RETURN_OK_IF_SKIP(cctx);
621
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100622 // Get the known type of the two items on the stack. If they are matching
623 // use a type-specific instruction. Otherwise fall back to runtime type
624 // checking.
625 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
626 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200627 if (type1 == VAR_UNKNOWN)
628 type1 = VAR_ANY;
629 if (type2 == VAR_UNKNOWN)
630 type2 = VAR_ANY;
631
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100632 if (type1 == type2)
633 {
634 switch (type1)
635 {
636 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
637 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
638 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
639 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
640 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
641 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
642 case VAR_LIST: isntype = ISN_COMPARELIST; break;
643 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
644 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100645 default: isntype = ISN_COMPAREANY; break;
646 }
647 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200648 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100649 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
650 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
651 isntype = ISN_COMPAREANY;
652
653 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
654 && (isntype == ISN_COMPAREBOOL
655 || isntype == ISN_COMPARESPECIAL
656 || isntype == ISN_COMPARENR
657 || isntype == ISN_COMPAREFLOAT))
658 {
659 semsg(_("E1037: Cannot use \"%s\" with %s"),
660 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
661 return FAIL;
662 }
663 if (isntype == ISN_DROP
664 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
665 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
666 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
667 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
668 && exptype != EXPR_IS && exptype != EXPR_ISNOT
669 && (type1 == VAR_BLOB || type2 == VAR_BLOB
670 || type1 == VAR_LIST || type2 == VAR_LIST))))
671 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100672 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100673 vartype_name(type1), vartype_name(type2));
674 return FAIL;
675 }
676
677 if ((isn = generate_instr(cctx, isntype)) == NULL)
678 return FAIL;
679 isn->isn_arg.op.op_type = exptype;
680 isn->isn_arg.op.op_ic = ic;
681
682 // takes two arguments, puts one bool back
683 if (stack->ga_len >= 2)
684 {
685 --stack->ga_len;
686 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
687 }
688
689 return OK;
690}
691
692/*
693 * Generate an ISN_2BOOL instruction.
694 */
695 static int
696generate_2BOOL(cctx_T *cctx, int invert)
697{
698 isn_T *isn;
699 garray_T *stack = &cctx->ctx_type_stack;
700
Bram Moolenaar080457c2020-03-03 21:53:32 +0100701 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100702 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
703 return FAIL;
704 isn->isn_arg.number = invert;
705
706 // type becomes bool
707 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
708
709 return OK;
710}
711
712 static int
713generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
714{
715 isn_T *isn;
716 garray_T *stack = &cctx->ctx_type_stack;
717
Bram Moolenaar080457c2020-03-03 21:53:32 +0100718 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100719 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
720 return FAIL;
721 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
722 isn->isn_arg.type.ct_off = offset;
723
724 // type becomes vartype
725 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
726
727 return OK;
728}
729
730/*
731 * Generate an ISN_PUSHNR instruction.
732 */
733 static int
734generate_PUSHNR(cctx_T *cctx, varnumber_T number)
735{
736 isn_T *isn;
737
Bram Moolenaar080457c2020-03-03 21:53:32 +0100738 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100739 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
740 return FAIL;
741 isn->isn_arg.number = number;
742
743 return OK;
744}
745
746/*
747 * Generate an ISN_PUSHBOOL instruction.
748 */
749 static int
750generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
751{
752 isn_T *isn;
753
Bram Moolenaar080457c2020-03-03 21:53:32 +0100754 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100755 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
756 return FAIL;
757 isn->isn_arg.number = number;
758
759 return OK;
760}
761
762/*
763 * Generate an ISN_PUSHSPEC instruction.
764 */
765 static int
766generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
767{
768 isn_T *isn;
769
Bram Moolenaar080457c2020-03-03 21:53:32 +0100770 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100771 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
772 return FAIL;
773 isn->isn_arg.number = number;
774
775 return OK;
776}
777
778#ifdef FEAT_FLOAT
779/*
780 * Generate an ISN_PUSHF instruction.
781 */
782 static int
783generate_PUSHF(cctx_T *cctx, float_T fnumber)
784{
785 isn_T *isn;
786
Bram Moolenaar080457c2020-03-03 21:53:32 +0100787 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100788 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
789 return FAIL;
790 isn->isn_arg.fnumber = fnumber;
791
792 return OK;
793}
794#endif
795
796/*
797 * Generate an ISN_PUSHS instruction.
798 * Consumes "str".
799 */
800 static int
801generate_PUSHS(cctx_T *cctx, char_u *str)
802{
803 isn_T *isn;
804
Bram Moolenaar080457c2020-03-03 21:53:32 +0100805 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100806 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
807 return FAIL;
808 isn->isn_arg.string = str;
809
810 return OK;
811}
812
813/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100814 * Generate an ISN_PUSHCHANNEL instruction.
815 * Consumes "channel".
816 */
817 static int
818generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
819{
820 isn_T *isn;
821
Bram Moolenaar080457c2020-03-03 21:53:32 +0100822 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100823 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
824 return FAIL;
825 isn->isn_arg.channel = channel;
826
827 return OK;
828}
829
830/*
831 * Generate an ISN_PUSHJOB instruction.
832 * Consumes "job".
833 */
834 static int
835generate_PUSHJOB(cctx_T *cctx, job_T *job)
836{
837 isn_T *isn;
838
Bram Moolenaar080457c2020-03-03 21:53:32 +0100839 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100840 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100841 return FAIL;
842 isn->isn_arg.job = job;
843
844 return OK;
845}
846
847/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100848 * Generate an ISN_PUSHBLOB instruction.
849 * Consumes "blob".
850 */
851 static int
852generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
853{
854 isn_T *isn;
855
Bram Moolenaar080457c2020-03-03 21:53:32 +0100856 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100857 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
858 return FAIL;
859 isn->isn_arg.blob = blob;
860
861 return OK;
862}
863
864/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100865 * Generate an ISN_PUSHFUNC instruction with name "name".
866 * Consumes "name".
867 */
868 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200869generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100870{
871 isn_T *isn;
872
Bram Moolenaar080457c2020-03-03 21:53:32 +0100873 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200874 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100875 return FAIL;
876 isn->isn_arg.string = name;
877
878 return OK;
879}
880
881/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100882 * Generate an ISN_STORE instruction.
883 */
884 static int
885generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
886{
887 isn_T *isn;
888
Bram Moolenaar080457c2020-03-03 21:53:32 +0100889 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100890 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
891 return FAIL;
892 if (name != NULL)
893 isn->isn_arg.string = vim_strsave(name);
894 else
895 isn->isn_arg.number = idx;
896
897 return OK;
898}
899
900/*
901 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
902 */
903 static int
904generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
905{
906 isn_T *isn;
907
Bram Moolenaar080457c2020-03-03 21:53:32 +0100908 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100909 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
910 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100911 isn->isn_arg.storenr.stnr_idx = idx;
912 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100913
914 return OK;
915}
916
917/*
918 * Generate an ISN_STOREOPT instruction
919 */
920 static int
921generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
922{
923 isn_T *isn;
924
Bram Moolenaar080457c2020-03-03 21:53:32 +0100925 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100926 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
927 return FAIL;
928 isn->isn_arg.storeopt.so_name = vim_strsave(name);
929 isn->isn_arg.storeopt.so_flags = opt_flags;
930
931 return OK;
932}
933
934/*
935 * Generate an ISN_LOAD or similar instruction.
936 */
937 static int
938generate_LOAD(
939 cctx_T *cctx,
940 isntype_T isn_type,
941 int idx,
942 char_u *name,
943 type_T *type)
944{
945 isn_T *isn;
946
Bram Moolenaar080457c2020-03-03 21:53:32 +0100947 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100948 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
949 return FAIL;
950 if (name != NULL)
951 isn->isn_arg.string = vim_strsave(name);
952 else
953 isn->isn_arg.number = idx;
954
955 return OK;
956}
957
958/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200959 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100960 */
961 static int
962generate_LOADV(
963 cctx_T *cctx,
964 char_u *name,
965 int error)
966{
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200967 int di_flags;
968 int vidx = find_vim_var(name, &di_flags);
969 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100970
Bram Moolenaar080457c2020-03-03 21:53:32 +0100971 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100972 if (vidx < 0)
973 {
974 if (error)
975 semsg(_(e_var_notfound), name);
976 return FAIL;
977 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200978 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100979
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200980 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100981}
982
983/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100984 * Generate an ISN_LOADS instruction.
985 */
986 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100987generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100988 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100989 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100990 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100991 int sid,
992 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100993{
994 isn_T *isn;
995
Bram Moolenaar080457c2020-03-03 21:53:32 +0100996 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100997 if (isn_type == ISN_LOADS)
998 isn = generate_instr_type(cctx, isn_type, type);
999 else
1000 isn = generate_instr_drop(cctx, isn_type, 1);
1001 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001002 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001003 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1004 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001005
1006 return OK;
1007}
1008
1009/*
1010 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1011 */
1012 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001013generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001014 cctx_T *cctx,
1015 isntype_T isn_type,
1016 int sid,
1017 int idx,
1018 type_T *type)
1019{
1020 isn_T *isn;
1021
Bram Moolenaar080457c2020-03-03 21:53:32 +01001022 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001023 if (isn_type == ISN_LOADSCRIPT)
1024 isn = generate_instr_type(cctx, isn_type, type);
1025 else
1026 isn = generate_instr_drop(cctx, isn_type, 1);
1027 if (isn == NULL)
1028 return FAIL;
1029 isn->isn_arg.script.script_sid = sid;
1030 isn->isn_arg.script.script_idx = idx;
1031 return OK;
1032}
1033
1034/*
1035 * Generate an ISN_NEWLIST instruction.
1036 */
1037 static int
1038generate_NEWLIST(cctx_T *cctx, int count)
1039{
1040 isn_T *isn;
1041 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001042 type_T *type;
1043 type_T *member;
1044
Bram Moolenaar080457c2020-03-03 21:53:32 +01001045 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001046 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1047 return FAIL;
1048 isn->isn_arg.number = count;
1049
1050 // drop the value types
1051 stack->ga_len -= count;
1052
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001053 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001054 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001055 if (count > 0)
1056 member = ((type_T **)stack->ga_data)[stack->ga_len];
1057 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001058 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001059 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001060
1061 // add the list type to the type stack
1062 if (ga_grow(stack, 1) == FAIL)
1063 return FAIL;
1064 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1065 ++stack->ga_len;
1066
1067 return OK;
1068}
1069
1070/*
1071 * Generate an ISN_NEWDICT instruction.
1072 */
1073 static int
1074generate_NEWDICT(cctx_T *cctx, int count)
1075{
1076 isn_T *isn;
1077 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001078 type_T *type;
1079 type_T *member;
1080
Bram Moolenaar080457c2020-03-03 21:53:32 +01001081 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001082 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1083 return FAIL;
1084 isn->isn_arg.number = count;
1085
1086 // drop the key and value types
1087 stack->ga_len -= 2 * count;
1088
Bram Moolenaar436472f2020-02-20 22:54:43 +01001089 // Use the first value type for the list member type. Use "void" for an
1090 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001091 if (count > 0)
1092 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1093 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001094 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001095 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001096
1097 // add the dict type to the type stack
1098 if (ga_grow(stack, 1) == FAIL)
1099 return FAIL;
1100 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1101 ++stack->ga_len;
1102
1103 return OK;
1104}
1105
1106/*
1107 * Generate an ISN_FUNCREF instruction.
1108 */
1109 static int
1110generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1111{
1112 isn_T *isn;
1113 garray_T *stack = &cctx->ctx_type_stack;
1114
Bram Moolenaar080457c2020-03-03 21:53:32 +01001115 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001116 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1117 return FAIL;
1118 isn->isn_arg.number = dfunc_idx;
1119
1120 if (ga_grow(stack, 1) == FAIL)
1121 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001122 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001123 // TODO: argument and return types
1124 ++stack->ga_len;
1125
1126 return OK;
1127}
1128
1129/*
1130 * Generate an ISN_JUMP instruction.
1131 */
1132 static int
1133generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1134{
1135 isn_T *isn;
1136 garray_T *stack = &cctx->ctx_type_stack;
1137
Bram Moolenaar080457c2020-03-03 21:53:32 +01001138 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001139 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1140 return FAIL;
1141 isn->isn_arg.jump.jump_when = when;
1142 isn->isn_arg.jump.jump_where = where;
1143
1144 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1145 --stack->ga_len;
1146
1147 return OK;
1148}
1149
1150 static int
1151generate_FOR(cctx_T *cctx, int loop_idx)
1152{
1153 isn_T *isn;
1154 garray_T *stack = &cctx->ctx_type_stack;
1155
Bram Moolenaar080457c2020-03-03 21:53:32 +01001156 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001157 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1158 return FAIL;
1159 isn->isn_arg.forloop.for_idx = loop_idx;
1160
1161 if (ga_grow(stack, 1) == FAIL)
1162 return FAIL;
1163 // type doesn't matter, will be stored next
1164 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1165 ++stack->ga_len;
1166
1167 return OK;
1168}
1169
1170/*
1171 * Generate an ISN_BCALL instruction.
1172 * Return FAIL if the number of arguments is wrong.
1173 */
1174 static int
1175generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1176{
1177 isn_T *isn;
1178 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001179 type_T *argtypes[MAX_FUNC_ARGS];
1180 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001181
Bram Moolenaar080457c2020-03-03 21:53:32 +01001182 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001183 if (check_internal_func(func_idx, argcount) == FAIL)
1184 return FAIL;
1185
1186 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1187 return FAIL;
1188 isn->isn_arg.bfunc.cbf_idx = func_idx;
1189 isn->isn_arg.bfunc.cbf_argcount = argcount;
1190
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001191 for (i = 0; i < argcount; ++i)
1192 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1193
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001194 stack->ga_len -= argcount; // drop the arguments
1195 if (ga_grow(stack, 1) == FAIL)
1196 return FAIL;
1197 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001198 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001199 ++stack->ga_len; // add return value
1200
1201 return OK;
1202}
1203
1204/*
1205 * Generate an ISN_DCALL or ISN_UCALL instruction.
1206 * Return FAIL if the number of arguments is wrong.
1207 */
1208 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001209generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001210{
1211 isn_T *isn;
1212 garray_T *stack = &cctx->ctx_type_stack;
1213 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001214 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001215
Bram Moolenaar080457c2020-03-03 21:53:32 +01001216 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001217 if (argcount > regular_args && !has_varargs(ufunc))
1218 {
1219 semsg(_(e_toomanyarg), ufunc->uf_name);
1220 return FAIL;
1221 }
1222 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1223 {
1224 semsg(_(e_toofewarg), ufunc->uf_name);
1225 return FAIL;
1226 }
1227
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001228 if (ufunc->uf_dfunc_idx >= 0)
1229 {
1230 int i;
1231
1232 for (i = 0; i < argcount; ++i)
1233 {
1234 type_T *expected;
1235 type_T *actual;
1236
1237 if (i < regular_args)
1238 {
1239 if (ufunc->uf_arg_types == NULL)
1240 continue;
1241 expected = ufunc->uf_arg_types[i];
1242 }
1243 else
1244 expected = ufunc->uf_va_type->tt_member;
1245 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1246 if (check_type(expected, actual, FALSE) == FAIL)
1247 {
1248 arg_type_mismatch(expected, actual, i + 1);
1249 return FAIL;
1250 }
1251 }
1252 }
1253
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001254 // Turn varargs into a list.
1255 if (ufunc->uf_va_name != NULL)
1256 {
1257 int count = argcount - regular_args;
1258
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001259 // If count is negative an empty list will be added after evaluating
1260 // default values for missing optional arguments.
1261 if (count >= 0)
1262 {
1263 generate_NEWLIST(cctx, count);
1264 argcount = regular_args + 1;
1265 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001266 }
1267
1268 if ((isn = generate_instr(cctx,
1269 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1270 return FAIL;
1271 if (ufunc->uf_dfunc_idx >= 0)
1272 {
1273 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1274 isn->isn_arg.dfunc.cdf_argcount = argcount;
1275 }
1276 else
1277 {
1278 // A user function may be deleted and redefined later, can't use the
1279 // ufunc pointer, need to look it up again at runtime.
1280 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1281 isn->isn_arg.ufunc.cuf_argcount = argcount;
1282 }
1283
1284 stack->ga_len -= argcount; // drop the arguments
1285 if (ga_grow(stack, 1) == FAIL)
1286 return FAIL;
1287 // add return value
1288 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1289 ++stack->ga_len;
1290
1291 return OK;
1292}
1293
1294/*
1295 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1296 */
1297 static int
1298generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1299{
1300 isn_T *isn;
1301 garray_T *stack = &cctx->ctx_type_stack;
1302
Bram Moolenaar080457c2020-03-03 21:53:32 +01001303 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001304 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1305 return FAIL;
1306 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1307 isn->isn_arg.ufunc.cuf_argcount = argcount;
1308
1309 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001310 if (ga_grow(stack, 1) == FAIL)
1311 return FAIL;
1312 // add return value
1313 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1314 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001315
1316 return OK;
1317}
1318
1319/*
1320 * Generate an ISN_PCALL instruction.
1321 */
1322 static int
1323generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1324{
1325 isn_T *isn;
1326 garray_T *stack = &cctx->ctx_type_stack;
1327
Bram Moolenaar080457c2020-03-03 21:53:32 +01001328 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001329 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1330 return FAIL;
1331 isn->isn_arg.pfunc.cpf_top = at_top;
1332 isn->isn_arg.pfunc.cpf_argcount = argcount;
1333
1334 stack->ga_len -= argcount; // drop the arguments
1335
1336 // drop the funcref/partial, get back the return value
1337 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1338
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001339 // If partial is above the arguments it must be cleared and replaced with
1340 // the return value.
1341 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1342 return FAIL;
1343
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001344 return OK;
1345}
1346
1347/*
1348 * Generate an ISN_MEMBER instruction.
1349 */
1350 static int
1351generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1352{
1353 isn_T *isn;
1354 garray_T *stack = &cctx->ctx_type_stack;
1355 type_T *type;
1356
Bram Moolenaar080457c2020-03-03 21:53:32 +01001357 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001358 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1359 return FAIL;
1360 isn->isn_arg.string = vim_strnsave(name, (int)len);
1361
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001362 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001363 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001364 if (type->tt_type != VAR_DICT && type != &t_any)
1365 {
1366 emsg(_(e_dictreq));
1367 return FAIL;
1368 }
1369 // change dict type to dict member type
1370 if (type->tt_type == VAR_DICT)
1371 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001372
1373 return OK;
1374}
1375
1376/*
1377 * Generate an ISN_ECHO instruction.
1378 */
1379 static int
1380generate_ECHO(cctx_T *cctx, int with_white, int count)
1381{
1382 isn_T *isn;
1383
Bram Moolenaar080457c2020-03-03 21:53:32 +01001384 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001385 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1386 return FAIL;
1387 isn->isn_arg.echo.echo_with_white = with_white;
1388 isn->isn_arg.echo.echo_count = count;
1389
1390 return OK;
1391}
1392
Bram Moolenaarad39c092020-02-26 18:23:43 +01001393/*
1394 * Generate an ISN_EXECUTE instruction.
1395 */
1396 static int
1397generate_EXECUTE(cctx_T *cctx, int count)
1398{
1399 isn_T *isn;
1400
1401 if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL)
1402 return FAIL;
1403 isn->isn_arg.number = count;
1404
1405 return OK;
1406}
1407
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001408 static int
1409generate_EXEC(cctx_T *cctx, char_u *line)
1410{
1411 isn_T *isn;
1412
Bram Moolenaar080457c2020-03-03 21:53:32 +01001413 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001414 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1415 return FAIL;
1416 isn->isn_arg.string = vim_strsave(line);
1417 return OK;
1418}
1419
1420static char e_white_both[] =
1421 N_("E1004: white space required before and after '%s'");
Bram Moolenaard77a8522020-04-03 21:59:57 +02001422static char e_white_after[] = N_("E1069: white space required after '%s'");
1423static char e_no_white_before[] = N_("E1068: No white space allowed before '%s'");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001424
1425/*
1426 * Reserve space for a local variable.
1427 * Return the index or -1 if it failed.
1428 */
1429 static int
1430reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1431{
1432 int idx;
1433 lvar_T *lvar;
1434
1435 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1436 {
1437 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1438 return -1;
1439 }
1440
1441 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1442 return -1;
1443 idx = cctx->ctx_locals.ga_len;
1444 if (cctx->ctx_max_local < idx + 1)
1445 cctx->ctx_max_local = idx + 1;
1446 ++cctx->ctx_locals.ga_len;
1447
1448 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1449 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1450 lvar->lv_const = isConst;
1451 lvar->lv_type = type;
1452
1453 return idx;
1454}
1455
1456/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001457 * Remove local variables above "new_top".
1458 */
1459 static void
1460unwind_locals(cctx_T *cctx, int new_top)
1461{
1462 if (cctx->ctx_locals.ga_len > new_top)
1463 {
1464 int idx;
1465 lvar_T *lvar;
1466
1467 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1468 {
1469 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1470 vim_free(lvar->lv_name);
1471 }
1472 }
1473 cctx->ctx_locals.ga_len = new_top;
1474}
1475
1476/*
1477 * Free all local variables.
1478 */
1479 static void
1480free_local(cctx_T *cctx)
1481{
1482 unwind_locals(cctx, 0);
1483 ga_clear(&cctx->ctx_locals);
1484}
1485
1486/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001487 * Skip over a type definition and return a pointer to just after it.
1488 */
1489 char_u *
1490skip_type(char_u *start)
1491{
1492 char_u *p = start;
1493
1494 while (ASCII_ISALNUM(*p) || *p == '_')
1495 ++p;
1496
1497 // Skip over "<type>"; this is permissive about white space.
1498 if (*skipwhite(p) == '<')
1499 {
1500 p = skipwhite(p);
1501 p = skip_type(skipwhite(p + 1));
1502 p = skipwhite(p);
1503 if (*p == '>')
1504 ++p;
1505 }
1506 return p;
1507}
1508
1509/*
1510 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001511 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001512 * Returns NULL in case of failure.
1513 */
1514 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001515parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001516{
1517 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001518 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001519
1520 if (**arg != '<')
1521 {
1522 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001523 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001524 else
1525 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001526 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001527 }
1528 *arg = skipwhite(*arg + 1);
1529
Bram Moolenaard77a8522020-04-03 21:59:57 +02001530 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001531
1532 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001533 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001534 {
1535 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001536 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001537 }
1538 ++*arg;
1539
1540 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001541 return get_list_type(member_type, type_gap);
1542 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001543}
1544
1545/*
1546 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001547 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001548 */
1549 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001550parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001551{
1552 char_u *p = *arg;
1553 size_t len;
1554
1555 // skip over the first word
1556 while (ASCII_ISALNUM(*p) || *p == '_')
1557 ++p;
1558 len = p - *arg;
1559
1560 switch (**arg)
1561 {
1562 case 'a':
1563 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1564 {
1565 *arg += len;
1566 return &t_any;
1567 }
1568 break;
1569 case 'b':
1570 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1571 {
1572 *arg += len;
1573 return &t_bool;
1574 }
1575 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1576 {
1577 *arg += len;
1578 return &t_blob;
1579 }
1580 break;
1581 case 'c':
1582 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1583 {
1584 *arg += len;
1585 return &t_channel;
1586 }
1587 break;
1588 case 'd':
1589 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1590 {
1591 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001592 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001593 }
1594 break;
1595 case 'f':
1596 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1597 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001598#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001599 *arg += len;
1600 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001601#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001602 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001603 return &t_any;
1604#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001605 }
1606 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1607 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001608 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001609 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001610 int argcount = -1;
1611 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001612 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001613 type_T *arg_type[MAX_FUNC_ARGS + 1];
1614
1615 // func({type}, ...): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001616 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001617 if (**arg == '(')
1618 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001619 // "func" may or may not return a value, "func()" does
1620 // not return a value.
1621 ret_type = &t_void;
1622
Bram Moolenaard77a8522020-04-03 21:59:57 +02001623 p = ++*arg;
1624 argcount = 0;
1625 while (*p != NUL && *p != ')')
1626 {
1627 if (STRNCMP(p, "...", 3) == 0)
1628 {
1629 flags |= TTFLAG_VARARGS;
1630 break;
1631 }
1632 arg_type[argcount++] = parse_type(&p, type_gap);
1633
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001634 if (*p == '?')
1635 {
1636 if (first_optional == -1)
1637 first_optional = argcount;
1638 ++p;
1639 }
1640 else if (first_optional != -1)
1641 {
1642 emsg(_("E1007: mandatory argument after optional argument"));
1643 return &t_any;
1644 }
1645
Bram Moolenaard77a8522020-04-03 21:59:57 +02001646 if (*p != ',' && *skipwhite(p) == ',')
1647 {
1648 semsg(_(e_no_white_before), ",");
1649 return &t_any;
1650 }
1651 if (*p == ',')
1652 {
1653 ++p;
1654 if (!VIM_ISWHITE(*p))
1655 semsg(_(e_white_after), ",");
1656 }
1657 p = skipwhite(p);
1658 if (argcount == MAX_FUNC_ARGS)
1659 {
1660 emsg(_("E740: Too many argument types"));
1661 return &t_any;
1662 }
1663 }
1664
1665 p = skipwhite(p);
1666 if (*p != ')')
1667 {
1668 emsg(_(e_missing_close));
1669 return &t_any;
1670 }
1671 *arg = p + 1;
1672 }
1673 if (**arg == ':')
1674 {
1675 // parse return type
1676 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001677 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001678 semsg(_(e_white_after), ":");
1679 *arg = skipwhite(*arg);
1680 ret_type = parse_type(arg, type_gap);
1681 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001682 type = get_func_type(ret_type,
1683 flags == 0 && first_optional == -1 ? argcount : 99,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001684 type_gap);
1685 if (flags != 0)
1686 type->tt_flags = flags;
1687 if (argcount > 0)
1688 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001689 if (func_type_add_arg_types(type, argcount,
1690 first_optional == -1 ? argcount : first_optional,
1691 type_gap) == FAIL)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001692 return &t_any;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001693 mch_memmove(type->tt_args, arg_type,
1694 sizeof(type_T *) * argcount);
1695 }
1696 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001697 }
1698 break;
1699 case 'j':
1700 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1701 {
1702 *arg += len;
1703 return &t_job;
1704 }
1705 break;
1706 case 'l':
1707 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1708 {
1709 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001710 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001711 }
1712 break;
1713 case 'n':
1714 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1715 {
1716 *arg += len;
1717 return &t_number;
1718 }
1719 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001720 case 's':
1721 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1722 {
1723 *arg += len;
1724 return &t_string;
1725 }
1726 break;
1727 case 'v':
1728 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1729 {
1730 *arg += len;
1731 return &t_void;
1732 }
1733 break;
1734 }
1735
1736 semsg(_("E1010: Type not recognized: %s"), *arg);
1737 return &t_any;
1738}
1739
1740/*
1741 * Check if "type1" and "type2" are exactly the same.
1742 */
1743 static int
1744equal_type(type_T *type1, type_T *type2)
1745{
1746 if (type1->tt_type != type2->tt_type)
1747 return FALSE;
1748 switch (type1->tt_type)
1749 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001750 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001751 case VAR_ANY:
1752 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001753 case VAR_SPECIAL:
1754 case VAR_BOOL:
1755 case VAR_NUMBER:
1756 case VAR_FLOAT:
1757 case VAR_STRING:
1758 case VAR_BLOB:
1759 case VAR_JOB:
1760 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001761 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001762 case VAR_LIST:
1763 case VAR_DICT:
1764 return equal_type(type1->tt_member, type2->tt_member);
1765 case VAR_FUNC:
1766 case VAR_PARTIAL:
1767 // TODO; check argument types.
1768 return equal_type(type1->tt_member, type2->tt_member)
1769 && type1->tt_argcount == type2->tt_argcount;
1770 }
1771 return TRUE;
1772}
1773
1774/*
1775 * Find the common type of "type1" and "type2" and put it in "dest".
1776 * "type2" and "dest" may be the same.
1777 */
1778 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001779common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001780{
1781 if (equal_type(type1, type2))
1782 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001783 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001784 return;
1785 }
1786
1787 if (type1->tt_type == type2->tt_type)
1788 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001789 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1790 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001791 type_T *common;
1792
Bram Moolenaard77a8522020-04-03 21:59:57 +02001793 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001794 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001795 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001796 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001797 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001798 return;
1799 }
1800 // TODO: VAR_FUNC and VAR_PARTIAL
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001801 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001802 }
1803
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001804 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001805}
1806
1807 char *
1808vartype_name(vartype_T type)
1809{
1810 switch (type)
1811 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001812 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001813 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001814 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001815 case VAR_SPECIAL: return "special";
1816 case VAR_BOOL: return "bool";
1817 case VAR_NUMBER: return "number";
1818 case VAR_FLOAT: return "float";
1819 case VAR_STRING: return "string";
1820 case VAR_BLOB: return "blob";
1821 case VAR_JOB: return "job";
1822 case VAR_CHANNEL: return "channel";
1823 case VAR_LIST: return "list";
1824 case VAR_DICT: return "dict";
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001825 case VAR_FUNC: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001826 case VAR_PARTIAL: return "partial";
1827 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001828 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001829}
1830
1831/*
1832 * Return the name of a type.
1833 * The result may be in allocated memory, in which case "tofree" is set.
1834 */
1835 char *
1836type_name(type_T *type, char **tofree)
1837{
1838 char *name = vartype_name(type->tt_type);
1839
1840 *tofree = NULL;
1841 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1842 {
1843 char *member_free;
1844 char *member_name = type_name(type->tt_member, &member_free);
1845 size_t len;
1846
1847 len = STRLEN(name) + STRLEN(member_name) + 3;
1848 *tofree = alloc(len);
1849 if (*tofree != NULL)
1850 {
1851 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1852 vim_free(member_free);
1853 return *tofree;
1854 }
1855 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001856 if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
1857 {
1858 garray_T ga;
1859 int i;
1860
1861 ga_init2(&ga, 1, 100);
1862 if (ga_grow(&ga, 20) == FAIL)
1863 return "[unknown]";
1864 *tofree = ga.ga_data;
1865 STRCPY(ga.ga_data, "func(");
1866 ga.ga_len += 5;
1867
1868 for (i = 0; i < type->tt_argcount; ++i)
1869 {
1870 char *arg_free;
1871 char *arg_type = type_name(type->tt_args[i], &arg_free);
1872 int len;
1873
1874 if (i > 0)
1875 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001876 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001877 ga.ga_len += 2;
1878 }
1879 len = (int)STRLEN(arg_type);
1880 if (ga_grow(&ga, len + 6) == FAIL)
1881 {
1882 vim_free(arg_free);
1883 return "[unknown]";
1884 }
1885 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001886 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001887 ga.ga_len += len;
1888 vim_free(arg_free);
1889 }
1890
1891 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001892 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001893 else
1894 {
1895 char *ret_free;
1896 char *ret_name = type_name(type->tt_member, &ret_free);
1897 int len;
1898
1899 len = (int)STRLEN(ret_name) + 4;
1900 if (ga_grow(&ga, len) == FAIL)
1901 {
1902 vim_free(ret_free);
1903 return "[unknown]";
1904 }
1905 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001906 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1907 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001908 vim_free(ret_free);
1909 }
1910 return ga.ga_data;
1911 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001912
1913 return name;
1914}
1915
1916/*
1917 * Find "name" in script-local items of script "sid".
1918 * Returns the index in "sn_var_vals" if found.
1919 * If found but not in "sn_var_vals" returns -1.
1920 * If not found returns -2.
1921 */
1922 int
1923get_script_item_idx(int sid, char_u *name, int check_writable)
1924{
1925 hashtab_T *ht;
1926 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001927 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001928 int idx;
1929
1930 // First look the name up in the hashtable.
1931 if (sid <= 0 || sid > script_items.ga_len)
1932 return -1;
1933 ht = &SCRIPT_VARS(sid);
1934 di = find_var_in_ht(ht, 0, name, TRUE);
1935 if (di == NULL)
1936 return -2;
1937
1938 // Now find the svar_T index in sn_var_vals.
1939 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
1940 {
1941 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1942
1943 if (sv->sv_tv == &di->di_tv)
1944 {
1945 if (check_writable && sv->sv_const)
1946 semsg(_(e_readonlyvar), name);
1947 return idx;
1948 }
1949 }
1950 return -1;
1951}
1952
1953/*
1954 * Find "name" in imported items of the current script/
1955 */
1956 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001957find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001958{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001959 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001960 int idx;
1961
1962 if (cctx != NULL)
1963 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1964 {
1965 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
1966 + idx;
1967
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001968 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1969 : STRLEN(import->imp_name) == len
1970 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001971 return import;
1972 }
1973
1974 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
1975 {
1976 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
1977
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001978 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1979 : STRLEN(import->imp_name) == len
1980 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001981 return import;
1982 }
1983 return NULL;
1984}
1985
1986/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001987 * Free all imported variables.
1988 */
1989 static void
1990free_imported(cctx_T *cctx)
1991{
1992 int idx;
1993
1994 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1995 {
1996 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
1997
1998 vim_free(import->imp_name);
1999 }
2000 ga_clear(&cctx->ctx_imports);
2001}
2002
2003/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002004 * Generate an instruction to load script-local variable "name", without the
2005 * leading "s:".
2006 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002007 */
2008 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002009compile_load_scriptvar(
2010 cctx_T *cctx,
2011 char_u *name, // variable NUL terminated
2012 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002013 char_u **end, // end of variable
2014 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002015{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002016 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002017 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2018 imported_T *import;
2019
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002020 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002021 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002022 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002023 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2024 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002025 }
2026 if (idx >= 0)
2027 {
2028 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2029
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002030 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002031 current_sctx.sc_sid, idx, sv->sv_type);
2032 return OK;
2033 }
2034
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002035 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002036 if (import != NULL)
2037 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002038 if (import->imp_all)
2039 {
2040 char_u *p = skipwhite(*end);
2041 int name_len;
2042 ufunc_T *ufunc;
2043 type_T *type;
2044
2045 // Used "import * as Name", need to lookup the member.
2046 if (*p != '.')
2047 {
2048 semsg(_("E1060: expected dot after name: %s"), start);
2049 return FAIL;
2050 }
2051 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002052 if (VIM_ISWHITE(*p))
2053 {
2054 emsg(_("E1074: no white space allowed after dot"));
2055 return FAIL;
2056 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002057
2058 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2059 // TODO: what if it is a function?
2060 if (idx < 0)
2061 return FAIL;
2062 *end = p;
2063
2064 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2065 import->imp_sid,
2066 idx,
2067 type);
2068 }
2069 else
2070 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002071 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002072 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2073 import->imp_sid,
2074 import->imp_var_vals_idx,
2075 import->imp_type);
2076 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002077 return OK;
2078 }
2079
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002080 if (error)
2081 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002082 return FAIL;
2083}
2084
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002085 static int
2086generate_funcref(cctx_T *cctx, char_u *name)
2087{
2088 ufunc_T *ufunc = find_func(name, cctx);
2089
2090 if (ufunc == NULL)
2091 return FAIL;
2092
2093 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2094}
2095
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002096/*
2097 * Compile a variable name into a load instruction.
2098 * "end" points to just after the name.
2099 * When "error" is FALSE do not give an error when not found.
2100 */
2101 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002102compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002103{
2104 type_T *type;
2105 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002106 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002107 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002108 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002109
2110 if (*(*arg + 1) == ':')
2111 {
2112 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002113 if (end <= *arg + 2)
2114 name = vim_strsave((char_u *)"[empty]");
2115 else
2116 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002117 if (name == NULL)
2118 return FAIL;
2119
2120 if (**arg == 'v')
2121 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002122 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002123 }
2124 else if (**arg == 'g')
2125 {
2126 // Global variables can be defined later, thus we don't check if it
2127 // exists, give error at runtime.
2128 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2129 }
2130 else if (**arg == 's')
2131 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002132 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002133 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002134 else if (**arg == 'b')
2135 {
2136 semsg("Namespace b: not supported yet: %s", *arg);
2137 goto theend;
2138 }
2139 else if (**arg == 'w')
2140 {
2141 semsg("Namespace w: not supported yet: %s", *arg);
2142 goto theend;
2143 }
2144 else if (**arg == 't')
2145 {
2146 semsg("Namespace t: not supported yet: %s", *arg);
2147 goto theend;
2148 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002149 else
2150 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002151 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002152 goto theend;
2153 }
2154 }
2155 else
2156 {
2157 size_t len = end - *arg;
2158 int idx;
2159 int gen_load = FALSE;
2160
2161 name = vim_strnsave(*arg, end - *arg);
2162 if (name == NULL)
2163 return FAIL;
2164
2165 idx = lookup_arg(*arg, len, cctx);
2166 if (idx >= 0)
2167 {
2168 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2169 type = cctx->ctx_ufunc->uf_arg_types[idx];
2170 else
2171 type = &t_any;
2172
2173 // Arguments are located above the frame pointer.
2174 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2175 if (cctx->ctx_ufunc->uf_va_name != NULL)
2176 --idx;
2177 gen_load = TRUE;
2178 }
2179 else if (lookup_vararg(*arg, len, cctx))
2180 {
2181 // varargs is always the last argument
2182 idx = -STACK_FRAME_SIZE - 1;
2183 type = cctx->ctx_ufunc->uf_va_type;
2184 gen_load = TRUE;
2185 }
2186 else
2187 {
2188 idx = lookup_local(*arg, len, cctx);
2189 if (idx >= 0)
2190 {
2191 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2192 gen_load = TRUE;
2193 }
2194 else
2195 {
2196 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2197 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2198 res = generate_PUSHBOOL(cctx, **arg == 't'
2199 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002200 else
2201 {
2202 // "var" can be script-local even without using "s:" if it
2203 // already exists.
2204 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2205 == SCRIPT_VERSION_VIM9
2206 || lookup_script(*arg, len) == OK)
2207 res = compile_load_scriptvar(cctx, name, *arg, &end,
2208 FALSE);
2209
2210 // When the name starts with an uppercase letter or "x:" it
2211 // can be a user defined function.
2212 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2213 res = generate_funcref(cctx, name);
2214 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002215 }
2216 }
2217 if (gen_load)
2218 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2219 }
2220
2221 *arg = end;
2222
2223theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002224 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002225 semsg(_(e_var_notfound), name);
2226 vim_free(name);
2227 return res;
2228}
2229
2230/*
2231 * Compile the argument expressions.
2232 * "arg" points to just after the "(" and is advanced to after the ")"
2233 */
2234 static int
2235compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2236{
2237 char_u *p = *arg;
2238
2239 while (*p != NUL && *p != ')')
2240 {
2241 if (compile_expr1(&p, cctx) == FAIL)
2242 return FAIL;
2243 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002244
2245 if (*p != ',' && *skipwhite(p) == ',')
2246 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002247 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002248 p = skipwhite(p);
2249 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002250 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002251 {
2252 ++p;
2253 if (!VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002254 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002255 }
2256 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002257 }
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002258 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002259 if (*p != ')')
2260 {
2261 emsg(_(e_missing_close));
2262 return FAIL;
2263 }
2264 *arg = p + 1;
2265 return OK;
2266}
2267
2268/*
2269 * Compile a function call: name(arg1, arg2)
2270 * "arg" points to "name", "arg + varlen" to the "(".
2271 * "argcount_init" is 1 for "value->method()"
2272 * Instructions:
2273 * EVAL arg1
2274 * EVAL arg2
2275 * BCALL / DCALL / UCALL
2276 */
2277 static int
2278compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2279{
2280 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002281 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002282 int argcount = argcount_init;
2283 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002284 char_u fname_buf[FLEN_FIXED + 1];
2285 char_u *tofree = NULL;
2286 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002287 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002288 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002289
2290 if (varlen >= sizeof(namebuf))
2291 {
2292 semsg(_("E1011: name too long: %s"), name);
2293 return FAIL;
2294 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002295 vim_strncpy(namebuf, *arg, varlen);
2296 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002297
2298 *arg = skipwhite(*arg + varlen + 1);
2299 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002300 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002301
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002302 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002303 {
2304 int idx;
2305
2306 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002307 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002308 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002309 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002310 else
2311 semsg(_(e_unknownfunc), namebuf);
2312 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002313 }
2314
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002315 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002316 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002317 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002318 {
2319 res = generate_CALL(cctx, ufunc, argcount);
2320 goto theend;
2321 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002322
2323 // If the name is a variable, load it and use PCALL.
2324 p = namebuf;
2325 if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002326 {
2327 res = generate_PCALL(cctx, argcount, FALSE);
2328 goto theend;
2329 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002330
2331 // The function may be defined only later. Need to figure out at runtime.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002332 res = generate_UCALL(cctx, name, argcount);
2333
2334theend:
2335 vim_free(tofree);
2336 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002337}
2338
2339// like NAMESPACE_CHAR but with 'a' and 'l'.
2340#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2341
2342/*
2343 * Find the end of a variable or function name. Unlike find_name_end() this
2344 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002345 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002346 * Return a pointer to just after the name. Equal to "arg" if there is no
2347 * valid name.
2348 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002349 static char_u *
2350to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002351{
2352 char_u *p;
2353
2354 // Quick check for valid starting character.
2355 if (!eval_isnamec1(*arg))
2356 return arg;
2357
2358 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2359 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2360 // and can be used in slice "[n:]".
2361 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002362 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002363 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2364 break;
2365 return p;
2366}
2367
2368/*
2369 * Like to_name_end() but also skip over a list or dict constant.
2370 */
2371 char_u *
2372to_name_const_end(char_u *arg)
2373{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002374 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002375 typval_T rettv;
2376
2377 if (p == arg && *arg == '[')
2378 {
2379
2380 // Can be "[1, 2, 3]->Func()".
2381 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2382 p = arg;
2383 }
2384 else if (p == arg && *arg == '#' && arg[1] == '{')
2385 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002386 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002387 ++p;
2388 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2389 p = arg;
2390 }
2391 else if (p == arg && *arg == '{')
2392 {
2393 int ret = get_lambda_tv(&p, &rettv, FALSE);
2394
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002395 // Can be "{x -> ret}()".
2396 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002397 if (ret == NOTDONE)
2398 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2399 if (ret != OK)
2400 p = arg;
2401 }
2402
2403 return p;
2404}
2405
2406 static void
2407type_mismatch(type_T *expected, type_T *actual)
2408{
2409 char *tofree1, *tofree2;
2410
2411 semsg(_("E1013: type mismatch, expected %s but got %s"),
2412 type_name(expected, &tofree1), type_name(actual, &tofree2));
2413 vim_free(tofree1);
2414 vim_free(tofree2);
2415}
2416
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002417 static void
2418arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2419{
2420 char *tofree1, *tofree2;
2421
2422 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2423 argidx,
2424 type_name(expected, &tofree1), type_name(actual, &tofree2));
2425 vim_free(tofree1);
2426 vim_free(tofree2);
2427}
2428
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002429/*
2430 * Check if the expected and actual types match.
2431 */
2432 static int
2433check_type(type_T *expected, type_T *actual, int give_msg)
2434{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002435 int ret = OK;
2436
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002437 // When expected is "unknown" we accept any actual type.
2438 // When expected is "any" we accept any actual type except "void".
2439 if (expected->tt_type != VAR_UNKNOWN
2440 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002441 {
2442 if (expected->tt_type != actual->tt_type)
2443 {
2444 if (give_msg)
2445 type_mismatch(expected, actual);
2446 return FAIL;
2447 }
2448 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2449 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002450 // "unknown" is used for an empty list or dict
2451 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002452 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002453 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002454 else if (expected->tt_type == VAR_FUNC)
2455 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002456 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002457 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2458 if (ret == OK && expected->tt_argcount != -1
2459 && (actual->tt_argcount < expected->tt_min_argcount
2460 || actual->tt_argcount > expected->tt_argcount))
2461 ret = FAIL;
2462 }
2463 if (ret == FAIL && give_msg)
2464 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002465 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002466 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002467}
2468
2469/*
2470 * Check that
2471 * - "actual" is "expected" type or
2472 * - "actual" is a type that can be "expected" type: add a runtime check; or
2473 * - return FAIL.
2474 */
2475 static int
2476need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2477{
Bram Moolenaar89228602020-04-05 22:14:54 +02002478 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002479 return OK;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002480 if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002481 {
2482 type_mismatch(expected, actual);
2483 return FAIL;
2484 }
2485 generate_TYPECHECK(cctx, expected, offset);
2486 return OK;
2487}
2488
2489/*
2490 * parse a list: [expr, expr]
2491 * "*arg" points to the '['.
2492 */
2493 static int
2494compile_list(char_u **arg, cctx_T *cctx)
2495{
2496 char_u *p = skipwhite(*arg + 1);
2497 int count = 0;
2498
2499 while (*p != ']')
2500 {
2501 if (*p == NUL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01002502 {
2503 semsg(_(e_list_end), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002504 return FAIL;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002505 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002506 if (compile_expr1(&p, cctx) == FAIL)
2507 break;
2508 ++count;
2509 if (*p == ',')
2510 ++p;
2511 p = skipwhite(p);
2512 }
2513 *arg = p + 1;
2514
2515 generate_NEWLIST(cctx, count);
2516 return OK;
2517}
2518
2519/*
2520 * parse a lambda: {arg, arg -> expr}
2521 * "*arg" points to the '{'.
2522 */
2523 static int
2524compile_lambda(char_u **arg, cctx_T *cctx)
2525{
2526 garray_T *instr = &cctx->ctx_instr;
2527 typval_T rettv;
2528 ufunc_T *ufunc;
2529
2530 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002531 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002532 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002533
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002534 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002535 ++ufunc->uf_refcount;
2536 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002537 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002538
2539 // The function will have one line: "return {expr}".
2540 // Compile it into instructions.
2541 compile_def_function(ufunc, TRUE);
2542
2543 if (ufunc->uf_dfunc_idx >= 0)
2544 {
2545 if (ga_grow(instr, 1) == FAIL)
2546 return FAIL;
2547 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2548 return OK;
2549 }
2550 return FAIL;
2551}
2552
2553/*
2554 * Compile a lamda call: expr->{lambda}(args)
2555 * "arg" points to the "{".
2556 */
2557 static int
2558compile_lambda_call(char_u **arg, cctx_T *cctx)
2559{
2560 ufunc_T *ufunc;
2561 typval_T rettv;
2562 int argcount = 1;
2563 int ret = FAIL;
2564
2565 // Get the funcref in "rettv".
2566 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2567 return FAIL;
2568
2569 if (**arg != '(')
2570 {
2571 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002572 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002573 else
2574 semsg(_(e_missing_paren), "lambda");
2575 clear_tv(&rettv);
2576 return FAIL;
2577 }
2578
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002579 ufunc = rettv.vval.v_partial->pt_func;
2580 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002581 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002582 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002583
2584 // The function will have one line: "return {expr}".
2585 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002586 compile_def_function(ufunc, TRUE);
2587
2588 // compile the arguments
2589 *arg = skipwhite(*arg + 1);
2590 if (compile_arguments(arg, cctx, &argcount) == OK)
2591 // call the compiled function
2592 ret = generate_CALL(cctx, ufunc, argcount);
2593
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002594 return ret;
2595}
2596
2597/*
2598 * parse a dict: {'key': val} or #{key: val}
2599 * "*arg" points to the '{'.
2600 */
2601 static int
2602compile_dict(char_u **arg, cctx_T *cctx, int literal)
2603{
2604 garray_T *instr = &cctx->ctx_instr;
2605 int count = 0;
2606 dict_T *d = dict_alloc();
2607 dictitem_T *item;
2608
2609 if (d == NULL)
2610 return FAIL;
2611 *arg = skipwhite(*arg + 1);
2612 while (**arg != '}' && **arg != NUL)
2613 {
2614 char_u *key = NULL;
2615
2616 if (literal)
2617 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002618 char_u *p = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002619
2620 if (p == *arg)
2621 {
2622 semsg(_("E1014: Invalid key: %s"), *arg);
2623 return FAIL;
2624 }
2625 key = vim_strnsave(*arg, p - *arg);
2626 if (generate_PUSHS(cctx, key) == FAIL)
2627 return FAIL;
2628 *arg = p;
2629 }
2630 else
2631 {
2632 isn_T *isn;
2633
2634 if (compile_expr1(arg, cctx) == FAIL)
2635 return FAIL;
2636 // TODO: check type is string
2637 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2638 if (isn->isn_type == ISN_PUSHS)
2639 key = isn->isn_arg.string;
2640 }
2641
2642 // Check for duplicate keys, if using string keys.
2643 if (key != NULL)
2644 {
2645 item = dict_find(d, key, -1);
2646 if (item != NULL)
2647 {
2648 semsg(_(e_duplicate_key), key);
2649 goto failret;
2650 }
2651 item = dictitem_alloc(key);
2652 if (item != NULL)
2653 {
2654 item->di_tv.v_type = VAR_UNKNOWN;
2655 item->di_tv.v_lock = 0;
2656 if (dict_add(d, item) == FAIL)
2657 dictitem_free(item);
2658 }
2659 }
2660
2661 *arg = skipwhite(*arg);
2662 if (**arg != ':')
2663 {
2664 semsg(_(e_missing_dict_colon), *arg);
2665 return FAIL;
2666 }
2667
2668 *arg = skipwhite(*arg + 1);
2669 if (compile_expr1(arg, cctx) == FAIL)
2670 return FAIL;
2671 ++count;
2672
2673 if (**arg == '}')
2674 break;
2675 if (**arg != ',')
2676 {
2677 semsg(_(e_missing_dict_comma), *arg);
2678 goto failret;
2679 }
2680 *arg = skipwhite(*arg + 1);
2681 }
2682
2683 if (**arg != '}')
2684 {
2685 semsg(_(e_missing_dict_end), *arg);
2686 goto failret;
2687 }
2688 *arg = *arg + 1;
2689
2690 dict_unref(d);
2691 return generate_NEWDICT(cctx, count);
2692
2693failret:
2694 dict_unref(d);
2695 return FAIL;
2696}
2697
2698/*
2699 * Compile "&option".
2700 */
2701 static int
2702compile_get_option(char_u **arg, cctx_T *cctx)
2703{
2704 typval_T rettv;
2705 char_u *start = *arg;
2706 int ret;
2707
2708 // parse the option and get the current value to get the type.
2709 rettv.v_type = VAR_UNKNOWN;
2710 ret = get_option_tv(arg, &rettv, TRUE);
2711 if (ret == OK)
2712 {
2713 // include the '&' in the name, get_option_tv() expects it.
2714 char_u *name = vim_strnsave(start, *arg - start);
2715 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2716
2717 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2718 vim_free(name);
2719 }
2720 clear_tv(&rettv);
2721
2722 return ret;
2723}
2724
2725/*
2726 * Compile "$VAR".
2727 */
2728 static int
2729compile_get_env(char_u **arg, cctx_T *cctx)
2730{
2731 char_u *start = *arg;
2732 int len;
2733 int ret;
2734 char_u *name;
2735
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002736 ++*arg;
2737 len = get_env_len(arg);
2738 if (len == 0)
2739 {
2740 semsg(_(e_syntax_at), start - 1);
2741 return FAIL;
2742 }
2743
2744 // include the '$' in the name, get_env_tv() expects it.
2745 name = vim_strnsave(start, len + 1);
2746 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2747 vim_free(name);
2748 return ret;
2749}
2750
2751/*
2752 * Compile "@r".
2753 */
2754 static int
2755compile_get_register(char_u **arg, cctx_T *cctx)
2756{
2757 int ret;
2758
2759 ++*arg;
2760 if (**arg == NUL)
2761 {
2762 semsg(_(e_syntax_at), *arg - 1);
2763 return FAIL;
2764 }
2765 if (!valid_yank_reg(**arg, TRUE))
2766 {
2767 emsg_invreg(**arg);
2768 return FAIL;
2769 }
2770 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2771 ++*arg;
2772 return ret;
2773}
2774
2775/*
2776 * Apply leading '!', '-' and '+' to constant "rettv".
2777 */
2778 static int
2779apply_leader(typval_T *rettv, char_u *start, char_u *end)
2780{
2781 char_u *p = end;
2782
2783 // this works from end to start
2784 while (p > start)
2785 {
2786 --p;
2787 if (*p == '-' || *p == '+')
2788 {
2789 // only '-' has an effect, for '+' we only check the type
2790#ifdef FEAT_FLOAT
2791 if (rettv->v_type == VAR_FLOAT)
2792 {
2793 if (*p == '-')
2794 rettv->vval.v_float = -rettv->vval.v_float;
2795 }
2796 else
2797#endif
2798 {
2799 varnumber_T val;
2800 int error = FALSE;
2801
2802 // tv_get_number_chk() accepts a string, but we don't want that
2803 // here
2804 if (check_not_string(rettv) == FAIL)
2805 return FAIL;
2806 val = tv_get_number_chk(rettv, &error);
2807 clear_tv(rettv);
2808 if (error)
2809 return FAIL;
2810 if (*p == '-')
2811 val = -val;
2812 rettv->v_type = VAR_NUMBER;
2813 rettv->vval.v_number = val;
2814 }
2815 }
2816 else
2817 {
2818 int v = tv2bool(rettv);
2819
2820 // '!' is permissive in the type.
2821 clear_tv(rettv);
2822 rettv->v_type = VAR_BOOL;
2823 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
2824 }
2825 }
2826 return OK;
2827}
2828
2829/*
2830 * Recognize v: variables that are constants and set "rettv".
2831 */
2832 static void
2833get_vim_constant(char_u **arg, typval_T *rettv)
2834{
2835 if (STRNCMP(*arg, "v:true", 6) == 0)
2836 {
2837 rettv->v_type = VAR_BOOL;
2838 rettv->vval.v_number = VVAL_TRUE;
2839 *arg += 6;
2840 }
2841 else if (STRNCMP(*arg, "v:false", 7) == 0)
2842 {
2843 rettv->v_type = VAR_BOOL;
2844 rettv->vval.v_number = VVAL_FALSE;
2845 *arg += 7;
2846 }
2847 else if (STRNCMP(*arg, "v:null", 6) == 0)
2848 {
2849 rettv->v_type = VAR_SPECIAL;
2850 rettv->vval.v_number = VVAL_NULL;
2851 *arg += 6;
2852 }
2853 else if (STRNCMP(*arg, "v:none", 6) == 0)
2854 {
2855 rettv->v_type = VAR_SPECIAL;
2856 rettv->vval.v_number = VVAL_NONE;
2857 *arg += 6;
2858 }
2859}
2860
2861/*
2862 * Compile code to apply '-', '+' and '!'.
2863 */
2864 static int
2865compile_leader(cctx_T *cctx, char_u *start, char_u *end)
2866{
2867 char_u *p = end;
2868
2869 // this works from end to start
2870 while (p > start)
2871 {
2872 --p;
2873 if (*p == '-' || *p == '+')
2874 {
2875 int negate = *p == '-';
2876 isn_T *isn;
2877
2878 // TODO: check type
2879 while (p > start && (p[-1] == '-' || p[-1] == '+'))
2880 {
2881 --p;
2882 if (*p == '-')
2883 negate = !negate;
2884 }
2885 // only '-' has an effect, for '+' we only check the type
2886 if (negate)
2887 isn = generate_instr(cctx, ISN_NEGATENR);
2888 else
2889 isn = generate_instr(cctx, ISN_CHECKNR);
2890 if (isn == NULL)
2891 return FAIL;
2892 }
2893 else
2894 {
2895 int invert = TRUE;
2896
2897 while (p > start && p[-1] == '!')
2898 {
2899 --p;
2900 invert = !invert;
2901 }
2902 if (generate_2BOOL(cctx, invert) == FAIL)
2903 return FAIL;
2904 }
2905 }
2906 return OK;
2907}
2908
2909/*
2910 * Compile whatever comes after "name" or "name()".
2911 */
2912 static int
2913compile_subscript(
2914 char_u **arg,
2915 cctx_T *cctx,
2916 char_u **start_leader,
2917 char_u *end_leader)
2918{
2919 for (;;)
2920 {
2921 if (**arg == '(')
2922 {
2923 int argcount = 0;
2924
2925 // funcref(arg)
2926 *arg = skipwhite(*arg + 1);
2927 if (compile_arguments(arg, cctx, &argcount) == FAIL)
2928 return FAIL;
2929 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
2930 return FAIL;
2931 }
2932 else if (**arg == '-' && (*arg)[1] == '>')
2933 {
2934 char_u *p;
2935
2936 // something->method()
2937 // Apply the '!', '-' and '+' first:
2938 // -1.0->func() works like (-1.0)->func()
2939 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
2940 return FAIL;
2941 *start_leader = end_leader; // don't apply again later
2942
2943 *arg = skipwhite(*arg + 2);
2944 if (**arg == '{')
2945 {
2946 // lambda call: list->{lambda}
2947 if (compile_lambda_call(arg, cctx) == FAIL)
2948 return FAIL;
2949 }
2950 else
2951 {
2952 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02002953 p = *arg;
2954 if (ASCII_ISALPHA(*p) && p[1] == ':')
2955 p += 2;
2956 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002957 ;
2958 if (*p != '(')
2959 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02002960 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002961 return FAIL;
2962 }
2963 // TODO: base value may not be the first argument
2964 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
2965 return FAIL;
2966 }
2967 }
2968 else if (**arg == '[')
2969 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01002970 garray_T *stack;
2971 type_T **typep;
2972
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002973 // list index: list[123]
2974 // TODO: more arguments
2975 // TODO: dict member dict['name']
2976 *arg = skipwhite(*arg + 1);
2977 if (compile_expr1(arg, cctx) == FAIL)
2978 return FAIL;
2979
2980 if (**arg != ']')
2981 {
2982 emsg(_(e_missbrac));
2983 return FAIL;
2984 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01002985 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002986
2987 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
2988 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01002989 stack = &cctx->ctx_type_stack;
2990 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
2991 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
2992 {
2993 emsg(_(e_listreq));
2994 return FAIL;
2995 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01002996 if ((*typep)->tt_type == VAR_LIST)
2997 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002998 }
2999 else if (**arg == '.' && (*arg)[1] != '.')
3000 {
3001 char_u *p;
3002
3003 ++*arg;
3004 p = *arg;
3005 // dictionary member: dict.name
3006 if (eval_isnamec1(*p))
3007 while (eval_isnamec(*p))
3008 MB_PTR_ADV(p);
3009 if (p == *arg)
3010 {
3011 semsg(_(e_syntax_at), *arg);
3012 return FAIL;
3013 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003014 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3015 return FAIL;
3016 *arg = p;
3017 }
3018 else
3019 break;
3020 }
3021
3022 // TODO - see handle_subscript():
3023 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3024 // Don't do this when "Func" is already a partial that was bound
3025 // explicitly (pt_auto is FALSE).
3026
3027 return OK;
3028}
3029
3030/*
3031 * Compile an expression at "*p" and add instructions to "instr".
3032 * "p" is advanced until after the expression, skipping white space.
3033 *
3034 * This is the equivalent of eval1(), eval2(), etc.
3035 */
3036
3037/*
3038 * number number constant
3039 * 0zFFFFFFFF Blob constant
3040 * "string" string constant
3041 * 'string' literal string constant
3042 * &option-name option value
3043 * @r register contents
3044 * identifier variable value
3045 * function() function call
3046 * $VAR environment variable
3047 * (expression) nested expression
3048 * [expr, expr] List
3049 * {key: val, key: val} Dictionary
3050 * #{key: val, key: val} Dictionary with literal keys
3051 *
3052 * Also handle:
3053 * ! in front logical NOT
3054 * - in front unary minus
3055 * + in front unary plus (ignored)
3056 * trailing (arg) funcref/partial call
3057 * trailing [] subscript in String or List
3058 * trailing .name entry in Dictionary
3059 * trailing ->name() method call
3060 */
3061 static int
3062compile_expr7(char_u **arg, cctx_T *cctx)
3063{
3064 typval_T rettv;
3065 char_u *start_leader, *end_leader;
3066 int ret = OK;
3067
3068 /*
3069 * Skip '!', '-' and '+' characters. They are handled later.
3070 */
3071 start_leader = *arg;
3072 while (**arg == '!' || **arg == '-' || **arg == '+')
3073 *arg = skipwhite(*arg + 1);
3074 end_leader = *arg;
3075
3076 rettv.v_type = VAR_UNKNOWN;
3077 switch (**arg)
3078 {
3079 /*
3080 * Number constant.
3081 */
3082 case '0': // also for blob starting with 0z
3083 case '1':
3084 case '2':
3085 case '3':
3086 case '4':
3087 case '5':
3088 case '6':
3089 case '7':
3090 case '8':
3091 case '9':
3092 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3093 return FAIL;
3094 break;
3095
3096 /*
3097 * String constant: "string".
3098 */
3099 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3100 return FAIL;
3101 break;
3102
3103 /*
3104 * Literal string constant: 'str''ing'.
3105 */
3106 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3107 return FAIL;
3108 break;
3109
3110 /*
3111 * Constant Vim variable.
3112 */
3113 case 'v': get_vim_constant(arg, &rettv);
3114 ret = NOTDONE;
3115 break;
3116
3117 /*
3118 * List: [expr, expr]
3119 */
3120 case '[': ret = compile_list(arg, cctx);
3121 break;
3122
3123 /*
3124 * Dictionary: #{key: val, key: val}
3125 */
3126 case '#': if ((*arg)[1] == '{')
3127 {
3128 ++*arg;
3129 ret = compile_dict(arg, cctx, TRUE);
3130 }
3131 else
3132 ret = NOTDONE;
3133 break;
3134
3135 /*
3136 * Lambda: {arg, arg -> expr}
3137 * Dictionary: {'key': val, 'key': val}
3138 */
3139 case '{': {
3140 char_u *start = skipwhite(*arg + 1);
3141
3142 // Find out what comes after the arguments.
3143 ret = get_function_args(&start, '-', NULL,
3144 NULL, NULL, NULL, TRUE);
3145 if (ret != FAIL && *start == '>')
3146 ret = compile_lambda(arg, cctx);
3147 else
3148 ret = compile_dict(arg, cctx, FALSE);
3149 }
3150 break;
3151
3152 /*
3153 * Option value: &name
3154 */
3155 case '&': ret = compile_get_option(arg, cctx);
3156 break;
3157
3158 /*
3159 * Environment variable: $VAR.
3160 */
3161 case '$': ret = compile_get_env(arg, cctx);
3162 break;
3163
3164 /*
3165 * Register contents: @r.
3166 */
3167 case '@': ret = compile_get_register(arg, cctx);
3168 break;
3169 /*
3170 * nested expression: (expression).
3171 */
3172 case '(': *arg = skipwhite(*arg + 1);
3173 ret = compile_expr1(arg, cctx); // recursive!
3174 *arg = skipwhite(*arg);
3175 if (**arg == ')')
3176 ++*arg;
3177 else if (ret == OK)
3178 {
3179 emsg(_(e_missing_close));
3180 ret = FAIL;
3181 }
3182 break;
3183
3184 default: ret = NOTDONE;
3185 break;
3186 }
3187 if (ret == FAIL)
3188 return FAIL;
3189
3190 if (rettv.v_type != VAR_UNKNOWN)
3191 {
3192 // apply the '!', '-' and '+' before the constant
3193 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3194 {
3195 clear_tv(&rettv);
3196 return FAIL;
3197 }
3198 start_leader = end_leader; // don't apply again below
3199
3200 // push constant
3201 switch (rettv.v_type)
3202 {
3203 case VAR_BOOL:
3204 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3205 break;
3206 case VAR_SPECIAL:
3207 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3208 break;
3209 case VAR_NUMBER:
3210 generate_PUSHNR(cctx, rettv.vval.v_number);
3211 break;
3212#ifdef FEAT_FLOAT
3213 case VAR_FLOAT:
3214 generate_PUSHF(cctx, rettv.vval.v_float);
3215 break;
3216#endif
3217 case VAR_BLOB:
3218 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3219 rettv.vval.v_blob = NULL;
3220 break;
3221 case VAR_STRING:
3222 generate_PUSHS(cctx, rettv.vval.v_string);
3223 rettv.vval.v_string = NULL;
3224 break;
3225 default:
3226 iemsg("constant type missing");
3227 return FAIL;
3228 }
3229 }
3230 else if (ret == NOTDONE)
3231 {
3232 char_u *p;
3233 int r;
3234
3235 if (!eval_isnamec1(**arg))
3236 {
3237 semsg(_("E1015: Name expected: %s"), *arg);
3238 return FAIL;
3239 }
3240
3241 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003242 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003243 if (*p == '(')
3244 r = compile_call(arg, p - *arg, cctx, 0);
3245 else
3246 r = compile_load(arg, p, cctx, TRUE);
3247 if (r == FAIL)
3248 return FAIL;
3249 }
3250
3251 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3252 return FAIL;
3253
3254 // Now deal with prefixed '-', '+' and '!', if not done already.
3255 return compile_leader(cctx, start_leader, end_leader);
3256}
3257
3258/*
3259 * * number multiplication
3260 * / number division
3261 * % number modulo
3262 */
3263 static int
3264compile_expr6(char_u **arg, cctx_T *cctx)
3265{
3266 char_u *op;
3267
3268 // get the first variable
3269 if (compile_expr7(arg, cctx) == FAIL)
3270 return FAIL;
3271
3272 /*
3273 * Repeat computing, until no "*", "/" or "%" is following.
3274 */
3275 for (;;)
3276 {
3277 op = skipwhite(*arg);
3278 if (*op != '*' && *op != '/' && *op != '%')
3279 break;
3280 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[1]))
3281 {
3282 char_u buf[3];
3283
3284 vim_strncpy(buf, op, 1);
3285 semsg(_(e_white_both), buf);
3286 }
3287 *arg = skipwhite(op + 1);
3288
3289 // get the second variable
3290 if (compile_expr7(arg, cctx) == FAIL)
3291 return FAIL;
3292
3293 generate_two_op(cctx, op);
3294 }
3295
3296 return OK;
3297}
3298
3299/*
3300 * + number addition
3301 * - number subtraction
3302 * .. string concatenation
3303 */
3304 static int
3305compile_expr5(char_u **arg, cctx_T *cctx)
3306{
3307 char_u *op;
3308 int oplen;
3309
3310 // get the first variable
3311 if (compile_expr6(arg, cctx) == FAIL)
3312 return FAIL;
3313
3314 /*
3315 * Repeat computing, until no "+", "-" or ".." is following.
3316 */
3317 for (;;)
3318 {
3319 op = skipwhite(*arg);
3320 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3321 break;
3322 oplen = (*op == '.' ? 2 : 1);
3323
3324 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[oplen]))
3325 {
3326 char_u buf[3];
3327
3328 vim_strncpy(buf, op, oplen);
3329 semsg(_(e_white_both), buf);
3330 }
3331
3332 *arg = skipwhite(op + oplen);
3333
3334 // get the second variable
3335 if (compile_expr6(arg, cctx) == FAIL)
3336 return FAIL;
3337
3338 if (*op == '.')
3339 {
3340 if (may_generate_2STRING(-2, cctx) == FAIL
3341 || may_generate_2STRING(-1, cctx) == FAIL)
3342 return FAIL;
3343 generate_instr_drop(cctx, ISN_CONCAT, 1);
3344 }
3345 else
3346 generate_two_op(cctx, op);
3347 }
3348
3349 return OK;
3350}
3351
Bram Moolenaar080457c2020-03-03 21:53:32 +01003352 static exptype_T
3353get_compare_type(char_u *p, int *len, int *type_is)
3354{
3355 exptype_T type = EXPR_UNKNOWN;
3356 int i;
3357
3358 switch (p[0])
3359 {
3360 case '=': if (p[1] == '=')
3361 type = EXPR_EQUAL;
3362 else if (p[1] == '~')
3363 type = EXPR_MATCH;
3364 break;
3365 case '!': if (p[1] == '=')
3366 type = EXPR_NEQUAL;
3367 else if (p[1] == '~')
3368 type = EXPR_NOMATCH;
3369 break;
3370 case '>': if (p[1] != '=')
3371 {
3372 type = EXPR_GREATER;
3373 *len = 1;
3374 }
3375 else
3376 type = EXPR_GEQUAL;
3377 break;
3378 case '<': if (p[1] != '=')
3379 {
3380 type = EXPR_SMALLER;
3381 *len = 1;
3382 }
3383 else
3384 type = EXPR_SEQUAL;
3385 break;
3386 case 'i': if (p[1] == 's')
3387 {
3388 // "is" and "isnot"; but not a prefix of a name
3389 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3390 *len = 5;
3391 i = p[*len];
3392 if (!isalnum(i) && i != '_')
3393 {
3394 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3395 *type_is = TRUE;
3396 }
3397 }
3398 break;
3399 }
3400 return type;
3401}
3402
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003403/*
3404 * expr5a == expr5b
3405 * expr5a =~ expr5b
3406 * expr5a != expr5b
3407 * expr5a !~ expr5b
3408 * expr5a > expr5b
3409 * expr5a >= expr5b
3410 * expr5a < expr5b
3411 * expr5a <= expr5b
3412 * expr5a is expr5b
3413 * expr5a isnot expr5b
3414 *
3415 * Produces instructions:
3416 * EVAL expr5a Push result of "expr5a"
3417 * EVAL expr5b Push result of "expr5b"
3418 * COMPARE one of the compare instructions
3419 */
3420 static int
3421compile_expr4(char_u **arg, cctx_T *cctx)
3422{
3423 exptype_T type = EXPR_UNKNOWN;
3424 char_u *p;
3425 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003426 int type_is = FALSE;
3427
3428 // get the first variable
3429 if (compile_expr5(arg, cctx) == FAIL)
3430 return FAIL;
3431
3432 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003433 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003434
3435 /*
3436 * If there is a comparative operator, use it.
3437 */
3438 if (type != EXPR_UNKNOWN)
3439 {
3440 int ic = FALSE; // Default: do not ignore case
3441
3442 if (type_is && (p[len] == '?' || p[len] == '#'))
3443 {
3444 semsg(_(e_invexpr2), *arg);
3445 return FAIL;
3446 }
3447 // extra question mark appended: ignore case
3448 if (p[len] == '?')
3449 {
3450 ic = TRUE;
3451 ++len;
3452 }
3453 // extra '#' appended: match case (ignored)
3454 else if (p[len] == '#')
3455 ++len;
3456 // nothing appended: match case
3457
3458 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[len]))
3459 {
3460 char_u buf[7];
3461
3462 vim_strncpy(buf, p, len);
3463 semsg(_(e_white_both), buf);
3464 }
3465
3466 // get the second variable
3467 *arg = skipwhite(p + len);
3468 if (compile_expr5(arg, cctx) == FAIL)
3469 return FAIL;
3470
3471 generate_COMPARE(cctx, type, ic);
3472 }
3473
3474 return OK;
3475}
3476
3477/*
3478 * Compile || or &&.
3479 */
3480 static int
3481compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3482{
3483 char_u *p = skipwhite(*arg);
3484 int opchar = *op;
3485
3486 if (p[0] == opchar && p[1] == opchar)
3487 {
3488 garray_T *instr = &cctx->ctx_instr;
3489 garray_T end_ga;
3490
3491 /*
3492 * Repeat until there is no following "||" or "&&"
3493 */
3494 ga_init2(&end_ga, sizeof(int), 10);
3495 while (p[0] == opchar && p[1] == opchar)
3496 {
3497 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
3498 semsg(_(e_white_both), op);
3499
3500 if (ga_grow(&end_ga, 1) == FAIL)
3501 {
3502 ga_clear(&end_ga);
3503 return FAIL;
3504 }
3505 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3506 ++end_ga.ga_len;
3507 generate_JUMP(cctx, opchar == '|'
3508 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3509
3510 // eval the next expression
3511 *arg = skipwhite(p + 2);
3512 if ((opchar == '|' ? compile_expr3(arg, cctx)
3513 : compile_expr4(arg, cctx)) == FAIL)
3514 {
3515 ga_clear(&end_ga);
3516 return FAIL;
3517 }
3518 p = skipwhite(*arg);
3519 }
3520
3521 // Fill in the end label in all jumps.
3522 while (end_ga.ga_len > 0)
3523 {
3524 isn_T *isn;
3525
3526 --end_ga.ga_len;
3527 isn = ((isn_T *)instr->ga_data)
3528 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3529 isn->isn_arg.jump.jump_where = instr->ga_len;
3530 }
3531 ga_clear(&end_ga);
3532 }
3533
3534 return OK;
3535}
3536
3537/*
3538 * expr4a && expr4a && expr4a logical AND
3539 *
3540 * Produces instructions:
3541 * EVAL expr4a Push result of "expr4a"
3542 * JUMP_AND_KEEP_IF_FALSE end
3543 * EVAL expr4b Push result of "expr4b"
3544 * JUMP_AND_KEEP_IF_FALSE end
3545 * EVAL expr4c Push result of "expr4c"
3546 * end:
3547 */
3548 static int
3549compile_expr3(char_u **arg, cctx_T *cctx)
3550{
3551 // get the first variable
3552 if (compile_expr4(arg, cctx) == FAIL)
3553 return FAIL;
3554
3555 // || and && work almost the same
3556 return compile_and_or(arg, cctx, "&&");
3557}
3558
3559/*
3560 * expr3a || expr3b || expr3c logical OR
3561 *
3562 * Produces instructions:
3563 * EVAL expr3a Push result of "expr3a"
3564 * JUMP_AND_KEEP_IF_TRUE end
3565 * EVAL expr3b Push result of "expr3b"
3566 * JUMP_AND_KEEP_IF_TRUE end
3567 * EVAL expr3c Push result of "expr3c"
3568 * end:
3569 */
3570 static int
3571compile_expr2(char_u **arg, cctx_T *cctx)
3572{
3573 // eval the first expression
3574 if (compile_expr3(arg, cctx) == FAIL)
3575 return FAIL;
3576
3577 // || and && work almost the same
3578 return compile_and_or(arg, cctx, "||");
3579}
3580
3581/*
3582 * Toplevel expression: expr2 ? expr1a : expr1b
3583 *
3584 * Produces instructions:
3585 * EVAL expr2 Push result of "expr"
3586 * JUMP_IF_FALSE alt jump if false
3587 * EVAL expr1a
3588 * JUMP_ALWAYS end
3589 * alt: EVAL expr1b
3590 * end:
3591 */
3592 static int
3593compile_expr1(char_u **arg, cctx_T *cctx)
3594{
3595 char_u *p;
3596
3597 // evaluate the first expression
3598 if (compile_expr2(arg, cctx) == FAIL)
3599 return FAIL;
3600
3601 p = skipwhite(*arg);
3602 if (*p == '?')
3603 {
3604 garray_T *instr = &cctx->ctx_instr;
3605 garray_T *stack = &cctx->ctx_type_stack;
3606 int alt_idx = instr->ga_len;
3607 int end_idx;
3608 isn_T *isn;
3609 type_T *type1;
3610 type_T *type2;
3611
3612 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3613 semsg(_(e_white_both), "?");
3614
3615 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3616
3617 // evaluate the second expression; any type is accepted
3618 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003619 if (compile_expr1(arg, cctx) == FAIL)
3620 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003621
3622 // remember the type and drop it
3623 --stack->ga_len;
3624 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3625
3626 end_idx = instr->ga_len;
3627 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3628
3629 // jump here from JUMP_IF_FALSE
3630 isn = ((isn_T *)instr->ga_data) + alt_idx;
3631 isn->isn_arg.jump.jump_where = instr->ga_len;
3632
3633 // Check for the ":".
3634 p = skipwhite(*arg);
3635 if (*p != ':')
3636 {
3637 emsg(_(e_missing_colon));
3638 return FAIL;
3639 }
3640 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3641 semsg(_(e_white_both), ":");
3642
3643 // evaluate the third expression
3644 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003645 if (compile_expr1(arg, cctx) == FAIL)
3646 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003647
3648 // If the types differ, the result has a more generic type.
3649 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003650 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003651
3652 // jump here from JUMP_ALWAYS
3653 isn = ((isn_T *)instr->ga_data) + end_idx;
3654 isn->isn_arg.jump.jump_where = instr->ga_len;
3655 }
3656 return OK;
3657}
3658
3659/*
3660 * compile "return [expr]"
3661 */
3662 static char_u *
3663compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3664{
3665 char_u *p = arg;
3666 garray_T *stack = &cctx->ctx_type_stack;
3667 type_T *stack_type;
3668
3669 if (*p != NUL && *p != '|' && *p != '\n')
3670 {
3671 // compile return argument into instructions
3672 if (compile_expr1(&p, cctx) == FAIL)
3673 return NULL;
3674
3675 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3676 if (set_return_type)
3677 cctx->ctx_ufunc->uf_ret_type = stack_type;
3678 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3679 == FAIL)
3680 return NULL;
3681 }
3682 else
3683 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003684 // "set_return_type" cannot be TRUE, only used for a lambda which
3685 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003686 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3687 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003688 {
3689 emsg(_("E1003: Missing return value"));
3690 return NULL;
3691 }
3692
3693 // No argument, return zero.
3694 generate_PUSHNR(cctx, 0);
3695 }
3696
3697 if (generate_instr(cctx, ISN_RETURN) == NULL)
3698 return NULL;
3699
3700 // "return val | endif" is possible
3701 return skipwhite(p);
3702}
3703
3704/*
3705 * Return the length of an assignment operator, or zero if there isn't one.
3706 */
3707 int
3708assignment_len(char_u *p, int *heredoc)
3709{
3710 if (*p == '=')
3711 {
3712 if (p[1] == '<' && p[2] == '<')
3713 {
3714 *heredoc = TRUE;
3715 return 3;
3716 }
3717 return 1;
3718 }
3719 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3720 return 2;
3721 if (STRNCMP(p, "..=", 3) == 0)
3722 return 3;
3723 return 0;
3724}
3725
3726// words that cannot be used as a variable
3727static char *reserved[] = {
3728 "true",
3729 "false",
3730 NULL
3731};
3732
3733/*
3734 * Get a line for "=<<".
3735 * Return a pointer to the line in allocated memory.
3736 * Return NULL for end-of-file or some error.
3737 */
3738 static char_u *
3739heredoc_getline(
3740 int c UNUSED,
3741 void *cookie,
3742 int indent UNUSED,
3743 int do_concat UNUSED)
3744{
3745 cctx_T *cctx = (cctx_T *)cookie;
3746
3747 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003748 {
3749 iemsg("Heredoc got to end");
3750 return NULL;
3751 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003752 ++cctx->ctx_lnum;
3753 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3754 [cctx->ctx_lnum]);
3755}
3756
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003757typedef enum {
3758 dest_local,
3759 dest_option,
3760 dest_env,
3761 dest_global,
3762 dest_vimvar,
3763 dest_script,
3764 dest_reg,
3765} assign_dest_T;
3766
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003767/*
3768 * compile "let var [= expr]", "const var = expr" and "var = expr"
3769 * "arg" points to "var".
3770 */
3771 static char_u *
3772compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3773{
3774 char_u *p;
3775 char_u *ret = NULL;
3776 int var_count = 0;
3777 int semicolon = 0;
3778 size_t varlen;
3779 garray_T *instr = &cctx->ctx_instr;
3780 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02003781 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003782 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003783 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003784 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003785 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003786 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003787 int oplen = 0;
3788 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003789 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003790 lvar_T *lvar;
3791 char_u *name;
3792 char_u *sp;
3793 int has_type = FALSE;
3794 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
3795 int instr_count = -1;
3796
3797 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
3798 if (p == NULL)
3799 return NULL;
3800 if (var_count > 0)
3801 {
3802 // TODO: let [var, var] = list
3803 emsg("Cannot handle a list yet");
3804 return NULL;
3805 }
3806
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003807 // "a: type" is declaring variable "a" with a type, not "a:".
3808 if (is_decl && p == arg + 2 && p[-1] == ':')
3809 --p;
3810
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003811 varlen = p - arg;
3812 name = vim_strnsave(arg, (int)varlen);
3813 if (name == NULL)
3814 return NULL;
3815
Bram Moolenaar080457c2020-03-03 21:53:32 +01003816 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003817 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003818 if (*arg == '&')
3819 {
3820 int cc;
3821 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003822
Bram Moolenaar080457c2020-03-03 21:53:32 +01003823 dest = dest_option;
3824 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003825 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003826 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003827 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003828 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003829 if (is_decl)
3830 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003831 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003832 goto theend;
3833 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01003834 p = arg;
3835 p = find_option_end(&p, &opt_flags);
3836 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003837 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003838 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01003839 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003840 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003841 }
3842 cc = *p;
3843 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003844 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003845 *p = cc;
3846 if (opt_type == -3)
3847 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003848 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003849 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003850 }
3851 if (opt_type == -2 || opt_type == 0)
3852 type = &t_string;
3853 else
3854 type = &t_number; // both number and boolean option
3855 }
3856 else if (*arg == '$')
3857 {
3858 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003859 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003860 if (is_decl)
3861 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003862 semsg(_("E1065: Cannot declare an environment variable: %s"),
3863 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003864 goto theend;
3865 }
3866 }
3867 else if (*arg == '@')
3868 {
3869 if (!valid_yank_reg(arg[1], TRUE))
3870 {
3871 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003872 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003873 }
3874 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003875 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003876 if (is_decl)
3877 {
3878 semsg(_("E1066: Cannot declare a register: %s"), name);
3879 goto theend;
3880 }
3881 }
3882 else if (STRNCMP(arg, "g:", 2) == 0)
3883 {
3884 dest = dest_global;
3885 if (is_decl)
3886 {
3887 semsg(_("E1016: Cannot declare a global variable: %s"), name);
3888 goto theend;
3889 }
3890 }
3891 else if (STRNCMP(arg, "v:", 2) == 0)
3892 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02003893 typval_T *vtv;
3894 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003895
Bram Moolenaar5da356e2020-04-09 19:34:43 +02003896 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003897 if (vimvaridx < 0)
3898 {
3899 semsg(_(e_var_notfound), arg);
3900 goto theend;
3901 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02003902 // We use the current value of "sandbox" here, is that OK?
3903 if (var_check_ro(di_flags, name, FALSE))
3904 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003905 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003906 vtv = get_vim_var_tv(vimvaridx);
3907 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003908 if (is_decl)
3909 {
3910 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
3911 goto theend;
3912 }
3913 }
3914 else
3915 {
3916 for (idx = 0; reserved[idx] != NULL; ++idx)
3917 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003918 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003919 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003920 goto theend;
3921 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01003922
3923 idx = lookup_local(arg, varlen, cctx);
3924 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003925 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003926 if (is_decl)
3927 {
3928 semsg(_("E1017: Variable already declared: %s"), name);
3929 goto theend;
3930 }
3931 else
3932 {
3933 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3934 if (lvar->lv_const)
3935 {
3936 semsg(_("E1018: Cannot assign to a constant: %s"), name);
3937 goto theend;
3938 }
3939 }
3940 }
3941 else if (STRNCMP(arg, "s:", 2) == 0
3942 || lookup_script(arg, varlen) == OK
3943 || find_imported(arg, varlen, cctx) != NULL)
3944 {
3945 dest = dest_script;
3946 if (is_decl)
3947 {
3948 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003949 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003950 goto theend;
3951 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003952 }
3953 }
3954 }
3955
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003956 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003957 {
3958 if (is_decl && *p == ':')
3959 {
3960 // parse optional type: "let var: type = expr"
3961 p = skipwhite(p + 1);
3962 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003963 has_type = TRUE;
3964 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02003965 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003966 {
3967 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3968 type = lvar->lv_type;
3969 }
3970 }
3971
3972 sp = p;
3973 p = skipwhite(p);
3974 op = p;
3975 oplen = assignment_len(p, &heredoc);
3976 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
3977 {
3978 char_u buf[4];
3979
3980 vim_strncpy(buf, op, oplen);
3981 semsg(_(e_white_both), buf);
3982 }
3983
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003984 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02003985 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003986 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01003987 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003988 goto theend;
3989 }
3990
Bram Moolenaar080457c2020-03-03 21:53:32 +01003991 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003992 {
3993 if (oplen > 1 && !heredoc)
3994 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003995 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003996 semsg(_("E1020: cannot use an operator on a new variable: %s"),
3997 name);
3998 goto theend;
3999 }
4000
4001 // new local variable
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004002 if ((type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
4003 && var_check_func_name(name, TRUE))
4004 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004005 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4006 if (idx < 0)
4007 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004008 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004009 }
4010
4011 if (heredoc)
4012 {
4013 list_T *l;
4014 listitem_T *li;
4015
4016 // [let] varname =<< [trim] {end}
4017 eap->getline = heredoc_getline;
4018 eap->cookie = cctx;
4019 l = heredoc_get(eap, op + 3);
4020
4021 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004022 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004023 {
4024 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4025 li->li_tv.vval.v_string = NULL;
4026 }
4027 generate_NEWLIST(cctx, l->lv_len);
4028 type = &t_list_string;
4029 list_free(l);
4030 p += STRLEN(p);
4031 }
4032 else if (oplen > 0)
4033 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004034 int r;
4035 type_T *stacktype;
4036 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004037
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004038 // for "+=", "*=", "..=" etc. first load the current value
4039 if (*op != '=')
4040 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004041 switch (dest)
4042 {
4043 case dest_option:
4044 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004045 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004046 break;
4047 case dest_global:
4048 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4049 break;
4050 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004051 compile_load_scriptvar(cctx,
4052 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004053 break;
4054 case dest_env:
4055 // Include $ in the name here
4056 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4057 break;
4058 case dest_reg:
4059 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4060 break;
4061 case dest_vimvar:
4062 generate_LOADV(cctx, name + 2, TRUE);
4063 break;
4064 case dest_local:
4065 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4066 break;
4067 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004068 }
4069
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004070 // Compile the expression. Temporarily hide the new local variable
4071 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004072 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004073 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004074 instr_count = instr->ga_len;
4075 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004076 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004077 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004078 ++cctx->ctx_locals.ga_len;
4079 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004080 goto theend;
4081
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004082 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004083 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004084 stack = &cctx->ctx_type_stack;
4085 stacktype = stack->ga_len == 0 ? &t_void
4086 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4087 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004088 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004089 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4090 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004091 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004092 if (stacktype->tt_type == VAR_VOID)
4093 {
4094 emsg(_("E1031: Cannot use void value"));
4095 goto theend;
4096 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004097 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004098 {
4099 // An empty list or dict has a &t_void member, for a
4100 // variable that implies &t_any.
4101 if (stacktype == &t_list_empty)
4102 lvar->lv_type = &t_list_any;
4103 else if (stacktype == &t_dict_empty)
4104 lvar->lv_type = &t_dict_any;
4105 else
4106 lvar->lv_type = stacktype;
4107 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004108 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004109 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4110 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004111 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004112 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004113 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004114 }
4115 }
4116 else if (cmdidx == CMD_const)
4117 {
4118 emsg(_("E1021: const requires a value"));
4119 goto theend;
4120 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004121 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004122 {
4123 emsg(_("E1022: type or initialization required"));
4124 goto theend;
4125 }
4126 else
4127 {
4128 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004129 if (ga_grow(instr, 1) == FAIL)
4130 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004131 switch (type->tt_type)
4132 {
4133 case VAR_BOOL:
4134 generate_PUSHBOOL(cctx, VVAL_FALSE);
4135 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004136 case VAR_FLOAT:
4137#ifdef FEAT_FLOAT
4138 generate_PUSHF(cctx, 0.0);
4139#endif
4140 break;
4141 case VAR_STRING:
4142 generate_PUSHS(cctx, NULL);
4143 break;
4144 case VAR_BLOB:
4145 generate_PUSHBLOB(cctx, NULL);
4146 break;
4147 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004148 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004149 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004150 case VAR_LIST:
4151 generate_NEWLIST(cctx, 0);
4152 break;
4153 case VAR_DICT:
4154 generate_NEWDICT(cctx, 0);
4155 break;
4156 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004157 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004158 break;
4159 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004160 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004161 break;
4162 case VAR_NUMBER:
4163 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004164 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004165 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004166 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004167 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004168 generate_PUSHNR(cctx, 0);
4169 break;
4170 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004171 }
4172
4173 if (oplen > 0 && *op != '=')
4174 {
4175 type_T *expected = &t_number;
4176 garray_T *stack = &cctx->ctx_type_stack;
4177 type_T *stacktype;
4178
4179 // TODO: if type is known use float or any operation
4180
4181 if (*op == '.')
4182 expected = &t_string;
4183 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4184 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4185 goto theend;
4186
4187 if (*op == '.')
4188 generate_instr_drop(cctx, ISN_CONCAT, 1);
4189 else
4190 {
4191 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4192
4193 if (isn == NULL)
4194 goto theend;
4195 switch (*op)
4196 {
4197 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4198 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4199 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4200 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4201 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4202 }
4203 }
4204 }
4205
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004206 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004207 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004208 case dest_option:
4209 generate_STOREOPT(cctx, name + 1, opt_flags);
4210 break;
4211 case dest_global:
4212 // include g: with the name, easier to execute that way
4213 generate_STORE(cctx, ISN_STOREG, 0, name);
4214 break;
4215 case dest_env:
4216 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4217 break;
4218 case dest_reg:
4219 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4220 break;
4221 case dest_vimvar:
4222 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4223 break;
4224 case dest_script:
4225 {
4226 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4227 imported_T *import = NULL;
4228 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004229
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004230 if (name[1] != ':')
4231 {
4232 import = find_imported(name, 0, cctx);
4233 if (import != NULL)
4234 sid = import->imp_sid;
4235 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004236
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004237 idx = get_script_item_idx(sid, rawname, TRUE);
4238 // TODO: specific type
4239 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004240 {
4241 char_u *name_s = name;
4242
4243 // Include s: in the name for store_var()
4244 if (name[1] != ':')
4245 {
4246 int len = (int)STRLEN(name) + 3;
4247
4248 name_s = alloc(len);
4249 if (name_s == NULL)
4250 name_s = name;
4251 else
4252 vim_snprintf((char *)name_s, len, "s:%s", name);
4253 }
4254 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4255 if (name_s != name)
4256 vim_free(name_s);
4257 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004258 else
4259 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4260 sid, idx, &t_any);
4261 }
4262 break;
4263 case dest_local:
4264 {
4265 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004266
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004267 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4268 // into ISN_STORENR
4269 if (instr->ga_len == instr_count + 1
4270 && isn->isn_type == ISN_PUSHNR)
4271 {
4272 varnumber_T val = isn->isn_arg.number;
4273 garray_T *stack = &cctx->ctx_type_stack;
4274
4275 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004276 isn->isn_arg.storenr.stnr_idx = idx;
4277 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004278 if (stack->ga_len > 0)
4279 --stack->ga_len;
4280 }
4281 else
4282 generate_STORE(cctx, ISN_STORE, idx, NULL);
4283 }
4284 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004285 }
4286 ret = p;
4287
4288theend:
4289 vim_free(name);
4290 return ret;
4291}
4292
4293/*
4294 * Compile an :import command.
4295 */
4296 static char_u *
4297compile_import(char_u *arg, cctx_T *cctx)
4298{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004299 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004300}
4301
4302/*
4303 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4304 */
4305 static int
4306compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4307{
4308 garray_T *instr = &cctx->ctx_instr;
4309 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4310
4311 if (endlabel == NULL)
4312 return FAIL;
4313 endlabel->el_next = *el;
4314 *el = endlabel;
4315 endlabel->el_end_label = instr->ga_len;
4316
4317 generate_JUMP(cctx, when, 0);
4318 return OK;
4319}
4320
4321 static void
4322compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4323{
4324 garray_T *instr = &cctx->ctx_instr;
4325
4326 while (*el != NULL)
4327 {
4328 endlabel_T *cur = (*el);
4329 isn_T *isn;
4330
4331 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4332 isn->isn_arg.jump.jump_where = instr->ga_len;
4333 *el = cur->el_next;
4334 vim_free(cur);
4335 }
4336}
4337
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004338 static void
4339compile_free_jump_to_end(endlabel_T **el)
4340{
4341 while (*el != NULL)
4342 {
4343 endlabel_T *cur = (*el);
4344
4345 *el = cur->el_next;
4346 vim_free(cur);
4347 }
4348}
4349
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004350/*
4351 * Create a new scope and set up the generic items.
4352 */
4353 static scope_T *
4354new_scope(cctx_T *cctx, scopetype_T type)
4355{
4356 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4357
4358 if (scope == NULL)
4359 return NULL;
4360 scope->se_outer = cctx->ctx_scope;
4361 cctx->ctx_scope = scope;
4362 scope->se_type = type;
4363 scope->se_local_count = cctx->ctx_locals.ga_len;
4364 return scope;
4365}
4366
4367/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004368 * Free the current scope and go back to the outer scope.
4369 */
4370 static void
4371drop_scope(cctx_T *cctx)
4372{
4373 scope_T *scope = cctx->ctx_scope;
4374
4375 if (scope == NULL)
4376 {
4377 iemsg("calling drop_scope() without a scope");
4378 return;
4379 }
4380 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004381 switch (scope->se_type)
4382 {
4383 case IF_SCOPE:
4384 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4385 case FOR_SCOPE:
4386 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4387 case WHILE_SCOPE:
4388 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4389 case TRY_SCOPE:
4390 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4391 case NO_SCOPE:
4392 case BLOCK_SCOPE:
4393 break;
4394 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004395 vim_free(scope);
4396}
4397
4398/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004399 * Evaluate an expression that is a constant:
4400 * has(arg)
4401 *
4402 * Also handle:
4403 * ! in front logical NOT
4404 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004405 * Return FAIL if the expression is not a constant.
4406 */
4407 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004408evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004409{
4410 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004411 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004412 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004413
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004414 /*
4415 * Skip '!' characters. They are handled later.
4416 */
4417 start_leader = *arg;
4418 while (**arg == '!')
4419 *arg = skipwhite(*arg + 1);
4420 end_leader = *arg;
4421
4422 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004423 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004424 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004425 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4426 {
4427 tv->v_type = VAR_SPECIAL;
4428 tv->vval.v_number = VVAL_TRUE;
4429 *arg += 4;
4430 return OK;
4431 }
4432 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4433 {
4434 tv->v_type = VAR_SPECIAL;
4435 tv->vval.v_number = VVAL_FALSE;
4436 *arg += 5;
4437 return OK;
4438 }
4439
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004440 if (STRNCMP("has(", *arg, 4) == 0)
4441 {
4442 has_call = TRUE;
4443 *arg = skipwhite(*arg + 4);
4444 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004445
4446 if (**arg == '"')
4447 {
4448 if (get_string_tv(arg, tv, TRUE) == FAIL)
4449 return FAIL;
4450 }
4451 else if (**arg == '\'')
4452 {
4453 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4454 return FAIL;
4455 }
4456 else
4457 return FAIL;
4458
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004459 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004460 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004461 *arg = skipwhite(*arg);
4462 if (**arg != ')')
4463 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004464 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004465
4466 argvars[0] = *tv;
4467 argvars[1].v_type = VAR_UNKNOWN;
4468 tv->v_type = VAR_NUMBER;
4469 tv->vval.v_number = 0;
4470 f_has(argvars, tv);
4471 clear_tv(&argvars[0]);
4472
4473 while (start_leader < end_leader)
4474 {
4475 if (*start_leader == '!')
4476 tv->vval.v_number = !tv->vval.v_number;
4477 ++start_leader;
4478 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004479 }
4480
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004481 return OK;
4482}
4483
Bram Moolenaar080457c2020-03-03 21:53:32 +01004484 static int
4485evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4486{
4487 exptype_T type = EXPR_UNKNOWN;
4488 char_u *p;
4489 int len = 2;
4490 int type_is = FALSE;
4491
4492 // get the first variable
4493 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4494 return FAIL;
4495
4496 p = skipwhite(*arg);
4497 type = get_compare_type(p, &len, &type_is);
4498
4499 /*
4500 * If there is a comparative operator, use it.
4501 */
4502 if (type != EXPR_UNKNOWN)
4503 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004504 typval_T tv2;
4505 char_u *s1, *s2;
4506 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4507 int n;
4508
4509 // TODO: Only string == string is supported now
4510 if (tv->v_type != VAR_STRING)
4511 return FAIL;
4512 if (type != EXPR_EQUAL)
4513 return FAIL;
4514
4515 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004516 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004517 *arg = skipwhite(p + len);
4518 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4519 || tv2.v_type != VAR_STRING)
4520 {
4521 clear_tv(&tv2);
4522 return FAIL;
4523 }
4524 s1 = tv_get_string_buf(tv, buf1);
4525 s2 = tv_get_string_buf(&tv2, buf2);
4526 n = STRCMP(s1, s2);
4527 clear_tv(tv);
4528 clear_tv(&tv2);
4529 tv->v_type = VAR_BOOL;
4530 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004531 }
4532
4533 return OK;
4534}
4535
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004536static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4537
4538/*
4539 * Compile constant || or &&.
4540 */
4541 static int
4542evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4543{
4544 char_u *p = skipwhite(*arg);
4545 int opchar = *op;
4546
4547 if (p[0] == opchar && p[1] == opchar)
4548 {
4549 int val = tv2bool(tv);
4550
4551 /*
4552 * Repeat until there is no following "||" or "&&"
4553 */
4554 while (p[0] == opchar && p[1] == opchar)
4555 {
4556 typval_T tv2;
4557
4558 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4559 return FAIL;
4560
4561 // eval the next expression
4562 *arg = skipwhite(p + 2);
4563 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004564 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004565 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004566 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004567 {
4568 clear_tv(&tv2);
4569 return FAIL;
4570 }
4571 if ((opchar == '&') == val)
4572 {
4573 // false || tv2 or true && tv2: use tv2
4574 clear_tv(tv);
4575 *tv = tv2;
4576 val = tv2bool(tv);
4577 }
4578 else
4579 clear_tv(&tv2);
4580 p = skipwhite(*arg);
4581 }
4582 }
4583
4584 return OK;
4585}
4586
4587/*
4588 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4589 * Return FAIL if the expression is not a constant.
4590 */
4591 static int
4592evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4593{
4594 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004595 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004596 return FAIL;
4597
4598 // || and && work almost the same
4599 return evaluate_const_and_or(arg, cctx, "&&", tv);
4600}
4601
4602/*
4603 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4604 * Return FAIL if the expression is not a constant.
4605 */
4606 static int
4607evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4608{
4609 // evaluate the first expression
4610 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4611 return FAIL;
4612
4613 // || and && work almost the same
4614 return evaluate_const_and_or(arg, cctx, "||", tv);
4615}
4616
4617/*
4618 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4619 * E.g. for "has('feature')".
4620 * This does not produce error messages. "tv" should be cleared afterwards.
4621 * Return FAIL if the expression is not a constant.
4622 */
4623 static int
4624evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4625{
4626 char_u *p;
4627
4628 // evaluate the first expression
4629 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4630 return FAIL;
4631
4632 p = skipwhite(*arg);
4633 if (*p == '?')
4634 {
4635 int val = tv2bool(tv);
4636 typval_T tv2;
4637
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004638 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004639 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4640 return FAIL;
4641
4642 // evaluate the second expression; any type is accepted
4643 clear_tv(tv);
4644 *arg = skipwhite(p + 1);
4645 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
4646 return FAIL;
4647
4648 // Check for the ":".
4649 p = skipwhite(*arg);
4650 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4651 return FAIL;
4652
4653 // evaluate the third expression
4654 *arg = skipwhite(p + 1);
4655 tv2.v_type = VAR_UNKNOWN;
4656 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
4657 {
4658 clear_tv(&tv2);
4659 return FAIL;
4660 }
4661 if (val)
4662 {
4663 // use the expr after "?"
4664 clear_tv(&tv2);
4665 }
4666 else
4667 {
4668 // use the expr after ":"
4669 clear_tv(tv);
4670 *tv = tv2;
4671 }
4672 }
4673 return OK;
4674}
4675
4676/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004677 * compile "if expr"
4678 *
4679 * "if expr" Produces instructions:
4680 * EVAL expr Push result of "expr"
4681 * JUMP_IF_FALSE end
4682 * ... body ...
4683 * end:
4684 *
4685 * "if expr | else" Produces instructions:
4686 * EVAL expr Push result of "expr"
4687 * JUMP_IF_FALSE else
4688 * ... body ...
4689 * JUMP_ALWAYS end
4690 * else:
4691 * ... body ...
4692 * end:
4693 *
4694 * "if expr1 | elseif expr2 | else" Produces instructions:
4695 * EVAL expr Push result of "expr"
4696 * JUMP_IF_FALSE elseif
4697 * ... body ...
4698 * JUMP_ALWAYS end
4699 * elseif:
4700 * EVAL expr Push result of "expr"
4701 * JUMP_IF_FALSE else
4702 * ... body ...
4703 * JUMP_ALWAYS end
4704 * else:
4705 * ... body ...
4706 * end:
4707 */
4708 static char_u *
4709compile_if(char_u *arg, cctx_T *cctx)
4710{
4711 char_u *p = arg;
4712 garray_T *instr = &cctx->ctx_instr;
4713 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004714 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004715
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004716 // compile "expr"; if we know it evaluates to FALSE skip the block
4717 tv.v_type = VAR_UNKNOWN;
4718 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4719 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4720 else
4721 cctx->ctx_skip = MAYBE;
4722 clear_tv(&tv);
4723 if (cctx->ctx_skip == MAYBE)
4724 {
4725 p = arg;
4726 if (compile_expr1(&p, cctx) == FAIL)
4727 return NULL;
4728 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004729
4730 scope = new_scope(cctx, IF_SCOPE);
4731 if (scope == NULL)
4732 return NULL;
4733
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004734 if (cctx->ctx_skip == MAYBE)
4735 {
4736 // "where" is set when ":elseif", "else" or ":endif" is found
4737 scope->se_u.se_if.is_if_label = instr->ga_len;
4738 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4739 }
4740 else
4741 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004742
4743 return p;
4744}
4745
4746 static char_u *
4747compile_elseif(char_u *arg, cctx_T *cctx)
4748{
4749 char_u *p = arg;
4750 garray_T *instr = &cctx->ctx_instr;
4751 isn_T *isn;
4752 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004753 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004754
4755 if (scope == NULL || scope->se_type != IF_SCOPE)
4756 {
4757 emsg(_(e_elseif_without_if));
4758 return NULL;
4759 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004760 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004761
Bram Moolenaar158906c2020-02-06 20:39:45 +01004762 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004763 {
4764 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004765 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004766 return NULL;
4767 // previous "if" or "elseif" jumps here
4768 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4769 isn->isn_arg.jump.jump_where = instr->ga_len;
4770 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004771
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004772 // compile "expr"; if we know it evaluates to FALSE skip the block
4773 tv.v_type = VAR_UNKNOWN;
4774 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4775 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4776 else
4777 cctx->ctx_skip = MAYBE;
4778 clear_tv(&tv);
4779 if (cctx->ctx_skip == MAYBE)
4780 {
4781 p = arg;
4782 if (compile_expr1(&p, cctx) == FAIL)
4783 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004784
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004785 // "where" is set when ":elseif", "else" or ":endif" is found
4786 scope->se_u.se_if.is_if_label = instr->ga_len;
4787 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4788 }
4789 else
4790 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004791
4792 return p;
4793}
4794
4795 static char_u *
4796compile_else(char_u *arg, cctx_T *cctx)
4797{
4798 char_u *p = arg;
4799 garray_T *instr = &cctx->ctx_instr;
4800 isn_T *isn;
4801 scope_T *scope = cctx->ctx_scope;
4802
4803 if (scope == NULL || scope->se_type != IF_SCOPE)
4804 {
4805 emsg(_(e_else_without_if));
4806 return NULL;
4807 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004808 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004809
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004810 // jump from previous block to the end, unless the else block is empty
4811 if (cctx->ctx_skip == MAYBE)
4812 {
4813 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004814 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004815 return NULL;
4816 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004817
Bram Moolenaar158906c2020-02-06 20:39:45 +01004818 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004819 {
4820 if (scope->se_u.se_if.is_if_label >= 0)
4821 {
4822 // previous "if" or "elseif" jumps here
4823 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4824 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01004825 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004826 }
4827 }
4828
4829 if (cctx->ctx_skip != MAYBE)
4830 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004831
4832 return p;
4833}
4834
4835 static char_u *
4836compile_endif(char_u *arg, cctx_T *cctx)
4837{
4838 scope_T *scope = cctx->ctx_scope;
4839 ifscope_T *ifscope;
4840 garray_T *instr = &cctx->ctx_instr;
4841 isn_T *isn;
4842
4843 if (scope == NULL || scope->se_type != IF_SCOPE)
4844 {
4845 emsg(_(e_endif_without_if));
4846 return NULL;
4847 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004848 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004849 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004850
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004851 if (scope->se_u.se_if.is_if_label >= 0)
4852 {
4853 // previous "if" or "elseif" jumps here
4854 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4855 isn->isn_arg.jump.jump_where = instr->ga_len;
4856 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004857 // Fill in the "end" label in jumps at the end of the blocks.
4858 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004859 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004860
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004861 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004862 return arg;
4863}
4864
4865/*
4866 * compile "for var in expr"
4867 *
4868 * Produces instructions:
4869 * PUSHNR -1
4870 * STORE loop-idx Set index to -1
4871 * EVAL expr Push result of "expr"
4872 * top: FOR loop-idx, end Increment index, use list on bottom of stack
4873 * - if beyond end, jump to "end"
4874 * - otherwise get item from list and push it
4875 * STORE var Store item in "var"
4876 * ... body ...
4877 * JUMP top Jump back to repeat
4878 * end: DROP Drop the result of "expr"
4879 *
4880 */
4881 static char_u *
4882compile_for(char_u *arg, cctx_T *cctx)
4883{
4884 char_u *p;
4885 size_t varlen;
4886 garray_T *instr = &cctx->ctx_instr;
4887 garray_T *stack = &cctx->ctx_type_stack;
4888 scope_T *scope;
4889 int loop_idx; // index of loop iteration variable
4890 int var_idx; // index of "var"
4891 type_T *vartype;
4892
4893 // TODO: list of variables: "for [key, value] in dict"
4894 // parse "var"
4895 for (p = arg; eval_isnamec1(*p); ++p)
4896 ;
4897 varlen = p - arg;
4898 var_idx = lookup_local(arg, varlen, cctx);
4899 if (var_idx >= 0)
4900 {
4901 semsg(_("E1023: variable already defined: %s"), arg);
4902 return NULL;
4903 }
4904
4905 // consume "in"
4906 p = skipwhite(p);
4907 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
4908 {
4909 emsg(_(e_missing_in));
4910 return NULL;
4911 }
4912 p = skipwhite(p + 2);
4913
4914
4915 scope = new_scope(cctx, FOR_SCOPE);
4916 if (scope == NULL)
4917 return NULL;
4918
4919 // Reserve a variable to store the loop iteration counter.
4920 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
4921 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004922 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004923 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004924 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004925 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004926 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004927
4928 // Reserve a variable to store "var"
4929 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
4930 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004931 {
4932 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004933 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004934 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004935
4936 generate_STORENR(cctx, loop_idx, -1);
4937
4938 // compile "expr", it remains on the stack until "endfor"
4939 arg = p;
4940 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004941 {
4942 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004943 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004944 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004945
4946 // now we know the type of "var"
4947 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4948 if (vartype->tt_type != VAR_LIST)
4949 {
4950 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004951 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004952 return NULL;
4953 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02004954 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004955 {
4956 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
4957
4958 lvar->lv_type = vartype->tt_member;
4959 }
4960
4961 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004962 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004963
4964 generate_FOR(cctx, loop_idx);
4965 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
4966
4967 return arg;
4968}
4969
4970/*
4971 * compile "endfor"
4972 */
4973 static char_u *
4974compile_endfor(char_u *arg, cctx_T *cctx)
4975{
4976 garray_T *instr = &cctx->ctx_instr;
4977 scope_T *scope = cctx->ctx_scope;
4978 forscope_T *forscope;
4979 isn_T *isn;
4980
4981 if (scope == NULL || scope->se_type != FOR_SCOPE)
4982 {
4983 emsg(_(e_for));
4984 return NULL;
4985 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004986 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004987 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004988 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004989
4990 // At end of ":for" scope jump back to the FOR instruction.
4991 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
4992
4993 // Fill in the "end" label in the FOR statement so it can jump here
4994 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
4995 isn->isn_arg.forloop.for_end = instr->ga_len;
4996
4997 // Fill in the "end" label any BREAK statements
4998 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
4999
5000 // Below the ":for" scope drop the "expr" list from the stack.
5001 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5002 return NULL;
5003
5004 vim_free(scope);
5005
5006 return arg;
5007}
5008
5009/*
5010 * compile "while expr"
5011 *
5012 * Produces instructions:
5013 * top: EVAL expr Push result of "expr"
5014 * JUMP_IF_FALSE end jump if false
5015 * ... body ...
5016 * JUMP top Jump back to repeat
5017 * end:
5018 *
5019 */
5020 static char_u *
5021compile_while(char_u *arg, cctx_T *cctx)
5022{
5023 char_u *p = arg;
5024 garray_T *instr = &cctx->ctx_instr;
5025 scope_T *scope;
5026
5027 scope = new_scope(cctx, WHILE_SCOPE);
5028 if (scope == NULL)
5029 return NULL;
5030
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005031 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005032
5033 // compile "expr"
5034 if (compile_expr1(&p, cctx) == FAIL)
5035 return NULL;
5036
5037 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005038 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005039 JUMP_IF_FALSE, cctx) == FAIL)
5040 return FAIL;
5041
5042 return p;
5043}
5044
5045/*
5046 * compile "endwhile"
5047 */
5048 static char_u *
5049compile_endwhile(char_u *arg, cctx_T *cctx)
5050{
5051 scope_T *scope = cctx->ctx_scope;
5052
5053 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5054 {
5055 emsg(_(e_while));
5056 return NULL;
5057 }
5058 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005059 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005060
5061 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005062 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005063
5064 // Fill in the "end" label in the WHILE statement so it can jump here.
5065 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005066 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005067
5068 vim_free(scope);
5069
5070 return arg;
5071}
5072
5073/*
5074 * compile "continue"
5075 */
5076 static char_u *
5077compile_continue(char_u *arg, cctx_T *cctx)
5078{
5079 scope_T *scope = cctx->ctx_scope;
5080
5081 for (;;)
5082 {
5083 if (scope == NULL)
5084 {
5085 emsg(_(e_continue));
5086 return NULL;
5087 }
5088 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5089 break;
5090 scope = scope->se_outer;
5091 }
5092
5093 // Jump back to the FOR or WHILE instruction.
5094 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005095 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5096 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005097 return arg;
5098}
5099
5100/*
5101 * compile "break"
5102 */
5103 static char_u *
5104compile_break(char_u *arg, cctx_T *cctx)
5105{
5106 scope_T *scope = cctx->ctx_scope;
5107 endlabel_T **el;
5108
5109 for (;;)
5110 {
5111 if (scope == NULL)
5112 {
5113 emsg(_(e_break));
5114 return NULL;
5115 }
5116 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5117 break;
5118 scope = scope->se_outer;
5119 }
5120
5121 // Jump to the end of the FOR or WHILE loop.
5122 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005123 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005124 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005125 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005126 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5127 return FAIL;
5128
5129 return arg;
5130}
5131
5132/*
5133 * compile "{" start of block
5134 */
5135 static char_u *
5136compile_block(char_u *arg, cctx_T *cctx)
5137{
5138 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5139 return NULL;
5140 return skipwhite(arg + 1);
5141}
5142
5143/*
5144 * compile end of block: drop one scope
5145 */
5146 static void
5147compile_endblock(cctx_T *cctx)
5148{
5149 scope_T *scope = cctx->ctx_scope;
5150
5151 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005152 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005153 vim_free(scope);
5154}
5155
5156/*
5157 * compile "try"
5158 * Creates a new scope for the try-endtry, pointing to the first catch and
5159 * finally.
5160 * Creates another scope for the "try" block itself.
5161 * TRY instruction sets up exception handling at runtime.
5162 *
5163 * "try"
5164 * TRY -> catch1, -> finally push trystack entry
5165 * ... try block
5166 * "throw {exception}"
5167 * EVAL {exception}
5168 * THROW create exception
5169 * ... try block
5170 * " catch {expr}"
5171 * JUMP -> finally
5172 * catch1: PUSH exeception
5173 * EVAL {expr}
5174 * MATCH
5175 * JUMP nomatch -> catch2
5176 * CATCH remove exception
5177 * ... catch block
5178 * " catch"
5179 * JUMP -> finally
5180 * catch2: CATCH remove exception
5181 * ... catch block
5182 * " finally"
5183 * finally:
5184 * ... finally block
5185 * " endtry"
5186 * ENDTRY pop trystack entry, may rethrow
5187 */
5188 static char_u *
5189compile_try(char_u *arg, cctx_T *cctx)
5190{
5191 garray_T *instr = &cctx->ctx_instr;
5192 scope_T *try_scope;
5193 scope_T *scope;
5194
5195 // scope that holds the jumps that go to catch/finally/endtry
5196 try_scope = new_scope(cctx, TRY_SCOPE);
5197 if (try_scope == NULL)
5198 return NULL;
5199
5200 // "catch" is set when the first ":catch" is found.
5201 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005202 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005203 if (generate_instr(cctx, ISN_TRY) == NULL)
5204 return NULL;
5205
5206 // scope for the try block itself
5207 scope = new_scope(cctx, BLOCK_SCOPE);
5208 if (scope == NULL)
5209 return NULL;
5210
5211 return arg;
5212}
5213
5214/*
5215 * compile "catch {expr}"
5216 */
5217 static char_u *
5218compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5219{
5220 scope_T *scope = cctx->ctx_scope;
5221 garray_T *instr = &cctx->ctx_instr;
5222 char_u *p;
5223 isn_T *isn;
5224
5225 // end block scope from :try or :catch
5226 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5227 compile_endblock(cctx);
5228 scope = cctx->ctx_scope;
5229
5230 // Error if not in a :try scope
5231 if (scope == NULL || scope->se_type != TRY_SCOPE)
5232 {
5233 emsg(_(e_catch));
5234 return NULL;
5235 }
5236
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005237 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005238 {
5239 emsg(_("E1033: catch unreachable after catch-all"));
5240 return NULL;
5241 }
5242
5243 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005244 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005245 JUMP_ALWAYS, cctx) == FAIL)
5246 return NULL;
5247
5248 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005249 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005250 if (isn->isn_arg.try.try_catch == 0)
5251 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005252 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005253 {
5254 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005255 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005256 isn->isn_arg.jump.jump_where = instr->ga_len;
5257 }
5258
5259 p = skipwhite(arg);
5260 if (ends_excmd(*p))
5261 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005262 scope->se_u.se_try.ts_caught_all = TRUE;
5263 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005264 }
5265 else
5266 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005267 char_u *end;
5268 char_u *pat;
5269 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005270 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005271 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005272
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005273 // Push v:exception, push {expr} and MATCH
5274 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5275
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005276 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005277 if (*end != *p)
5278 {
5279 semsg(_("E1067: Separator mismatch: %s"), p);
5280 vim_free(tofree);
5281 return FAIL;
5282 }
5283 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005284 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005285 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005286 len = (int)(end - tofree);
5287 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005288 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005289 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005290 if (pat == NULL)
5291 return FAIL;
5292 if (generate_PUSHS(cctx, pat) == FAIL)
5293 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005294
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005295 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5296 return NULL;
5297
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005298 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005299 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5300 return NULL;
5301 }
5302
5303 if (generate_instr(cctx, ISN_CATCH) == NULL)
5304 return NULL;
5305
5306 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5307 return NULL;
5308 return p;
5309}
5310
5311 static char_u *
5312compile_finally(char_u *arg, cctx_T *cctx)
5313{
5314 scope_T *scope = cctx->ctx_scope;
5315 garray_T *instr = &cctx->ctx_instr;
5316 isn_T *isn;
5317
5318 // end block scope from :try or :catch
5319 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5320 compile_endblock(cctx);
5321 scope = cctx->ctx_scope;
5322
5323 // Error if not in a :try scope
5324 if (scope == NULL || scope->se_type != TRY_SCOPE)
5325 {
5326 emsg(_(e_finally));
5327 return NULL;
5328 }
5329
5330 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005331 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005332 if (isn->isn_arg.try.try_finally != 0)
5333 {
5334 emsg(_(e_finally_dup));
5335 return NULL;
5336 }
5337
5338 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005339 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005340
Bram Moolenaar585fea72020-04-02 22:33:21 +02005341 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005342 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005343 {
5344 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005345 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005346 isn->isn_arg.jump.jump_where = instr->ga_len;
5347 }
5348
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005349 // TODO: set index in ts_finally_label jumps
5350
5351 return arg;
5352}
5353
5354 static char_u *
5355compile_endtry(char_u *arg, cctx_T *cctx)
5356{
5357 scope_T *scope = cctx->ctx_scope;
5358 garray_T *instr = &cctx->ctx_instr;
5359 isn_T *isn;
5360
5361 // end block scope from :catch or :finally
5362 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5363 compile_endblock(cctx);
5364 scope = cctx->ctx_scope;
5365
5366 // Error if not in a :try scope
5367 if (scope == NULL || scope->se_type != TRY_SCOPE)
5368 {
5369 if (scope == NULL)
5370 emsg(_(e_no_endtry));
5371 else if (scope->se_type == WHILE_SCOPE)
5372 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005373 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005374 emsg(_(e_endfor));
5375 else
5376 emsg(_(e_endif));
5377 return NULL;
5378 }
5379
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005380 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005381 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5382 {
5383 emsg(_("E1032: missing :catch or :finally"));
5384 return NULL;
5385 }
5386
5387 // Fill in the "end" label in jumps at the end of the blocks, if not done
5388 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005389 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005390
5391 // End :catch or :finally scope: set value in ISN_TRY instruction
5392 if (isn->isn_arg.try.try_finally == 0)
5393 isn->isn_arg.try.try_finally = instr->ga_len;
5394 compile_endblock(cctx);
5395
5396 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5397 return NULL;
5398 return arg;
5399}
5400
5401/*
5402 * compile "throw {expr}"
5403 */
5404 static char_u *
5405compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5406{
5407 char_u *p = skipwhite(arg);
5408
5409 if (ends_excmd(*p))
5410 {
5411 emsg(_(e_argreq));
5412 return NULL;
5413 }
5414 if (compile_expr1(&p, cctx) == FAIL)
5415 return NULL;
5416 if (may_generate_2STRING(-1, cctx) == FAIL)
5417 return NULL;
5418 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5419 return NULL;
5420
5421 return p;
5422}
5423
5424/*
5425 * compile "echo expr"
5426 */
5427 static char_u *
5428compile_echo(char_u *arg, int with_white, cctx_T *cctx)
5429{
5430 char_u *p = arg;
5431 int count = 0;
5432
Bram Moolenaarad39c092020-02-26 18:23:43 +01005433 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005434 {
5435 if (compile_expr1(&p, cctx) == FAIL)
5436 return NULL;
5437 ++count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005438 p = skipwhite(p);
5439 if (ends_excmd(*p))
5440 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005441 }
5442
5443 generate_ECHO(cctx, with_white, count);
Bram Moolenaarad39c092020-02-26 18:23:43 +01005444 return p;
5445}
5446
5447/*
5448 * compile "execute expr"
5449 */
5450 static char_u *
5451compile_execute(char_u *arg, cctx_T *cctx)
5452{
5453 char_u *p = arg;
5454 int count = 0;
5455
5456 for (;;)
5457 {
5458 if (compile_expr1(&p, cctx) == FAIL)
5459 return NULL;
5460 ++count;
5461 p = skipwhite(p);
5462 if (ends_excmd(*p))
5463 break;
5464 }
5465
5466 generate_EXECUTE(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005467
5468 return p;
5469}
5470
5471/*
5472 * After ex_function() has collected all the function lines: parse and compile
5473 * the lines into instructions.
5474 * Adds the function to "def_functions".
5475 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5476 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005477 * This can be used recursively through compile_lambda(), which may reallocate
5478 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005479 */
5480 void
5481compile_def_function(ufunc_T *ufunc, int set_return_type)
5482{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005483 char_u *line = NULL;
5484 char_u *p;
5485 exarg_T ea;
5486 char *errormsg = NULL; // error message
5487 int had_return = FALSE;
5488 cctx_T cctx;
5489 garray_T *instr;
5490 int called_emsg_before = called_emsg;
5491 int ret = FAIL;
5492 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005493 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005494
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005495 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005496 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005497
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005498 if (ufunc->uf_dfunc_idx >= 0)
5499 {
5500 // Redefining a function that was compiled before.
5501 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5502
5503 // Free old instructions.
5504 delete_def_function_contents(dfunc);
5505 }
5506 else
5507 {
5508 // Add the function to "def_functions".
5509 if (ga_grow(&def_functions, 1) == FAIL)
5510 return;
5511 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
5512 vim_memset(dfunc, 0, sizeof(dfunc_T));
5513 dfunc->df_idx = def_functions.ga_len;
5514 ufunc->uf_dfunc_idx = dfunc->df_idx;
5515 dfunc->df_ufunc = ufunc;
5516 ++def_functions.ga_len;
5517 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005518 }
5519
5520 vim_memset(&cctx, 0, sizeof(cctx));
5521 cctx.ctx_ufunc = ufunc;
5522 cctx.ctx_lnum = -1;
5523 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5524 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5525 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5526 cctx.ctx_type_list = &ufunc->uf_type_list;
5527 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5528 instr = &cctx.ctx_instr;
5529
5530 // Most modern script version.
5531 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5532
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005533 if (ufunc->uf_def_args.ga_len > 0)
5534 {
5535 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005536 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005537 int i;
5538 char_u *arg;
5539 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5540
5541 // Produce instructions for the default values of optional arguments.
5542 // Store the instruction index in uf_def_arg_idx[] so that we know
5543 // where to start when the function is called, depending on the number
5544 // of arguments.
5545 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5546 if (ufunc->uf_def_arg_idx == NULL)
5547 goto erret;
5548 for (i = 0; i < count; ++i)
5549 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005550 garray_T *stack = &cctx.ctx_type_stack;
5551 type_T *val_type;
5552 int arg_idx = first_def_arg + i;
5553
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005554 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5555 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005556 if (compile_expr1(&arg, &cctx) == FAIL)
5557 goto erret;
5558
5559 // If no type specified use the type of the default value.
5560 // Otherwise check that the default value type matches the
5561 // specified type.
5562 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5563 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
5564 ufunc->uf_arg_types[arg_idx] = val_type;
5565 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
5566 == FAIL)
5567 {
5568 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
5569 arg_idx + 1);
5570 goto erret;
5571 }
5572
5573 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005574 goto erret;
5575 }
5576
5577 // If a varargs is following, push an empty list.
5578 if (ufunc->uf_va_name != NULL)
5579 {
5580 if (generate_NEWLIST(&cctx, 0) == FAIL
5581 || generate_STORE(&cctx, ISN_STORE, -off, NULL) == FAIL)
5582 goto erret;
5583 }
5584
5585 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5586 }
5587
5588 /*
5589 * Loop over all the lines of the function and generate instructions.
5590 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005591 for (;;)
5592 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005593 int is_ex_command;
5594
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005595 // Bail out on the first error to avoid a flood of errors and report
5596 // the right line number when inside try/catch.
5597 if (emsg_before != called_emsg)
5598 goto erret;
5599
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005600 if (line != NULL && *line == '|')
5601 // the line continues after a '|'
5602 ++line;
5603 else if (line != NULL && *line != NUL)
5604 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005605 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005606 goto erret;
5607 }
5608 else
5609 {
5610 do
5611 {
5612 ++cctx.ctx_lnum;
5613 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
5614 break;
5615 line = ((char_u **)ufunc->uf_lines.ga_data)[cctx.ctx_lnum];
5616 } while (line == NULL);
5617 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
5618 break;
5619 SOURCING_LNUM = ufunc->uf_script_ctx.sc_lnum + cctx.ctx_lnum + 1;
5620 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005621 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005622
5623 had_return = FALSE;
5624 vim_memset(&ea, 0, sizeof(ea));
5625 ea.cmdlinep = &line;
5626 ea.cmd = skipwhite(line);
5627
5628 // "}" ends a block scope
5629 if (*ea.cmd == '}')
5630 {
5631 scopetype_T stype = cctx.ctx_scope == NULL
5632 ? NO_SCOPE : cctx.ctx_scope->se_type;
5633
5634 if (stype == BLOCK_SCOPE)
5635 {
5636 compile_endblock(&cctx);
5637 line = ea.cmd;
5638 }
5639 else
5640 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005641 emsg(_("E1025: using } outside of a block scope"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005642 goto erret;
5643 }
5644 if (line != NULL)
5645 line = skipwhite(ea.cmd + 1);
5646 continue;
5647 }
5648
5649 // "{" starts a block scope
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01005650 // "{'a': 1}->func() is something else
5651 if (*ea.cmd == '{' && ends_excmd(*skipwhite(ea.cmd + 1)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005652 {
5653 line = compile_block(ea.cmd, &cctx);
5654 continue;
5655 }
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005656 is_ex_command = *ea.cmd == ':';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005657
5658 /*
5659 * COMMAND MODIFIERS
5660 */
5661 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
5662 {
5663 if (errormsg != NULL)
5664 goto erret;
5665 // empty line or comment
5666 line = (char_u *)"";
5667 continue;
5668 }
5669
5670 // Skip ":call" to get to the function name.
5671 if (checkforcmd(&ea.cmd, "call", 3))
5672 ea.cmd = skipwhite(ea.cmd);
5673
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005674 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005675 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005676 // Assuming the command starts with a variable or function name,
5677 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
5678 // val".
5679 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
5680 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005681 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02005682 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005683 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005684 int oplen;
5685 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005686
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005687 oplen = assignment_len(skipwhite(p), &heredoc);
5688 if (oplen > 0)
5689 {
5690 // Recognize an assignment if we recognize the variable
5691 // name:
5692 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005693 // "local = expr" where "local" is a local var.
5694 // "script = expr" where "script" is a script-local var.
5695 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005696 // "&opt = expr"
5697 // "$ENV = expr"
5698 // "@r = expr"
5699 if (*ea.cmd == '&'
5700 || *ea.cmd == '$'
5701 || *ea.cmd == '@'
5702 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
5703 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
5704 || lookup_script(ea.cmd, p - ea.cmd) == OK
5705 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
5706 {
5707 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
5708 if (line == NULL)
5709 goto erret;
5710 continue;
5711 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005712 }
5713 }
5714 }
5715
5716 /*
5717 * COMMAND after range
5718 */
5719 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005720 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
5721 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005722
5723 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
5724 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005725 if (cctx.ctx_skip == TRUE)
5726 {
5727 line += STRLEN(line);
5728 continue;
5729 }
5730
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005731 // Expression or function call.
5732 if (ea.cmdidx == CMD_eval)
5733 {
5734 p = ea.cmd;
5735 if (compile_expr1(&p, &cctx) == FAIL)
5736 goto erret;
5737
5738 // drop the return value
5739 generate_instr_drop(&cctx, ISN_DROP, 1);
5740 line = p;
5741 continue;
5742 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02005743 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005744 iemsg("Command from find_ex_command() not handled");
5745 goto erret;
5746 }
5747
5748 p = skipwhite(p);
5749
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005750 if (cctx.ctx_skip == TRUE
5751 && ea.cmdidx != CMD_elseif
5752 && ea.cmdidx != CMD_else
5753 && ea.cmdidx != CMD_endif)
5754 {
5755 line += STRLEN(line);
5756 continue;
5757 }
5758
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005759 switch (ea.cmdidx)
5760 {
5761 case CMD_def:
5762 case CMD_function:
5763 // TODO: Nested function
5764 emsg("Nested function not implemented yet");
5765 goto erret;
5766
5767 case CMD_return:
5768 line = compile_return(p, set_return_type, &cctx);
5769 had_return = TRUE;
5770 break;
5771
5772 case CMD_let:
5773 case CMD_const:
5774 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
5775 break;
5776
5777 case CMD_import:
5778 line = compile_import(p, &cctx);
5779 break;
5780
5781 case CMD_if:
5782 line = compile_if(p, &cctx);
5783 break;
5784 case CMD_elseif:
5785 line = compile_elseif(p, &cctx);
5786 break;
5787 case CMD_else:
5788 line = compile_else(p, &cctx);
5789 break;
5790 case CMD_endif:
5791 line = compile_endif(p, &cctx);
5792 break;
5793
5794 case CMD_while:
5795 line = compile_while(p, &cctx);
5796 break;
5797 case CMD_endwhile:
5798 line = compile_endwhile(p, &cctx);
5799 break;
5800
5801 case CMD_for:
5802 line = compile_for(p, &cctx);
5803 break;
5804 case CMD_endfor:
5805 line = compile_endfor(p, &cctx);
5806 break;
5807 case CMD_continue:
5808 line = compile_continue(p, &cctx);
5809 break;
5810 case CMD_break:
5811 line = compile_break(p, &cctx);
5812 break;
5813
5814 case CMD_try:
5815 line = compile_try(p, &cctx);
5816 break;
5817 case CMD_catch:
5818 line = compile_catch(p, &cctx);
5819 break;
5820 case CMD_finally:
5821 line = compile_finally(p, &cctx);
5822 break;
5823 case CMD_endtry:
5824 line = compile_endtry(p, &cctx);
5825 break;
5826 case CMD_throw:
5827 line = compile_throw(p, &cctx);
5828 break;
5829
5830 case CMD_echo:
5831 line = compile_echo(p, TRUE, &cctx);
5832 break;
5833 case CMD_echon:
5834 line = compile_echo(p, FALSE, &cctx);
5835 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005836 case CMD_execute:
5837 line = compile_execute(p, &cctx);
5838 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005839
5840 default:
5841 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01005842 // TODO:
5843 // CMD_echomsg
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01005844 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005845 generate_EXEC(&cctx, line);
5846 line = (char_u *)"";
5847 break;
5848 }
5849 if (line == NULL)
5850 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02005851 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005852
5853 if (cctx.ctx_type_stack.ga_len < 0)
5854 {
5855 iemsg("Type stack underflow");
5856 goto erret;
5857 }
5858 }
5859
5860 if (cctx.ctx_scope != NULL)
5861 {
5862 if (cctx.ctx_scope->se_type == IF_SCOPE)
5863 emsg(_(e_endif));
5864 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
5865 emsg(_(e_endwhile));
5866 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
5867 emsg(_(e_endfor));
5868 else
5869 emsg(_("E1026: Missing }"));
5870 goto erret;
5871 }
5872
5873 if (!had_return)
5874 {
5875 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
5876 {
5877 emsg(_("E1027: Missing return statement"));
5878 goto erret;
5879 }
5880
5881 // Return zero if there is no return at the end.
5882 generate_PUSHNR(&cctx, 0);
5883 generate_instr(&cctx, ISN_RETURN);
5884 }
5885
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005886 {
5887 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5888 + ufunc->uf_dfunc_idx;
5889 dfunc->df_deleted = FALSE;
5890 dfunc->df_instr = instr->ga_data;
5891 dfunc->df_instr_count = instr->ga_len;
5892 dfunc->df_varcount = cctx.ctx_max_local;
5893 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005894
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005895 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02005896 int varargs = ufunc->uf_va_name != NULL;
5897 int argcount = ufunc->uf_args.ga_len - (varargs ? 1 : 0);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005898
5899 // Create a type for the function, with the return type and any
5900 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02005901 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
5902 // The type is included in "tt_args".
5903 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
5904 ufunc->uf_args.ga_len, &ufunc->uf_type_list);
5905 if (ufunc->uf_args.ga_len > 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005906 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02005907 if (func_type_add_arg_types(ufunc->uf_func_type,
5908 ufunc->uf_args.ga_len,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005909 argcount - ufunc->uf_def_args.ga_len,
5910 &ufunc->uf_type_list) == FAIL)
5911 {
5912 ret = FAIL;
5913 goto erret;
5914 }
5915 if (ufunc->uf_arg_types == NULL)
5916 {
5917 int i;
5918
5919 // lambda does not have argument types.
5920 for (i = 0; i < argcount; ++i)
5921 ufunc->uf_func_type->tt_args[i] = &t_any;
5922 }
5923 else
5924 mch_memmove(ufunc->uf_func_type->tt_args,
5925 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02005926 if (varargs)
5927 ufunc->uf_func_type->tt_args[argcount] =
5928 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005929 }
5930 }
5931
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005932 ret = OK;
5933
5934erret:
5935 if (ret == FAIL)
5936 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01005937 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005938 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5939 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005940
5941 for (idx = 0; idx < instr->ga_len; ++idx)
5942 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005943 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01005944
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005945 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005946 if (!dfunc->df_deleted)
5947 --def_functions.ga_len;
5948
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005949 while (cctx.ctx_scope != NULL)
5950 drop_scope(&cctx);
5951
Bram Moolenaar20431c92020-03-20 18:39:46 +01005952 // Don't execute this function body.
5953 ga_clear_strings(&ufunc->uf_lines);
5954
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005955 if (errormsg != NULL)
5956 emsg(errormsg);
5957 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005958 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005959 }
5960
5961 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005962 free_imported(&cctx);
5963 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005964 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005965}
5966
5967/*
5968 * Delete an instruction, free what it contains.
5969 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01005970 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005971delete_instr(isn_T *isn)
5972{
5973 switch (isn->isn_type)
5974 {
5975 case ISN_EXEC:
5976 case ISN_LOADENV:
5977 case ISN_LOADG:
5978 case ISN_LOADOPT:
5979 case ISN_MEMBER:
5980 case ISN_PUSHEXC:
5981 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005982 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005983 case ISN_STOREG:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005984 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005985 vim_free(isn->isn_arg.string);
5986 break;
5987
5988 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005989 case ISN_STORES:
5990 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005991 break;
5992
5993 case ISN_STOREOPT:
5994 vim_free(isn->isn_arg.storeopt.so_name);
5995 break;
5996
5997 case ISN_PUSHBLOB: // push blob isn_arg.blob
5998 blob_unref(isn->isn_arg.blob);
5999 break;
6000
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006001 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006002#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006003 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006004#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006005 break;
6006
6007 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006008#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006009 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006010#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006011 break;
6012
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006013 case ISN_UCALL:
6014 vim_free(isn->isn_arg.ufunc.cuf_name);
6015 break;
6016
6017 case ISN_2BOOL:
6018 case ISN_2STRING:
6019 case ISN_ADDBLOB:
6020 case ISN_ADDLIST:
6021 case ISN_BCALL:
6022 case ISN_CATCH:
6023 case ISN_CHECKNR:
6024 case ISN_CHECKTYPE:
6025 case ISN_COMPAREANY:
6026 case ISN_COMPAREBLOB:
6027 case ISN_COMPAREBOOL:
6028 case ISN_COMPAREDICT:
6029 case ISN_COMPAREFLOAT:
6030 case ISN_COMPAREFUNC:
6031 case ISN_COMPARELIST:
6032 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006033 case ISN_COMPARESPECIAL:
6034 case ISN_COMPARESTRING:
6035 case ISN_CONCAT:
6036 case ISN_DCALL:
6037 case ISN_DROP:
6038 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006039 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006040 case ISN_ENDTRY:
6041 case ISN_FOR:
6042 case ISN_FUNCREF:
6043 case ISN_INDEX:
6044 case ISN_JUMP:
6045 case ISN_LOAD:
6046 case ISN_LOADSCRIPT:
6047 case ISN_LOADREG:
6048 case ISN_LOADV:
6049 case ISN_NEGATENR:
6050 case ISN_NEWDICT:
6051 case ISN_NEWLIST:
6052 case ISN_OPNR:
6053 case ISN_OPFLOAT:
6054 case ISN_OPANY:
6055 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006056 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006057 case ISN_PUSHF:
6058 case ISN_PUSHNR:
6059 case ISN_PUSHBOOL:
6060 case ISN_PUSHSPEC:
6061 case ISN_RETURN:
6062 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006063 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006064 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006065 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006066 case ISN_STORESCRIPT:
6067 case ISN_THROW:
6068 case ISN_TRY:
6069 // nothing allocated
6070 break;
6071 }
6072}
6073
6074/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006075 * Free all instructions for "dfunc".
6076 */
6077 static void
6078delete_def_function_contents(dfunc_T *dfunc)
6079{
6080 int idx;
6081
6082 ga_clear(&dfunc->df_def_args_isn);
6083
6084 if (dfunc->df_instr != NULL)
6085 {
6086 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6087 delete_instr(dfunc->df_instr + idx);
6088 VIM_CLEAR(dfunc->df_instr);
6089 }
6090
6091 dfunc->df_deleted = TRUE;
6092}
6093
6094/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006095 * When a user function is deleted, delete any associated def function.
6096 */
6097 void
6098delete_def_function(ufunc_T *ufunc)
6099{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006100 if (ufunc->uf_dfunc_idx >= 0)
6101 {
6102 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6103 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006104
Bram Moolenaar20431c92020-03-20 18:39:46 +01006105 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006106 }
6107}
6108
6109#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006110/*
6111 * Free all functions defined with ":def".
6112 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006113 void
6114free_def_functions(void)
6115{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006116 int idx;
6117
6118 for (idx = 0; idx < def_functions.ga_len; ++idx)
6119 {
6120 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6121
6122 delete_def_function_contents(dfunc);
6123 }
6124
6125 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006126}
6127#endif
6128
6129
6130#endif // FEAT_EVAL