blob: aeb950ca6a939182f98624217ae20acaa6ed2dae [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
123 garray_T *ctx_type_list; // space for adding types
124};
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);
132
133/*
134 * Lookup variable "name" in the local scope and return the index.
135 */
136 static int
137lookup_local(char_u *name, size_t len, cctx_T *cctx)
138{
139 int idx;
140
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100141 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100142 return -1;
143 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
144 {
145 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
146
147 if (STRNCMP(name, lvar->lv_name, len) == 0
148 && STRLEN(lvar->lv_name) == len)
149 return idx;
150 }
151 return -1;
152}
153
154/*
155 * Lookup an argument in the current function.
156 * Returns the argument index or -1 if not found.
157 */
158 static int
159lookup_arg(char_u *name, size_t len, cctx_T *cctx)
160{
161 int idx;
162
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100163 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100164 return -1;
165 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
166 {
167 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
168
169 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
170 return idx;
171 }
172 return -1;
173}
174
175/*
176 * Lookup a vararg argument in the current function.
177 * Returns TRUE if there is a match.
178 */
179 static int
180lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
181{
182 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
183
184 return len > 0 && va_name != NULL
185 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
186}
187
188/*
189 * Lookup a variable in the current script.
190 * Returns OK or FAIL.
191 */
192 static int
193lookup_script(char_u *name, size_t len)
194{
195 int cc;
196 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
197 dictitem_T *di;
198
199 cc = name[len];
200 name[len] = NUL;
201 di = find_var_in_ht(ht, 0, name, TRUE);
202 name[len] = cc;
203 return di == NULL ? FAIL: OK;
204}
205
206 static type_T *
207get_list_type(type_T *member_type, garray_T *type_list)
208{
209 type_T *type;
210
211 // recognize commonly used types
212 if (member_type->tt_type == VAR_UNKNOWN)
213 return &t_list_any;
Bram Moolenaar436472f2020-02-20 22:54:43 +0100214 if (member_type->tt_type == VAR_VOID)
215 return &t_list_empty;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100216 if (member_type->tt_type == VAR_NUMBER)
217 return &t_list_number;
218 if (member_type->tt_type == VAR_STRING)
219 return &t_list_string;
220
221 // Not a common type, create a new entry.
222 if (ga_grow(type_list, 1) == FAIL)
223 return FAIL;
224 type = ((type_T *)type_list->ga_data) + type_list->ga_len;
225 ++type_list->ga_len;
226 type->tt_type = VAR_LIST;
227 type->tt_member = member_type;
228 return type;
229}
230
231 static type_T *
232get_dict_type(type_T *member_type, garray_T *type_list)
233{
234 type_T *type;
235
236 // recognize commonly used types
237 if (member_type->tt_type == VAR_UNKNOWN)
238 return &t_dict_any;
Bram Moolenaar436472f2020-02-20 22:54:43 +0100239 if (member_type->tt_type == VAR_VOID)
240 return &t_dict_empty;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100241 if (member_type->tt_type == VAR_NUMBER)
242 return &t_dict_number;
243 if (member_type->tt_type == VAR_STRING)
244 return &t_dict_string;
245
246 // Not a common type, create a new entry.
247 if (ga_grow(type_list, 1) == FAIL)
248 return FAIL;
249 type = ((type_T *)type_list->ga_data) + type_list->ga_len;
250 ++type_list->ga_len;
251 type->tt_type = VAR_DICT;
252 type->tt_member = member_type;
253 return type;
254}
255
256/////////////////////////////////////////////////////////////////////
257// Following generate_ functions expect the caller to call ga_grow().
258
259/*
260 * Generate an instruction without arguments.
261 * Returns a pointer to the new instruction, NULL if failed.
262 */
263 static isn_T *
264generate_instr(cctx_T *cctx, isntype_T isn_type)
265{
266 garray_T *instr = &cctx->ctx_instr;
267 isn_T *isn;
268
269 if (ga_grow(instr, 1) == FAIL)
270 return NULL;
271 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
272 isn->isn_type = isn_type;
273 isn->isn_lnum = cctx->ctx_lnum + 1;
274 ++instr->ga_len;
275
276 return isn;
277}
278
279/*
280 * Generate an instruction without arguments.
281 * "drop" will be removed from the stack.
282 * Returns a pointer to the new instruction, NULL if failed.
283 */
284 static isn_T *
285generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
286{
287 garray_T *stack = &cctx->ctx_type_stack;
288
289 stack->ga_len -= drop;
290 return generate_instr(cctx, isn_type);
291}
292
293/*
294 * Generate instruction "isn_type" and put "type" on the type stack.
295 */
296 static isn_T *
297generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
298{
299 isn_T *isn;
300 garray_T *stack = &cctx->ctx_type_stack;
301
302 if ((isn = generate_instr(cctx, isn_type)) == NULL)
303 return NULL;
304
305 if (ga_grow(stack, 1) == FAIL)
306 return NULL;
307 ((type_T **)stack->ga_data)[stack->ga_len] = type;
308 ++stack->ga_len;
309
310 return isn;
311}
312
313/*
314 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
315 */
316 static int
317may_generate_2STRING(int offset, cctx_T *cctx)
318{
319 isn_T *isn;
320 garray_T *stack = &cctx->ctx_type_stack;
321 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
322
323 if ((*type)->tt_type == VAR_STRING)
324 return OK;
325 *type = &t_string;
326
327 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
328 return FAIL;
329 isn->isn_arg.number = offset;
330
331 return OK;
332}
333
334 static int
335check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
336{
337 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_UNKNOWN)
338 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
339 || type2 == VAR_UNKNOWN)))
340 {
341 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100342 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100343 else
344 semsg(_("E1036: %c requires number or float arguments"), *op);
345 return FAIL;
346 }
347 return OK;
348}
349
350/*
351 * Generate an instruction with two arguments. The instruction depends on the
352 * type of the arguments.
353 */
354 static int
355generate_two_op(cctx_T *cctx, char_u *op)
356{
357 garray_T *stack = &cctx->ctx_type_stack;
358 type_T *type1;
359 type_T *type2;
360 vartype_T vartype;
361 isn_T *isn;
362
363 // Get the known type of the two items on the stack. If they are matching
364 // use a type-specific instruction. Otherwise fall back to runtime type
365 // checking.
366 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
367 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
368 vartype = VAR_UNKNOWN;
369 if (type1->tt_type == type2->tt_type
370 && (type1->tt_type == VAR_NUMBER
371 || type1->tt_type == VAR_LIST
372#ifdef FEAT_FLOAT
373 || type1->tt_type == VAR_FLOAT
374#endif
375 || type1->tt_type == VAR_BLOB))
376 vartype = type1->tt_type;
377
378 switch (*op)
379 {
380 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar0062c2d2020-02-20 22:14:31 +0100381 && type1->tt_type != VAR_UNKNOWN
382 && type2->tt_type != VAR_UNKNOWN
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100383 && check_number_or_float(
384 type1->tt_type, type2->tt_type, op) == FAIL)
385 return FAIL;
386 isn = generate_instr_drop(cctx,
387 vartype == VAR_NUMBER ? ISN_OPNR
388 : vartype == VAR_LIST ? ISN_ADDLIST
389 : vartype == VAR_BLOB ? ISN_ADDBLOB
390#ifdef FEAT_FLOAT
391 : vartype == VAR_FLOAT ? ISN_OPFLOAT
392#endif
393 : ISN_OPANY, 1);
394 if (isn != NULL)
395 isn->isn_arg.op.op_type = EXPR_ADD;
396 break;
397
398 case '-':
399 case '*':
400 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
401 op) == FAIL)
402 return FAIL;
403 if (vartype == VAR_NUMBER)
404 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
405#ifdef FEAT_FLOAT
406 else if (vartype == VAR_FLOAT)
407 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
408#endif
409 else
410 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
411 if (isn != NULL)
412 isn->isn_arg.op.op_type = *op == '*'
413 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
414 break;
415
416 case '%': if ((type1->tt_type != VAR_UNKNOWN
417 && type1->tt_type != VAR_NUMBER)
418 || (type2->tt_type != VAR_UNKNOWN
419 && type2->tt_type != VAR_NUMBER))
420 {
421 emsg(_("E1035: % requires number arguments"));
422 return FAIL;
423 }
424 isn = generate_instr_drop(cctx,
425 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
426 if (isn != NULL)
427 isn->isn_arg.op.op_type = EXPR_REM;
428 break;
429 }
430
431 // correct type of result
432 if (vartype == VAR_UNKNOWN)
433 {
434 type_T *type = &t_any;
435
436#ifdef FEAT_FLOAT
437 // float+number and number+float results in float
438 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
439 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
440 type = &t_float;
441#endif
442 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
443 }
444
445 return OK;
446}
447
448/*
449 * Generate an ISN_COMPARE* instruction with a boolean result.
450 */
451 static int
452generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
453{
454 isntype_T isntype = ISN_DROP;
455 isn_T *isn;
456 garray_T *stack = &cctx->ctx_type_stack;
457 vartype_T type1;
458 vartype_T type2;
459
460 // Get the known type of the two items on the stack. If they are matching
461 // use a type-specific instruction. Otherwise fall back to runtime type
462 // checking.
463 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
464 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
465 if (type1 == type2)
466 {
467 switch (type1)
468 {
469 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
470 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
471 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
472 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
473 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
474 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
475 case VAR_LIST: isntype = ISN_COMPARELIST; break;
476 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
477 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
478 case VAR_PARTIAL: isntype = ISN_COMPAREPARTIAL; break;
479 default: isntype = ISN_COMPAREANY; break;
480 }
481 }
482 else if (type1 == VAR_UNKNOWN || type2 == VAR_UNKNOWN
483 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
484 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
485 isntype = ISN_COMPAREANY;
486
487 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
488 && (isntype == ISN_COMPAREBOOL
489 || isntype == ISN_COMPARESPECIAL
490 || isntype == ISN_COMPARENR
491 || isntype == ISN_COMPAREFLOAT))
492 {
493 semsg(_("E1037: Cannot use \"%s\" with %s"),
494 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
495 return FAIL;
496 }
497 if (isntype == ISN_DROP
498 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
499 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
500 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
501 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
502 && exptype != EXPR_IS && exptype != EXPR_ISNOT
503 && (type1 == VAR_BLOB || type2 == VAR_BLOB
504 || type1 == VAR_LIST || type2 == VAR_LIST))))
505 {
506 semsg(_("E1037: Cannot compare %s with %s"),
507 vartype_name(type1), vartype_name(type2));
508 return FAIL;
509 }
510
511 if ((isn = generate_instr(cctx, isntype)) == NULL)
512 return FAIL;
513 isn->isn_arg.op.op_type = exptype;
514 isn->isn_arg.op.op_ic = ic;
515
516 // takes two arguments, puts one bool back
517 if (stack->ga_len >= 2)
518 {
519 --stack->ga_len;
520 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
521 }
522
523 return OK;
524}
525
526/*
527 * Generate an ISN_2BOOL instruction.
528 */
529 static int
530generate_2BOOL(cctx_T *cctx, int invert)
531{
532 isn_T *isn;
533 garray_T *stack = &cctx->ctx_type_stack;
534
535 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
536 return FAIL;
537 isn->isn_arg.number = invert;
538
539 // type becomes bool
540 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
541
542 return OK;
543}
544
545 static int
546generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
547{
548 isn_T *isn;
549 garray_T *stack = &cctx->ctx_type_stack;
550
551 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
552 return FAIL;
553 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
554 isn->isn_arg.type.ct_off = offset;
555
556 // type becomes vartype
557 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
558
559 return OK;
560}
561
562/*
563 * Generate an ISN_PUSHNR instruction.
564 */
565 static int
566generate_PUSHNR(cctx_T *cctx, varnumber_T number)
567{
568 isn_T *isn;
569
570 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
571 return FAIL;
572 isn->isn_arg.number = number;
573
574 return OK;
575}
576
577/*
578 * Generate an ISN_PUSHBOOL instruction.
579 */
580 static int
581generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
582{
583 isn_T *isn;
584
585 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
586 return FAIL;
587 isn->isn_arg.number = number;
588
589 return OK;
590}
591
592/*
593 * Generate an ISN_PUSHSPEC instruction.
594 */
595 static int
596generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
597{
598 isn_T *isn;
599
600 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
601 return FAIL;
602 isn->isn_arg.number = number;
603
604 return OK;
605}
606
607#ifdef FEAT_FLOAT
608/*
609 * Generate an ISN_PUSHF instruction.
610 */
611 static int
612generate_PUSHF(cctx_T *cctx, float_T fnumber)
613{
614 isn_T *isn;
615
616 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
617 return FAIL;
618 isn->isn_arg.fnumber = fnumber;
619
620 return OK;
621}
622#endif
623
624/*
625 * Generate an ISN_PUSHS instruction.
626 * Consumes "str".
627 */
628 static int
629generate_PUSHS(cctx_T *cctx, char_u *str)
630{
631 isn_T *isn;
632
633 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
634 return FAIL;
635 isn->isn_arg.string = str;
636
637 return OK;
638}
639
640/*
641 * Generate an ISN_PUSHBLOB instruction.
642 * Consumes "blob".
643 */
644 static int
645generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
646{
647 isn_T *isn;
648
649 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
650 return FAIL;
651 isn->isn_arg.blob = blob;
652
653 return OK;
654}
655
656/*
657 * Generate an ISN_STORE instruction.
658 */
659 static int
660generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
661{
662 isn_T *isn;
663
664 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
665 return FAIL;
666 if (name != NULL)
667 isn->isn_arg.string = vim_strsave(name);
668 else
669 isn->isn_arg.number = idx;
670
671 return OK;
672}
673
674/*
675 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
676 */
677 static int
678generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
679{
680 isn_T *isn;
681
682 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
683 return FAIL;
684 isn->isn_arg.storenr.str_idx = idx;
685 isn->isn_arg.storenr.str_val = value;
686
687 return OK;
688}
689
690/*
691 * Generate an ISN_STOREOPT instruction
692 */
693 static int
694generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
695{
696 isn_T *isn;
697
698 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
699 return FAIL;
700 isn->isn_arg.storeopt.so_name = vim_strsave(name);
701 isn->isn_arg.storeopt.so_flags = opt_flags;
702
703 return OK;
704}
705
706/*
707 * Generate an ISN_LOAD or similar instruction.
708 */
709 static int
710generate_LOAD(
711 cctx_T *cctx,
712 isntype_T isn_type,
713 int idx,
714 char_u *name,
715 type_T *type)
716{
717 isn_T *isn;
718
719 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
720 return FAIL;
721 if (name != NULL)
722 isn->isn_arg.string = vim_strsave(name);
723 else
724 isn->isn_arg.number = idx;
725
726 return OK;
727}
728
729/*
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100730 * Generate an ISN_LOADV instruction.
731 */
732 static int
733generate_LOADV(
734 cctx_T *cctx,
735 char_u *name,
736 int error)
737{
738 // load v:var
739 int vidx = find_vim_var(name);
740
741 if (vidx < 0)
742 {
743 if (error)
744 semsg(_(e_var_notfound), name);
745 return FAIL;
746 }
747
748 // TODO: get actual type
749 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, &t_any);
750}
751
752/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100753 * Generate an ISN_LOADS instruction.
754 */
755 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100756generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100757 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100758 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100759 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100760 int sid,
761 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100762{
763 isn_T *isn;
764
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100765 if (isn_type == ISN_LOADS)
766 isn = generate_instr_type(cctx, isn_type, type);
767 else
768 isn = generate_instr_drop(cctx, isn_type, 1);
769 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100770 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100771 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
772 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100773
774 return OK;
775}
776
777/*
778 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
779 */
780 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100781generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100782 cctx_T *cctx,
783 isntype_T isn_type,
784 int sid,
785 int idx,
786 type_T *type)
787{
788 isn_T *isn;
789
790 if (isn_type == ISN_LOADSCRIPT)
791 isn = generate_instr_type(cctx, isn_type, type);
792 else
793 isn = generate_instr_drop(cctx, isn_type, 1);
794 if (isn == NULL)
795 return FAIL;
796 isn->isn_arg.script.script_sid = sid;
797 isn->isn_arg.script.script_idx = idx;
798 return OK;
799}
800
801/*
802 * Generate an ISN_NEWLIST instruction.
803 */
804 static int
805generate_NEWLIST(cctx_T *cctx, int count)
806{
807 isn_T *isn;
808 garray_T *stack = &cctx->ctx_type_stack;
809 garray_T *type_list = cctx->ctx_type_list;
810 type_T *type;
811 type_T *member;
812
813 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
814 return FAIL;
815 isn->isn_arg.number = count;
816
817 // drop the value types
818 stack->ga_len -= count;
819
Bram Moolenaar436472f2020-02-20 22:54:43 +0100820 // Use the first value type for the list member type. Use "void" for an
821 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100822 if (count > 0)
823 member = ((type_T **)stack->ga_data)[stack->ga_len];
824 else
Bram Moolenaar436472f2020-02-20 22:54:43 +0100825 member = &t_void;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100826 type = get_list_type(member, type_list);
827
828 // add the list type to the type stack
829 if (ga_grow(stack, 1) == FAIL)
830 return FAIL;
831 ((type_T **)stack->ga_data)[stack->ga_len] = type;
832 ++stack->ga_len;
833
834 return OK;
835}
836
837/*
838 * Generate an ISN_NEWDICT instruction.
839 */
840 static int
841generate_NEWDICT(cctx_T *cctx, int count)
842{
843 isn_T *isn;
844 garray_T *stack = &cctx->ctx_type_stack;
845 garray_T *type_list = cctx->ctx_type_list;
846 type_T *type;
847 type_T *member;
848
849 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
850 return FAIL;
851 isn->isn_arg.number = count;
852
853 // drop the key and value types
854 stack->ga_len -= 2 * count;
855
Bram Moolenaar436472f2020-02-20 22:54:43 +0100856 // Use the first value type for the list member type. Use "void" for an
857 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100858 if (count > 0)
859 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
860 else
Bram Moolenaar436472f2020-02-20 22:54:43 +0100861 member = &t_void;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100862 type = get_dict_type(member, type_list);
863
864 // add the dict type to the type stack
865 if (ga_grow(stack, 1) == FAIL)
866 return FAIL;
867 ((type_T **)stack->ga_data)[stack->ga_len] = type;
868 ++stack->ga_len;
869
870 return OK;
871}
872
873/*
874 * Generate an ISN_FUNCREF instruction.
875 */
876 static int
877generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
878{
879 isn_T *isn;
880 garray_T *stack = &cctx->ctx_type_stack;
881
882 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
883 return FAIL;
884 isn->isn_arg.number = dfunc_idx;
885
886 if (ga_grow(stack, 1) == FAIL)
887 return FAIL;
888 ((type_T **)stack->ga_data)[stack->ga_len] = &t_partial_any;
889 // TODO: argument and return types
890 ++stack->ga_len;
891
892 return OK;
893}
894
895/*
896 * Generate an ISN_JUMP instruction.
897 */
898 static int
899generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
900{
901 isn_T *isn;
902 garray_T *stack = &cctx->ctx_type_stack;
903
904 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
905 return FAIL;
906 isn->isn_arg.jump.jump_when = when;
907 isn->isn_arg.jump.jump_where = where;
908
909 if (when != JUMP_ALWAYS && stack->ga_len > 0)
910 --stack->ga_len;
911
912 return OK;
913}
914
915 static int
916generate_FOR(cctx_T *cctx, int loop_idx)
917{
918 isn_T *isn;
919 garray_T *stack = &cctx->ctx_type_stack;
920
921 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
922 return FAIL;
923 isn->isn_arg.forloop.for_idx = loop_idx;
924
925 if (ga_grow(stack, 1) == FAIL)
926 return FAIL;
927 // type doesn't matter, will be stored next
928 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
929 ++stack->ga_len;
930
931 return OK;
932}
933
934/*
935 * Generate an ISN_BCALL instruction.
936 * Return FAIL if the number of arguments is wrong.
937 */
938 static int
939generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
940{
941 isn_T *isn;
942 garray_T *stack = &cctx->ctx_type_stack;
943
944 if (check_internal_func(func_idx, argcount) == FAIL)
945 return FAIL;
946
947 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
948 return FAIL;
949 isn->isn_arg.bfunc.cbf_idx = func_idx;
950 isn->isn_arg.bfunc.cbf_argcount = argcount;
951
952 stack->ga_len -= argcount; // drop the arguments
953 if (ga_grow(stack, 1) == FAIL)
954 return FAIL;
955 ((type_T **)stack->ga_data)[stack->ga_len] =
956 internal_func_ret_type(func_idx, argcount);
957 ++stack->ga_len; // add return value
958
959 return OK;
960}
961
962/*
963 * Generate an ISN_DCALL or ISN_UCALL instruction.
964 * Return FAIL if the number of arguments is wrong.
965 */
966 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100967generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100968{
969 isn_T *isn;
970 garray_T *stack = &cctx->ctx_type_stack;
971 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100972 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100973
974 if (argcount > regular_args && !has_varargs(ufunc))
975 {
976 semsg(_(e_toomanyarg), ufunc->uf_name);
977 return FAIL;
978 }
979 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
980 {
981 semsg(_(e_toofewarg), ufunc->uf_name);
982 return FAIL;
983 }
984
985 // Turn varargs into a list.
986 if (ufunc->uf_va_name != NULL)
987 {
988 int count = argcount - regular_args;
989
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100990 // If count is negative an empty list will be added after evaluating
991 // default values for missing optional arguments.
992 if (count >= 0)
993 {
994 generate_NEWLIST(cctx, count);
995 argcount = regular_args + 1;
996 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100997 }
998
999 if ((isn = generate_instr(cctx,
1000 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1001 return FAIL;
1002 if (ufunc->uf_dfunc_idx >= 0)
1003 {
1004 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1005 isn->isn_arg.dfunc.cdf_argcount = argcount;
1006 }
1007 else
1008 {
1009 // A user function may be deleted and redefined later, can't use the
1010 // ufunc pointer, need to look it up again at runtime.
1011 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1012 isn->isn_arg.ufunc.cuf_argcount = argcount;
1013 }
1014
1015 stack->ga_len -= argcount; // drop the arguments
1016 if (ga_grow(stack, 1) == FAIL)
1017 return FAIL;
1018 // add return value
1019 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1020 ++stack->ga_len;
1021
1022 return OK;
1023}
1024
1025/*
1026 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1027 */
1028 static int
1029generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1030{
1031 isn_T *isn;
1032 garray_T *stack = &cctx->ctx_type_stack;
1033
1034 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1035 return FAIL;
1036 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1037 isn->isn_arg.ufunc.cuf_argcount = argcount;
1038
1039 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001040 if (ga_grow(stack, 1) == FAIL)
1041 return FAIL;
1042 // add return value
1043 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1044 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001045
1046 return OK;
1047}
1048
1049/*
1050 * Generate an ISN_PCALL instruction.
1051 */
1052 static int
1053generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1054{
1055 isn_T *isn;
1056 garray_T *stack = &cctx->ctx_type_stack;
1057
1058 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1059 return FAIL;
1060 isn->isn_arg.pfunc.cpf_top = at_top;
1061 isn->isn_arg.pfunc.cpf_argcount = argcount;
1062
1063 stack->ga_len -= argcount; // drop the arguments
1064
1065 // drop the funcref/partial, get back the return value
1066 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1067
1068 return OK;
1069}
1070
1071/*
1072 * Generate an ISN_MEMBER instruction.
1073 */
1074 static int
1075generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1076{
1077 isn_T *isn;
1078 garray_T *stack = &cctx->ctx_type_stack;
1079 type_T *type;
1080
1081 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1082 return FAIL;
1083 isn->isn_arg.string = vim_strnsave(name, (int)len);
1084
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001085 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001086 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001087 if (type->tt_type != VAR_DICT && type != &t_any)
1088 {
1089 emsg(_(e_dictreq));
1090 return FAIL;
1091 }
1092 // change dict type to dict member type
1093 if (type->tt_type == VAR_DICT)
1094 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001095
1096 return OK;
1097}
1098
1099/*
1100 * Generate an ISN_ECHO instruction.
1101 */
1102 static int
1103generate_ECHO(cctx_T *cctx, int with_white, int count)
1104{
1105 isn_T *isn;
1106
1107 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1108 return FAIL;
1109 isn->isn_arg.echo.echo_with_white = with_white;
1110 isn->isn_arg.echo.echo_count = count;
1111
1112 return OK;
1113}
1114
1115 static int
1116generate_EXEC(cctx_T *cctx, char_u *line)
1117{
1118 isn_T *isn;
1119
1120 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1121 return FAIL;
1122 isn->isn_arg.string = vim_strsave(line);
1123 return OK;
1124}
1125
1126static char e_white_both[] =
1127 N_("E1004: white space required before and after '%s'");
1128
1129/*
1130 * Reserve space for a local variable.
1131 * Return the index or -1 if it failed.
1132 */
1133 static int
1134reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1135{
1136 int idx;
1137 lvar_T *lvar;
1138
1139 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1140 {
1141 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1142 return -1;
1143 }
1144
1145 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1146 return -1;
1147 idx = cctx->ctx_locals.ga_len;
1148 if (cctx->ctx_max_local < idx + 1)
1149 cctx->ctx_max_local = idx + 1;
1150 ++cctx->ctx_locals.ga_len;
1151
1152 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1153 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1154 lvar->lv_const = isConst;
1155 lvar->lv_type = type;
1156
1157 return idx;
1158}
1159
1160/*
1161 * Skip over a type definition and return a pointer to just after it.
1162 */
1163 char_u *
1164skip_type(char_u *start)
1165{
1166 char_u *p = start;
1167
1168 while (ASCII_ISALNUM(*p) || *p == '_')
1169 ++p;
1170
1171 // Skip over "<type>"; this is permissive about white space.
1172 if (*skipwhite(p) == '<')
1173 {
1174 p = skipwhite(p);
1175 p = skip_type(skipwhite(p + 1));
1176 p = skipwhite(p);
1177 if (*p == '>')
1178 ++p;
1179 }
1180 return p;
1181}
1182
1183/*
1184 * Parse the member type: "<type>" and return "type" with the member set.
1185 * Use "type_list" if a new type needs to be added.
1186 * Returns NULL in case of failure.
1187 */
1188 static type_T *
1189parse_type_member(char_u **arg, type_T *type, garray_T *type_list)
1190{
1191 type_T *member_type;
1192
1193 if (**arg != '<')
1194 {
1195 if (*skipwhite(*arg) == '<')
1196 emsg(_("E1007: No white space allowed before <"));
1197 else
1198 emsg(_("E1008: Missing <type>"));
1199 return NULL;
1200 }
1201 *arg = skipwhite(*arg + 1);
1202
1203 member_type = parse_type(arg, type_list);
1204 if (member_type == NULL)
1205 return NULL;
1206
1207 *arg = skipwhite(*arg);
1208 if (**arg != '>')
1209 {
1210 emsg(_("E1009: Missing > after type"));
1211 return NULL;
1212 }
1213 ++*arg;
1214
1215 if (type->tt_type == VAR_LIST)
1216 return get_list_type(member_type, type_list);
1217 return get_dict_type(member_type, type_list);
1218}
1219
1220/*
1221 * Parse a type at "arg" and advance over it.
1222 * Return NULL for failure.
1223 */
1224 type_T *
1225parse_type(char_u **arg, garray_T *type_list)
1226{
1227 char_u *p = *arg;
1228 size_t len;
1229
1230 // skip over the first word
1231 while (ASCII_ISALNUM(*p) || *p == '_')
1232 ++p;
1233 len = p - *arg;
1234
1235 switch (**arg)
1236 {
1237 case 'a':
1238 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1239 {
1240 *arg += len;
1241 return &t_any;
1242 }
1243 break;
1244 case 'b':
1245 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1246 {
1247 *arg += len;
1248 return &t_bool;
1249 }
1250 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1251 {
1252 *arg += len;
1253 return &t_blob;
1254 }
1255 break;
1256 case 'c':
1257 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1258 {
1259 *arg += len;
1260 return &t_channel;
1261 }
1262 break;
1263 case 'd':
1264 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1265 {
1266 *arg += len;
1267 return parse_type_member(arg, &t_dict_any, type_list);
1268 }
1269 break;
1270 case 'f':
1271 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1272 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001273#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001274 *arg += len;
1275 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001276#else
1277 emsg(_("E1055: This Vim is not compiled with float support"));
1278 return &t_any;
1279#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001280 }
1281 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1282 {
1283 *arg += len;
1284 // TODO: arguments and return type
1285 return &t_func_any;
1286 }
1287 break;
1288 case 'j':
1289 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1290 {
1291 *arg += len;
1292 return &t_job;
1293 }
1294 break;
1295 case 'l':
1296 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1297 {
1298 *arg += len;
1299 return parse_type_member(arg, &t_list_any, type_list);
1300 }
1301 break;
1302 case 'n':
1303 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1304 {
1305 *arg += len;
1306 return &t_number;
1307 }
1308 break;
1309 case 'p':
1310 if (len == 4 && STRNCMP(*arg, "partial", len) == 0)
1311 {
1312 *arg += len;
1313 // TODO: arguments and return type
1314 return &t_partial_any;
1315 }
1316 break;
1317 case 's':
1318 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1319 {
1320 *arg += len;
1321 return &t_string;
1322 }
1323 break;
1324 case 'v':
1325 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1326 {
1327 *arg += len;
1328 return &t_void;
1329 }
1330 break;
1331 }
1332
1333 semsg(_("E1010: Type not recognized: %s"), *arg);
1334 return &t_any;
1335}
1336
1337/*
1338 * Check if "type1" and "type2" are exactly the same.
1339 */
1340 static int
1341equal_type(type_T *type1, type_T *type2)
1342{
1343 if (type1->tt_type != type2->tt_type)
1344 return FALSE;
1345 switch (type1->tt_type)
1346 {
1347 case VAR_VOID:
1348 case VAR_UNKNOWN:
1349 case VAR_SPECIAL:
1350 case VAR_BOOL:
1351 case VAR_NUMBER:
1352 case VAR_FLOAT:
1353 case VAR_STRING:
1354 case VAR_BLOB:
1355 case VAR_JOB:
1356 case VAR_CHANNEL:
1357 return TRUE; // not composite is always OK
1358 case VAR_LIST:
1359 case VAR_DICT:
1360 return equal_type(type1->tt_member, type2->tt_member);
1361 case VAR_FUNC:
1362 case VAR_PARTIAL:
1363 // TODO; check argument types.
1364 return equal_type(type1->tt_member, type2->tt_member)
1365 && type1->tt_argcount == type2->tt_argcount;
1366 }
1367 return TRUE;
1368}
1369
1370/*
1371 * Find the common type of "type1" and "type2" and put it in "dest".
1372 * "type2" and "dest" may be the same.
1373 */
1374 static void
1375common_type(type_T *type1, type_T *type2, type_T *dest)
1376{
1377 if (equal_type(type1, type2))
1378 {
1379 if (dest != type2)
1380 *dest = *type2;
1381 return;
1382 }
1383
1384 if (type1->tt_type == type2->tt_type)
1385 {
1386 dest->tt_type = type1->tt_type;
1387 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1388 {
1389 common_type(type1->tt_member, type2->tt_member, dest->tt_member);
1390 return;
1391 }
1392 // TODO: VAR_FUNC and VAR_PARTIAL
1393 }
1394
1395 dest->tt_type = VAR_UNKNOWN; // "any"
1396}
1397
1398 char *
1399vartype_name(vartype_T type)
1400{
1401 switch (type)
1402 {
1403 case VAR_VOID: return "void";
1404 case VAR_UNKNOWN: return "any";
1405 case VAR_SPECIAL: return "special";
1406 case VAR_BOOL: return "bool";
1407 case VAR_NUMBER: return "number";
1408 case VAR_FLOAT: return "float";
1409 case VAR_STRING: return "string";
1410 case VAR_BLOB: return "blob";
1411 case VAR_JOB: return "job";
1412 case VAR_CHANNEL: return "channel";
1413 case VAR_LIST: return "list";
1414 case VAR_DICT: return "dict";
1415 case VAR_FUNC: return "function";
1416 case VAR_PARTIAL: return "partial";
1417 }
1418 return "???";
1419}
1420
1421/*
1422 * Return the name of a type.
1423 * The result may be in allocated memory, in which case "tofree" is set.
1424 */
1425 char *
1426type_name(type_T *type, char **tofree)
1427{
1428 char *name = vartype_name(type->tt_type);
1429
1430 *tofree = NULL;
1431 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1432 {
1433 char *member_free;
1434 char *member_name = type_name(type->tt_member, &member_free);
1435 size_t len;
1436
1437 len = STRLEN(name) + STRLEN(member_name) + 3;
1438 *tofree = alloc(len);
1439 if (*tofree != NULL)
1440 {
1441 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1442 vim_free(member_free);
1443 return *tofree;
1444 }
1445 }
1446 // TODO: function and partial argument types
1447
1448 return name;
1449}
1450
1451/*
1452 * Find "name" in script-local items of script "sid".
1453 * Returns the index in "sn_var_vals" if found.
1454 * If found but not in "sn_var_vals" returns -1.
1455 * If not found returns -2.
1456 */
1457 int
1458get_script_item_idx(int sid, char_u *name, int check_writable)
1459{
1460 hashtab_T *ht;
1461 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001462 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001463 int idx;
1464
1465 // First look the name up in the hashtable.
1466 if (sid <= 0 || sid > script_items.ga_len)
1467 return -1;
1468 ht = &SCRIPT_VARS(sid);
1469 di = find_var_in_ht(ht, 0, name, TRUE);
1470 if (di == NULL)
1471 return -2;
1472
1473 // Now find the svar_T index in sn_var_vals.
1474 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
1475 {
1476 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1477
1478 if (sv->sv_tv == &di->di_tv)
1479 {
1480 if (check_writable && sv->sv_const)
1481 semsg(_(e_readonlyvar), name);
1482 return idx;
1483 }
1484 }
1485 return -1;
1486}
1487
1488/*
1489 * Find "name" in imported items of the current script/
1490 */
1491 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001492find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001493{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001494 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001495 int idx;
1496
1497 if (cctx != NULL)
1498 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1499 {
1500 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
1501 + idx;
1502
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001503 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1504 : STRLEN(import->imp_name) == len
1505 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001506 return import;
1507 }
1508
1509 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
1510 {
1511 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
1512
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001513 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1514 : STRLEN(import->imp_name) == len
1515 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001516 return import;
1517 }
1518 return NULL;
1519}
1520
1521/*
1522 * Generate an instruction to load script-local variable "name".
1523 */
1524 static int
1525compile_load_scriptvar(cctx_T *cctx, char_u *name)
1526{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001527 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001528 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
1529 imported_T *import;
1530
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001531 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001532 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001533 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001534 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
1535 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001536 }
1537 if (idx >= 0)
1538 {
1539 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1540
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001541 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001542 current_sctx.sc_sid, idx, sv->sv_type);
1543 return OK;
1544 }
1545
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001546 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001547 if (import != NULL)
1548 {
1549 // TODO: check this is a variable, not a function
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001550 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001551 import->imp_sid,
1552 import->imp_var_vals_idx,
1553 import->imp_type);
1554 return OK;
1555 }
1556
1557 semsg(_("E1050: Item not found: %s"), name);
1558 return FAIL;
1559}
1560
1561/*
1562 * Compile a variable name into a load instruction.
1563 * "end" points to just after the name.
1564 * When "error" is FALSE do not give an error when not found.
1565 */
1566 static int
1567compile_load(char_u **arg, char_u *end, cctx_T *cctx, int error)
1568{
1569 type_T *type;
1570 char_u *name;
1571 int res = FAIL;
1572
1573 if (*(*arg + 1) == ':')
1574 {
1575 // load namespaced variable
1576 name = vim_strnsave(*arg + 2, end - (*arg + 2));
1577 if (name == NULL)
1578 return FAIL;
1579
1580 if (**arg == 'v')
1581 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001582 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001583 }
1584 else if (**arg == 'g')
1585 {
1586 // Global variables can be defined later, thus we don't check if it
1587 // exists, give error at runtime.
1588 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
1589 }
1590 else if (**arg == 's')
1591 {
1592 res = compile_load_scriptvar(cctx, name);
1593 }
1594 else
1595 {
1596 semsg("Namespace not supported yet: %s", **arg);
1597 goto theend;
1598 }
1599 }
1600 else
1601 {
1602 size_t len = end - *arg;
1603 int idx;
1604 int gen_load = FALSE;
1605
1606 name = vim_strnsave(*arg, end - *arg);
1607 if (name == NULL)
1608 return FAIL;
1609
1610 idx = lookup_arg(*arg, len, cctx);
1611 if (idx >= 0)
1612 {
1613 if (cctx->ctx_ufunc->uf_arg_types != NULL)
1614 type = cctx->ctx_ufunc->uf_arg_types[idx];
1615 else
1616 type = &t_any;
1617
1618 // Arguments are located above the frame pointer.
1619 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
1620 if (cctx->ctx_ufunc->uf_va_name != NULL)
1621 --idx;
1622 gen_load = TRUE;
1623 }
1624 else if (lookup_vararg(*arg, len, cctx))
1625 {
1626 // varargs is always the last argument
1627 idx = -STACK_FRAME_SIZE - 1;
1628 type = cctx->ctx_ufunc->uf_va_type;
1629 gen_load = TRUE;
1630 }
1631 else
1632 {
1633 idx = lookup_local(*arg, len, cctx);
1634 if (idx >= 0)
1635 {
1636 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
1637 gen_load = TRUE;
1638 }
1639 else
1640 {
1641 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
1642 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
1643 res = generate_PUSHBOOL(cctx, **arg == 't'
1644 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001645 else if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
1646 == SCRIPT_VERSION_VIM9)
1647 // in Vim9 script "var" can be script-local.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001648 res = compile_load_scriptvar(cctx, name);
1649 }
1650 }
1651 if (gen_load)
1652 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
1653 }
1654
1655 *arg = end;
1656
1657theend:
1658 if (res == FAIL && error)
1659 semsg(_(e_var_notfound), name);
1660 vim_free(name);
1661 return res;
1662}
1663
1664/*
1665 * Compile the argument expressions.
1666 * "arg" points to just after the "(" and is advanced to after the ")"
1667 */
1668 static int
1669compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
1670{
1671 char_u *p = *arg;
1672
1673 while (*p != NUL && *p != ')')
1674 {
1675 if (compile_expr1(&p, cctx) == FAIL)
1676 return FAIL;
1677 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01001678
1679 if (*p != ',' && *skipwhite(p) == ',')
1680 {
1681 emsg(_("E1068: No white space allowed before ,"));
1682 p = skipwhite(p);
1683 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001684 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01001685 {
1686 ++p;
1687 if (!VIM_ISWHITE(*p))
1688 emsg(_("E1069: white space required after ,"));
1689 }
1690 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001691 }
Bram Moolenaar38a5f512020-02-19 12:40:39 +01001692 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001693 if (*p != ')')
1694 {
1695 emsg(_(e_missing_close));
1696 return FAIL;
1697 }
1698 *arg = p + 1;
1699 return OK;
1700}
1701
1702/*
1703 * Compile a function call: name(arg1, arg2)
1704 * "arg" points to "name", "arg + varlen" to the "(".
1705 * "argcount_init" is 1 for "value->method()"
1706 * Instructions:
1707 * EVAL arg1
1708 * EVAL arg2
1709 * BCALL / DCALL / UCALL
1710 */
1711 static int
1712compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
1713{
1714 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01001715 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001716 int argcount = argcount_init;
1717 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001718 char_u fname_buf[FLEN_FIXED + 1];
1719 char_u *tofree = NULL;
1720 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001721 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001722 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001723
1724 if (varlen >= sizeof(namebuf))
1725 {
1726 semsg(_("E1011: name too long: %s"), name);
1727 return FAIL;
1728 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001729 vim_strncpy(namebuf, *arg, varlen);
1730 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001731
1732 *arg = skipwhite(*arg + varlen + 1);
1733 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001734 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001735
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001736 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001737 {
1738 int idx;
1739
1740 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001741 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001742 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001743 {
1744 res = generate_BCALL(cctx, idx, argcount);
1745 goto theend;
1746 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001747 semsg(_(e_unknownfunc), namebuf);
1748 }
1749
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001750 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001751 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001752 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001753 {
1754 res = generate_CALL(cctx, ufunc, argcount);
1755 goto theend;
1756 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001757
1758 // If the name is a variable, load it and use PCALL.
1759 p = namebuf;
1760 if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001761 {
1762 res = generate_PCALL(cctx, argcount, FALSE);
1763 goto theend;
1764 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001765
1766 // The function may be defined only later. Need to figure out at runtime.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001767 res = generate_UCALL(cctx, name, argcount);
1768
1769theend:
1770 vim_free(tofree);
1771 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001772}
1773
1774// like NAMESPACE_CHAR but with 'a' and 'l'.
1775#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
1776
1777/*
1778 * Find the end of a variable or function name. Unlike find_name_end() this
1779 * does not recognize magic braces.
1780 * Return a pointer to just after the name. Equal to "arg" if there is no
1781 * valid name.
1782 */
1783 char_u *
1784to_name_end(char_u *arg)
1785{
1786 char_u *p;
1787
1788 // Quick check for valid starting character.
1789 if (!eval_isnamec1(*arg))
1790 return arg;
1791
1792 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
1793 // Include a namespace such as "s:var" and "v:var". But "n:" is not
1794 // and can be used in slice "[n:]".
1795 if (*p == ':' && (p != arg + 1
1796 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
1797 break;
1798 return p;
1799}
1800
1801/*
1802 * Like to_name_end() but also skip over a list or dict constant.
1803 */
1804 char_u *
1805to_name_const_end(char_u *arg)
1806{
1807 char_u *p = to_name_end(arg);
1808 typval_T rettv;
1809
1810 if (p == arg && *arg == '[')
1811 {
1812
1813 // Can be "[1, 2, 3]->Func()".
1814 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
1815 p = arg;
1816 }
1817 else if (p == arg && *arg == '#' && arg[1] == '{')
1818 {
1819 ++p;
1820 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
1821 p = arg;
1822 }
1823 else if (p == arg && *arg == '{')
1824 {
1825 int ret = get_lambda_tv(&p, &rettv, FALSE);
1826
1827 if (ret == NOTDONE)
1828 ret = eval_dict(&p, &rettv, FALSE, FALSE);
1829 if (ret != OK)
1830 p = arg;
1831 }
1832
1833 return p;
1834}
1835
1836 static void
1837type_mismatch(type_T *expected, type_T *actual)
1838{
1839 char *tofree1, *tofree2;
1840
1841 semsg(_("E1013: type mismatch, expected %s but got %s"),
1842 type_name(expected, &tofree1), type_name(actual, &tofree2));
1843 vim_free(tofree1);
1844 vim_free(tofree2);
1845}
1846
1847/*
1848 * Check if the expected and actual types match.
1849 */
1850 static int
1851check_type(type_T *expected, type_T *actual, int give_msg)
1852{
1853 if (expected->tt_type != VAR_UNKNOWN)
1854 {
1855 if (expected->tt_type != actual->tt_type)
1856 {
1857 if (give_msg)
1858 type_mismatch(expected, actual);
1859 return FAIL;
1860 }
1861 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
1862 {
Bram Moolenaar436472f2020-02-20 22:54:43 +01001863 int ret;
1864
1865 // void is used for an empty list or dict
1866 if (actual->tt_member == &t_void)
1867 ret = OK;
1868 else
1869 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001870 if (ret == FAIL && give_msg)
1871 type_mismatch(expected, actual);
1872 return ret;
1873 }
1874 }
1875 return OK;
1876}
1877
1878/*
1879 * Check that
1880 * - "actual" is "expected" type or
1881 * - "actual" is a type that can be "expected" type: add a runtime check; or
1882 * - return FAIL.
1883 */
1884 static int
1885need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
1886{
Bram Moolenaar436472f2020-02-20 22:54:43 +01001887 if (check_type(expected, actual, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001888 return OK;
1889 if (actual->tt_type != VAR_UNKNOWN)
1890 {
1891 type_mismatch(expected, actual);
1892 return FAIL;
1893 }
1894 generate_TYPECHECK(cctx, expected, offset);
1895 return OK;
1896}
1897
1898/*
1899 * parse a list: [expr, expr]
1900 * "*arg" points to the '['.
1901 */
1902 static int
1903compile_list(char_u **arg, cctx_T *cctx)
1904{
1905 char_u *p = skipwhite(*arg + 1);
1906 int count = 0;
1907
1908 while (*p != ']')
1909 {
1910 if (*p == NUL)
1911 return FAIL;
1912 if (compile_expr1(&p, cctx) == FAIL)
1913 break;
1914 ++count;
1915 if (*p == ',')
1916 ++p;
1917 p = skipwhite(p);
1918 }
1919 *arg = p + 1;
1920
1921 generate_NEWLIST(cctx, count);
1922 return OK;
1923}
1924
1925/*
1926 * parse a lambda: {arg, arg -> expr}
1927 * "*arg" points to the '{'.
1928 */
1929 static int
1930compile_lambda(char_u **arg, cctx_T *cctx)
1931{
1932 garray_T *instr = &cctx->ctx_instr;
1933 typval_T rettv;
1934 ufunc_T *ufunc;
1935
1936 // Get the funcref in "rettv".
1937 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
1938 return FAIL;
1939 ufunc = rettv.vval.v_partial->pt_func;
1940
1941 // The function will have one line: "return {expr}".
1942 // Compile it into instructions.
1943 compile_def_function(ufunc, TRUE);
1944
1945 if (ufunc->uf_dfunc_idx >= 0)
1946 {
1947 if (ga_grow(instr, 1) == FAIL)
1948 return FAIL;
1949 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
1950 return OK;
1951 }
1952 return FAIL;
1953}
1954
1955/*
1956 * Compile a lamda call: expr->{lambda}(args)
1957 * "arg" points to the "{".
1958 */
1959 static int
1960compile_lambda_call(char_u **arg, cctx_T *cctx)
1961{
1962 ufunc_T *ufunc;
1963 typval_T rettv;
1964 int argcount = 1;
1965 int ret = FAIL;
1966
1967 // Get the funcref in "rettv".
1968 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
1969 return FAIL;
1970
1971 if (**arg != '(')
1972 {
1973 if (*skipwhite(*arg) == '(')
1974 semsg(_(e_nowhitespace));
1975 else
1976 semsg(_(e_missing_paren), "lambda");
1977 clear_tv(&rettv);
1978 return FAIL;
1979 }
1980
1981 // The function will have one line: "return {expr}".
1982 // Compile it into instructions.
1983 ufunc = rettv.vval.v_partial->pt_func;
1984 ++ufunc->uf_refcount;
1985 compile_def_function(ufunc, TRUE);
1986
1987 // compile the arguments
1988 *arg = skipwhite(*arg + 1);
1989 if (compile_arguments(arg, cctx, &argcount) == OK)
1990 // call the compiled function
1991 ret = generate_CALL(cctx, ufunc, argcount);
1992
1993 clear_tv(&rettv);
1994 return ret;
1995}
1996
1997/*
1998 * parse a dict: {'key': val} or #{key: val}
1999 * "*arg" points to the '{'.
2000 */
2001 static int
2002compile_dict(char_u **arg, cctx_T *cctx, int literal)
2003{
2004 garray_T *instr = &cctx->ctx_instr;
2005 int count = 0;
2006 dict_T *d = dict_alloc();
2007 dictitem_T *item;
2008
2009 if (d == NULL)
2010 return FAIL;
2011 *arg = skipwhite(*arg + 1);
2012 while (**arg != '}' && **arg != NUL)
2013 {
2014 char_u *key = NULL;
2015
2016 if (literal)
2017 {
2018 char_u *p = to_name_end(*arg);
2019
2020 if (p == *arg)
2021 {
2022 semsg(_("E1014: Invalid key: %s"), *arg);
2023 return FAIL;
2024 }
2025 key = vim_strnsave(*arg, p - *arg);
2026 if (generate_PUSHS(cctx, key) == FAIL)
2027 return FAIL;
2028 *arg = p;
2029 }
2030 else
2031 {
2032 isn_T *isn;
2033
2034 if (compile_expr1(arg, cctx) == FAIL)
2035 return FAIL;
2036 // TODO: check type is string
2037 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2038 if (isn->isn_type == ISN_PUSHS)
2039 key = isn->isn_arg.string;
2040 }
2041
2042 // Check for duplicate keys, if using string keys.
2043 if (key != NULL)
2044 {
2045 item = dict_find(d, key, -1);
2046 if (item != NULL)
2047 {
2048 semsg(_(e_duplicate_key), key);
2049 goto failret;
2050 }
2051 item = dictitem_alloc(key);
2052 if (item != NULL)
2053 {
2054 item->di_tv.v_type = VAR_UNKNOWN;
2055 item->di_tv.v_lock = 0;
2056 if (dict_add(d, item) == FAIL)
2057 dictitem_free(item);
2058 }
2059 }
2060
2061 *arg = skipwhite(*arg);
2062 if (**arg != ':')
2063 {
2064 semsg(_(e_missing_dict_colon), *arg);
2065 return FAIL;
2066 }
2067
2068 *arg = skipwhite(*arg + 1);
2069 if (compile_expr1(arg, cctx) == FAIL)
2070 return FAIL;
2071 ++count;
2072
2073 if (**arg == '}')
2074 break;
2075 if (**arg != ',')
2076 {
2077 semsg(_(e_missing_dict_comma), *arg);
2078 goto failret;
2079 }
2080 *arg = skipwhite(*arg + 1);
2081 }
2082
2083 if (**arg != '}')
2084 {
2085 semsg(_(e_missing_dict_end), *arg);
2086 goto failret;
2087 }
2088 *arg = *arg + 1;
2089
2090 dict_unref(d);
2091 return generate_NEWDICT(cctx, count);
2092
2093failret:
2094 dict_unref(d);
2095 return FAIL;
2096}
2097
2098/*
2099 * Compile "&option".
2100 */
2101 static int
2102compile_get_option(char_u **arg, cctx_T *cctx)
2103{
2104 typval_T rettv;
2105 char_u *start = *arg;
2106 int ret;
2107
2108 // parse the option and get the current value to get the type.
2109 rettv.v_type = VAR_UNKNOWN;
2110 ret = get_option_tv(arg, &rettv, TRUE);
2111 if (ret == OK)
2112 {
2113 // include the '&' in the name, get_option_tv() expects it.
2114 char_u *name = vim_strnsave(start, *arg - start);
2115 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2116
2117 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2118 vim_free(name);
2119 }
2120 clear_tv(&rettv);
2121
2122 return ret;
2123}
2124
2125/*
2126 * Compile "$VAR".
2127 */
2128 static int
2129compile_get_env(char_u **arg, cctx_T *cctx)
2130{
2131 char_u *start = *arg;
2132 int len;
2133 int ret;
2134 char_u *name;
2135
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002136 ++*arg;
2137 len = get_env_len(arg);
2138 if (len == 0)
2139 {
2140 semsg(_(e_syntax_at), start - 1);
2141 return FAIL;
2142 }
2143
2144 // include the '$' in the name, get_env_tv() expects it.
2145 name = vim_strnsave(start, len + 1);
2146 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2147 vim_free(name);
2148 return ret;
2149}
2150
2151/*
2152 * Compile "@r".
2153 */
2154 static int
2155compile_get_register(char_u **arg, cctx_T *cctx)
2156{
2157 int ret;
2158
2159 ++*arg;
2160 if (**arg == NUL)
2161 {
2162 semsg(_(e_syntax_at), *arg - 1);
2163 return FAIL;
2164 }
2165 if (!valid_yank_reg(**arg, TRUE))
2166 {
2167 emsg_invreg(**arg);
2168 return FAIL;
2169 }
2170 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2171 ++*arg;
2172 return ret;
2173}
2174
2175/*
2176 * Apply leading '!', '-' and '+' to constant "rettv".
2177 */
2178 static int
2179apply_leader(typval_T *rettv, char_u *start, char_u *end)
2180{
2181 char_u *p = end;
2182
2183 // this works from end to start
2184 while (p > start)
2185 {
2186 --p;
2187 if (*p == '-' || *p == '+')
2188 {
2189 // only '-' has an effect, for '+' we only check the type
2190#ifdef FEAT_FLOAT
2191 if (rettv->v_type == VAR_FLOAT)
2192 {
2193 if (*p == '-')
2194 rettv->vval.v_float = -rettv->vval.v_float;
2195 }
2196 else
2197#endif
2198 {
2199 varnumber_T val;
2200 int error = FALSE;
2201
2202 // tv_get_number_chk() accepts a string, but we don't want that
2203 // here
2204 if (check_not_string(rettv) == FAIL)
2205 return FAIL;
2206 val = tv_get_number_chk(rettv, &error);
2207 clear_tv(rettv);
2208 if (error)
2209 return FAIL;
2210 if (*p == '-')
2211 val = -val;
2212 rettv->v_type = VAR_NUMBER;
2213 rettv->vval.v_number = val;
2214 }
2215 }
2216 else
2217 {
2218 int v = tv2bool(rettv);
2219
2220 // '!' is permissive in the type.
2221 clear_tv(rettv);
2222 rettv->v_type = VAR_BOOL;
2223 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
2224 }
2225 }
2226 return OK;
2227}
2228
2229/*
2230 * Recognize v: variables that are constants and set "rettv".
2231 */
2232 static void
2233get_vim_constant(char_u **arg, typval_T *rettv)
2234{
2235 if (STRNCMP(*arg, "v:true", 6) == 0)
2236 {
2237 rettv->v_type = VAR_BOOL;
2238 rettv->vval.v_number = VVAL_TRUE;
2239 *arg += 6;
2240 }
2241 else if (STRNCMP(*arg, "v:false", 7) == 0)
2242 {
2243 rettv->v_type = VAR_BOOL;
2244 rettv->vval.v_number = VVAL_FALSE;
2245 *arg += 7;
2246 }
2247 else if (STRNCMP(*arg, "v:null", 6) == 0)
2248 {
2249 rettv->v_type = VAR_SPECIAL;
2250 rettv->vval.v_number = VVAL_NULL;
2251 *arg += 6;
2252 }
2253 else if (STRNCMP(*arg, "v:none", 6) == 0)
2254 {
2255 rettv->v_type = VAR_SPECIAL;
2256 rettv->vval.v_number = VVAL_NONE;
2257 *arg += 6;
2258 }
2259}
2260
2261/*
2262 * Compile code to apply '-', '+' and '!'.
2263 */
2264 static int
2265compile_leader(cctx_T *cctx, char_u *start, char_u *end)
2266{
2267 char_u *p = end;
2268
2269 // this works from end to start
2270 while (p > start)
2271 {
2272 --p;
2273 if (*p == '-' || *p == '+')
2274 {
2275 int negate = *p == '-';
2276 isn_T *isn;
2277
2278 // TODO: check type
2279 while (p > start && (p[-1] == '-' || p[-1] == '+'))
2280 {
2281 --p;
2282 if (*p == '-')
2283 negate = !negate;
2284 }
2285 // only '-' has an effect, for '+' we only check the type
2286 if (negate)
2287 isn = generate_instr(cctx, ISN_NEGATENR);
2288 else
2289 isn = generate_instr(cctx, ISN_CHECKNR);
2290 if (isn == NULL)
2291 return FAIL;
2292 }
2293 else
2294 {
2295 int invert = TRUE;
2296
2297 while (p > start && p[-1] == '!')
2298 {
2299 --p;
2300 invert = !invert;
2301 }
2302 if (generate_2BOOL(cctx, invert) == FAIL)
2303 return FAIL;
2304 }
2305 }
2306 return OK;
2307}
2308
2309/*
2310 * Compile whatever comes after "name" or "name()".
2311 */
2312 static int
2313compile_subscript(
2314 char_u **arg,
2315 cctx_T *cctx,
2316 char_u **start_leader,
2317 char_u *end_leader)
2318{
2319 for (;;)
2320 {
2321 if (**arg == '(')
2322 {
2323 int argcount = 0;
2324
2325 // funcref(arg)
2326 *arg = skipwhite(*arg + 1);
2327 if (compile_arguments(arg, cctx, &argcount) == FAIL)
2328 return FAIL;
2329 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
2330 return FAIL;
2331 }
2332 else if (**arg == '-' && (*arg)[1] == '>')
2333 {
2334 char_u *p;
2335
2336 // something->method()
2337 // Apply the '!', '-' and '+' first:
2338 // -1.0->func() works like (-1.0)->func()
2339 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
2340 return FAIL;
2341 *start_leader = end_leader; // don't apply again later
2342
2343 *arg = skipwhite(*arg + 2);
2344 if (**arg == '{')
2345 {
2346 // lambda call: list->{lambda}
2347 if (compile_lambda_call(arg, cctx) == FAIL)
2348 return FAIL;
2349 }
2350 else
2351 {
2352 // method call: list->method()
2353 for (p = *arg; eval_isnamec1(*p); ++p)
2354 ;
2355 if (*p != '(')
2356 {
2357 semsg(_(e_missing_paren), arg);
2358 return FAIL;
2359 }
2360 // TODO: base value may not be the first argument
2361 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
2362 return FAIL;
2363 }
2364 }
2365 else if (**arg == '[')
2366 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01002367 garray_T *stack;
2368 type_T **typep;
2369
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002370 // list index: list[123]
2371 // TODO: more arguments
2372 // TODO: dict member dict['name']
2373 *arg = skipwhite(*arg + 1);
2374 if (compile_expr1(arg, cctx) == FAIL)
2375 return FAIL;
2376
2377 if (**arg != ']')
2378 {
2379 emsg(_(e_missbrac));
2380 return FAIL;
2381 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01002382 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002383
2384 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
2385 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01002386 stack = &cctx->ctx_type_stack;
2387 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
2388 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
2389 {
2390 emsg(_(e_listreq));
2391 return FAIL;
2392 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01002393 if ((*typep)->tt_type == VAR_LIST)
2394 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395 }
2396 else if (**arg == '.' && (*arg)[1] != '.')
2397 {
2398 char_u *p;
2399
2400 ++*arg;
2401 p = *arg;
2402 // dictionary member: dict.name
2403 if (eval_isnamec1(*p))
2404 while (eval_isnamec(*p))
2405 MB_PTR_ADV(p);
2406 if (p == *arg)
2407 {
2408 semsg(_(e_syntax_at), *arg);
2409 return FAIL;
2410 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002411 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
2412 return FAIL;
2413 *arg = p;
2414 }
2415 else
2416 break;
2417 }
2418
2419 // TODO - see handle_subscript():
2420 // Turn "dict.Func" into a partial for "Func" bound to "dict".
2421 // Don't do this when "Func" is already a partial that was bound
2422 // explicitly (pt_auto is FALSE).
2423
2424 return OK;
2425}
2426
2427/*
2428 * Compile an expression at "*p" and add instructions to "instr".
2429 * "p" is advanced until after the expression, skipping white space.
2430 *
2431 * This is the equivalent of eval1(), eval2(), etc.
2432 */
2433
2434/*
2435 * number number constant
2436 * 0zFFFFFFFF Blob constant
2437 * "string" string constant
2438 * 'string' literal string constant
2439 * &option-name option value
2440 * @r register contents
2441 * identifier variable value
2442 * function() function call
2443 * $VAR environment variable
2444 * (expression) nested expression
2445 * [expr, expr] List
2446 * {key: val, key: val} Dictionary
2447 * #{key: val, key: val} Dictionary with literal keys
2448 *
2449 * Also handle:
2450 * ! in front logical NOT
2451 * - in front unary minus
2452 * + in front unary plus (ignored)
2453 * trailing (arg) funcref/partial call
2454 * trailing [] subscript in String or List
2455 * trailing .name entry in Dictionary
2456 * trailing ->name() method call
2457 */
2458 static int
2459compile_expr7(char_u **arg, cctx_T *cctx)
2460{
2461 typval_T rettv;
2462 char_u *start_leader, *end_leader;
2463 int ret = OK;
2464
2465 /*
2466 * Skip '!', '-' and '+' characters. They are handled later.
2467 */
2468 start_leader = *arg;
2469 while (**arg == '!' || **arg == '-' || **arg == '+')
2470 *arg = skipwhite(*arg + 1);
2471 end_leader = *arg;
2472
2473 rettv.v_type = VAR_UNKNOWN;
2474 switch (**arg)
2475 {
2476 /*
2477 * Number constant.
2478 */
2479 case '0': // also for blob starting with 0z
2480 case '1':
2481 case '2':
2482 case '3':
2483 case '4':
2484 case '5':
2485 case '6':
2486 case '7':
2487 case '8':
2488 case '9':
2489 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
2490 return FAIL;
2491 break;
2492
2493 /*
2494 * String constant: "string".
2495 */
2496 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
2497 return FAIL;
2498 break;
2499
2500 /*
2501 * Literal string constant: 'str''ing'.
2502 */
2503 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
2504 return FAIL;
2505 break;
2506
2507 /*
2508 * Constant Vim variable.
2509 */
2510 case 'v': get_vim_constant(arg, &rettv);
2511 ret = NOTDONE;
2512 break;
2513
2514 /*
2515 * List: [expr, expr]
2516 */
2517 case '[': ret = compile_list(arg, cctx);
2518 break;
2519
2520 /*
2521 * Dictionary: #{key: val, key: val}
2522 */
2523 case '#': if ((*arg)[1] == '{')
2524 {
2525 ++*arg;
2526 ret = compile_dict(arg, cctx, TRUE);
2527 }
2528 else
2529 ret = NOTDONE;
2530 break;
2531
2532 /*
2533 * Lambda: {arg, arg -> expr}
2534 * Dictionary: {'key': val, 'key': val}
2535 */
2536 case '{': {
2537 char_u *start = skipwhite(*arg + 1);
2538
2539 // Find out what comes after the arguments.
2540 ret = get_function_args(&start, '-', NULL,
2541 NULL, NULL, NULL, TRUE);
2542 if (ret != FAIL && *start == '>')
2543 ret = compile_lambda(arg, cctx);
2544 else
2545 ret = compile_dict(arg, cctx, FALSE);
2546 }
2547 break;
2548
2549 /*
2550 * Option value: &name
2551 */
2552 case '&': ret = compile_get_option(arg, cctx);
2553 break;
2554
2555 /*
2556 * Environment variable: $VAR.
2557 */
2558 case '$': ret = compile_get_env(arg, cctx);
2559 break;
2560
2561 /*
2562 * Register contents: @r.
2563 */
2564 case '@': ret = compile_get_register(arg, cctx);
2565 break;
2566 /*
2567 * nested expression: (expression).
2568 */
2569 case '(': *arg = skipwhite(*arg + 1);
2570 ret = compile_expr1(arg, cctx); // recursive!
2571 *arg = skipwhite(*arg);
2572 if (**arg == ')')
2573 ++*arg;
2574 else if (ret == OK)
2575 {
2576 emsg(_(e_missing_close));
2577 ret = FAIL;
2578 }
2579 break;
2580
2581 default: ret = NOTDONE;
2582 break;
2583 }
2584 if (ret == FAIL)
2585 return FAIL;
2586
2587 if (rettv.v_type != VAR_UNKNOWN)
2588 {
2589 // apply the '!', '-' and '+' before the constant
2590 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
2591 {
2592 clear_tv(&rettv);
2593 return FAIL;
2594 }
2595 start_leader = end_leader; // don't apply again below
2596
2597 // push constant
2598 switch (rettv.v_type)
2599 {
2600 case VAR_BOOL:
2601 generate_PUSHBOOL(cctx, rettv.vval.v_number);
2602 break;
2603 case VAR_SPECIAL:
2604 generate_PUSHSPEC(cctx, rettv.vval.v_number);
2605 break;
2606 case VAR_NUMBER:
2607 generate_PUSHNR(cctx, rettv.vval.v_number);
2608 break;
2609#ifdef FEAT_FLOAT
2610 case VAR_FLOAT:
2611 generate_PUSHF(cctx, rettv.vval.v_float);
2612 break;
2613#endif
2614 case VAR_BLOB:
2615 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
2616 rettv.vval.v_blob = NULL;
2617 break;
2618 case VAR_STRING:
2619 generate_PUSHS(cctx, rettv.vval.v_string);
2620 rettv.vval.v_string = NULL;
2621 break;
2622 default:
2623 iemsg("constant type missing");
2624 return FAIL;
2625 }
2626 }
2627 else if (ret == NOTDONE)
2628 {
2629 char_u *p;
2630 int r;
2631
2632 if (!eval_isnamec1(**arg))
2633 {
2634 semsg(_("E1015: Name expected: %s"), *arg);
2635 return FAIL;
2636 }
2637
2638 // "name" or "name()"
2639 p = to_name_end(*arg);
2640 if (*p == '(')
2641 r = compile_call(arg, p - *arg, cctx, 0);
2642 else
2643 r = compile_load(arg, p, cctx, TRUE);
2644 if (r == FAIL)
2645 return FAIL;
2646 }
2647
2648 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
2649 return FAIL;
2650
2651 // Now deal with prefixed '-', '+' and '!', if not done already.
2652 return compile_leader(cctx, start_leader, end_leader);
2653}
2654
2655/*
2656 * * number multiplication
2657 * / number division
2658 * % number modulo
2659 */
2660 static int
2661compile_expr6(char_u **arg, cctx_T *cctx)
2662{
2663 char_u *op;
2664
2665 // get the first variable
2666 if (compile_expr7(arg, cctx) == FAIL)
2667 return FAIL;
2668
2669 /*
2670 * Repeat computing, until no "*", "/" or "%" is following.
2671 */
2672 for (;;)
2673 {
2674 op = skipwhite(*arg);
2675 if (*op != '*' && *op != '/' && *op != '%')
2676 break;
2677 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[1]))
2678 {
2679 char_u buf[3];
2680
2681 vim_strncpy(buf, op, 1);
2682 semsg(_(e_white_both), buf);
2683 }
2684 *arg = skipwhite(op + 1);
2685
2686 // get the second variable
2687 if (compile_expr7(arg, cctx) == FAIL)
2688 return FAIL;
2689
2690 generate_two_op(cctx, op);
2691 }
2692
2693 return OK;
2694}
2695
2696/*
2697 * + number addition
2698 * - number subtraction
2699 * .. string concatenation
2700 */
2701 static int
2702compile_expr5(char_u **arg, cctx_T *cctx)
2703{
2704 char_u *op;
2705 int oplen;
2706
2707 // get the first variable
2708 if (compile_expr6(arg, cctx) == FAIL)
2709 return FAIL;
2710
2711 /*
2712 * Repeat computing, until no "+", "-" or ".." is following.
2713 */
2714 for (;;)
2715 {
2716 op = skipwhite(*arg);
2717 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
2718 break;
2719 oplen = (*op == '.' ? 2 : 1);
2720
2721 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[oplen]))
2722 {
2723 char_u buf[3];
2724
2725 vim_strncpy(buf, op, oplen);
2726 semsg(_(e_white_both), buf);
2727 }
2728
2729 *arg = skipwhite(op + oplen);
2730
2731 // get the second variable
2732 if (compile_expr6(arg, cctx) == FAIL)
2733 return FAIL;
2734
2735 if (*op == '.')
2736 {
2737 if (may_generate_2STRING(-2, cctx) == FAIL
2738 || may_generate_2STRING(-1, cctx) == FAIL)
2739 return FAIL;
2740 generate_instr_drop(cctx, ISN_CONCAT, 1);
2741 }
2742 else
2743 generate_two_op(cctx, op);
2744 }
2745
2746 return OK;
2747}
2748
2749/*
2750 * expr5a == expr5b
2751 * expr5a =~ expr5b
2752 * expr5a != expr5b
2753 * expr5a !~ expr5b
2754 * expr5a > expr5b
2755 * expr5a >= expr5b
2756 * expr5a < expr5b
2757 * expr5a <= expr5b
2758 * expr5a is expr5b
2759 * expr5a isnot expr5b
2760 *
2761 * Produces instructions:
2762 * EVAL expr5a Push result of "expr5a"
2763 * EVAL expr5b Push result of "expr5b"
2764 * COMPARE one of the compare instructions
2765 */
2766 static int
2767compile_expr4(char_u **arg, cctx_T *cctx)
2768{
2769 exptype_T type = EXPR_UNKNOWN;
2770 char_u *p;
2771 int len = 2;
2772 int i;
2773 int type_is = FALSE;
2774
2775 // get the first variable
2776 if (compile_expr5(arg, cctx) == FAIL)
2777 return FAIL;
2778
2779 p = skipwhite(*arg);
2780 switch (p[0])
2781 {
2782 case '=': if (p[1] == '=')
2783 type = EXPR_EQUAL;
2784 else if (p[1] == '~')
2785 type = EXPR_MATCH;
2786 break;
2787 case '!': if (p[1] == '=')
2788 type = EXPR_NEQUAL;
2789 else if (p[1] == '~')
2790 type = EXPR_NOMATCH;
2791 break;
2792 case '>': if (p[1] != '=')
2793 {
2794 type = EXPR_GREATER;
2795 len = 1;
2796 }
2797 else
2798 type = EXPR_GEQUAL;
2799 break;
2800 case '<': if (p[1] != '=')
2801 {
2802 type = EXPR_SMALLER;
2803 len = 1;
2804 }
2805 else
2806 type = EXPR_SEQUAL;
2807 break;
2808 case 'i': if (p[1] == 's')
2809 {
2810 // "is" and "isnot"; but not a prefix of a name
2811 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
2812 len = 5;
2813 i = p[len];
2814 if (!isalnum(i) && i != '_')
2815 {
2816 type = len == 2 ? EXPR_IS : EXPR_ISNOT;
2817 type_is = TRUE;
2818 }
2819 }
2820 break;
2821 }
2822
2823 /*
2824 * If there is a comparative operator, use it.
2825 */
2826 if (type != EXPR_UNKNOWN)
2827 {
2828 int ic = FALSE; // Default: do not ignore case
2829
2830 if (type_is && (p[len] == '?' || p[len] == '#'))
2831 {
2832 semsg(_(e_invexpr2), *arg);
2833 return FAIL;
2834 }
2835 // extra question mark appended: ignore case
2836 if (p[len] == '?')
2837 {
2838 ic = TRUE;
2839 ++len;
2840 }
2841 // extra '#' appended: match case (ignored)
2842 else if (p[len] == '#')
2843 ++len;
2844 // nothing appended: match case
2845
2846 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[len]))
2847 {
2848 char_u buf[7];
2849
2850 vim_strncpy(buf, p, len);
2851 semsg(_(e_white_both), buf);
2852 }
2853
2854 // get the second variable
2855 *arg = skipwhite(p + len);
2856 if (compile_expr5(arg, cctx) == FAIL)
2857 return FAIL;
2858
2859 generate_COMPARE(cctx, type, ic);
2860 }
2861
2862 return OK;
2863}
2864
2865/*
2866 * Compile || or &&.
2867 */
2868 static int
2869compile_and_or(char_u **arg, cctx_T *cctx, char *op)
2870{
2871 char_u *p = skipwhite(*arg);
2872 int opchar = *op;
2873
2874 if (p[0] == opchar && p[1] == opchar)
2875 {
2876 garray_T *instr = &cctx->ctx_instr;
2877 garray_T end_ga;
2878
2879 /*
2880 * Repeat until there is no following "||" or "&&"
2881 */
2882 ga_init2(&end_ga, sizeof(int), 10);
2883 while (p[0] == opchar && p[1] == opchar)
2884 {
2885 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
2886 semsg(_(e_white_both), op);
2887
2888 if (ga_grow(&end_ga, 1) == FAIL)
2889 {
2890 ga_clear(&end_ga);
2891 return FAIL;
2892 }
2893 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
2894 ++end_ga.ga_len;
2895 generate_JUMP(cctx, opchar == '|'
2896 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
2897
2898 // eval the next expression
2899 *arg = skipwhite(p + 2);
2900 if ((opchar == '|' ? compile_expr3(arg, cctx)
2901 : compile_expr4(arg, cctx)) == FAIL)
2902 {
2903 ga_clear(&end_ga);
2904 return FAIL;
2905 }
2906 p = skipwhite(*arg);
2907 }
2908
2909 // Fill in the end label in all jumps.
2910 while (end_ga.ga_len > 0)
2911 {
2912 isn_T *isn;
2913
2914 --end_ga.ga_len;
2915 isn = ((isn_T *)instr->ga_data)
2916 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
2917 isn->isn_arg.jump.jump_where = instr->ga_len;
2918 }
2919 ga_clear(&end_ga);
2920 }
2921
2922 return OK;
2923}
2924
2925/*
2926 * expr4a && expr4a && expr4a logical AND
2927 *
2928 * Produces instructions:
2929 * EVAL expr4a Push result of "expr4a"
2930 * JUMP_AND_KEEP_IF_FALSE end
2931 * EVAL expr4b Push result of "expr4b"
2932 * JUMP_AND_KEEP_IF_FALSE end
2933 * EVAL expr4c Push result of "expr4c"
2934 * end:
2935 */
2936 static int
2937compile_expr3(char_u **arg, cctx_T *cctx)
2938{
2939 // get the first variable
2940 if (compile_expr4(arg, cctx) == FAIL)
2941 return FAIL;
2942
2943 // || and && work almost the same
2944 return compile_and_or(arg, cctx, "&&");
2945}
2946
2947/*
2948 * expr3a || expr3b || expr3c logical OR
2949 *
2950 * Produces instructions:
2951 * EVAL expr3a Push result of "expr3a"
2952 * JUMP_AND_KEEP_IF_TRUE end
2953 * EVAL expr3b Push result of "expr3b"
2954 * JUMP_AND_KEEP_IF_TRUE end
2955 * EVAL expr3c Push result of "expr3c"
2956 * end:
2957 */
2958 static int
2959compile_expr2(char_u **arg, cctx_T *cctx)
2960{
2961 // eval the first expression
2962 if (compile_expr3(arg, cctx) == FAIL)
2963 return FAIL;
2964
2965 // || and && work almost the same
2966 return compile_and_or(arg, cctx, "||");
2967}
2968
2969/*
2970 * Toplevel expression: expr2 ? expr1a : expr1b
2971 *
2972 * Produces instructions:
2973 * EVAL expr2 Push result of "expr"
2974 * JUMP_IF_FALSE alt jump if false
2975 * EVAL expr1a
2976 * JUMP_ALWAYS end
2977 * alt: EVAL expr1b
2978 * end:
2979 */
2980 static int
2981compile_expr1(char_u **arg, cctx_T *cctx)
2982{
2983 char_u *p;
2984
2985 // evaluate the first expression
2986 if (compile_expr2(arg, cctx) == FAIL)
2987 return FAIL;
2988
2989 p = skipwhite(*arg);
2990 if (*p == '?')
2991 {
2992 garray_T *instr = &cctx->ctx_instr;
2993 garray_T *stack = &cctx->ctx_type_stack;
2994 int alt_idx = instr->ga_len;
2995 int end_idx;
2996 isn_T *isn;
2997 type_T *type1;
2998 type_T *type2;
2999
3000 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3001 semsg(_(e_white_both), "?");
3002
3003 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3004
3005 // evaluate the second expression; any type is accepted
3006 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003007 if (compile_expr1(arg, cctx) == FAIL)
3008 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003009
3010 // remember the type and drop it
3011 --stack->ga_len;
3012 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3013
3014 end_idx = instr->ga_len;
3015 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3016
3017 // jump here from JUMP_IF_FALSE
3018 isn = ((isn_T *)instr->ga_data) + alt_idx;
3019 isn->isn_arg.jump.jump_where = instr->ga_len;
3020
3021 // Check for the ":".
3022 p = skipwhite(*arg);
3023 if (*p != ':')
3024 {
3025 emsg(_(e_missing_colon));
3026 return FAIL;
3027 }
3028 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3029 semsg(_(e_white_both), ":");
3030
3031 // evaluate the third expression
3032 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003033 if (compile_expr1(arg, cctx) == FAIL)
3034 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003035
3036 // If the types differ, the result has a more generic type.
3037 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3038 common_type(type1, type2, type2);
3039
3040 // jump here from JUMP_ALWAYS
3041 isn = ((isn_T *)instr->ga_data) + end_idx;
3042 isn->isn_arg.jump.jump_where = instr->ga_len;
3043 }
3044 return OK;
3045}
3046
3047/*
3048 * compile "return [expr]"
3049 */
3050 static char_u *
3051compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3052{
3053 char_u *p = arg;
3054 garray_T *stack = &cctx->ctx_type_stack;
3055 type_T *stack_type;
3056
3057 if (*p != NUL && *p != '|' && *p != '\n')
3058 {
3059 // compile return argument into instructions
3060 if (compile_expr1(&p, cctx) == FAIL)
3061 return NULL;
3062
3063 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3064 if (set_return_type)
3065 cctx->ctx_ufunc->uf_ret_type = stack_type;
3066 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3067 == FAIL)
3068 return NULL;
3069 }
3070 else
3071 {
3072 if (set_return_type)
3073 cctx->ctx_ufunc->uf_ret_type = &t_void;
3074 else if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID)
3075 {
3076 emsg(_("E1003: Missing return value"));
3077 return NULL;
3078 }
3079
3080 // No argument, return zero.
3081 generate_PUSHNR(cctx, 0);
3082 }
3083
3084 if (generate_instr(cctx, ISN_RETURN) == NULL)
3085 return NULL;
3086
3087 // "return val | endif" is possible
3088 return skipwhite(p);
3089}
3090
3091/*
3092 * Return the length of an assignment operator, or zero if there isn't one.
3093 */
3094 int
3095assignment_len(char_u *p, int *heredoc)
3096{
3097 if (*p == '=')
3098 {
3099 if (p[1] == '<' && p[2] == '<')
3100 {
3101 *heredoc = TRUE;
3102 return 3;
3103 }
3104 return 1;
3105 }
3106 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3107 return 2;
3108 if (STRNCMP(p, "..=", 3) == 0)
3109 return 3;
3110 return 0;
3111}
3112
3113// words that cannot be used as a variable
3114static char *reserved[] = {
3115 "true",
3116 "false",
3117 NULL
3118};
3119
3120/*
3121 * Get a line for "=<<".
3122 * Return a pointer to the line in allocated memory.
3123 * Return NULL for end-of-file or some error.
3124 */
3125 static char_u *
3126heredoc_getline(
3127 int c UNUSED,
3128 void *cookie,
3129 int indent UNUSED,
3130 int do_concat UNUSED)
3131{
3132 cctx_T *cctx = (cctx_T *)cookie;
3133
3134 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
3135 NULL;
3136 ++cctx->ctx_lnum;
3137 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3138 [cctx->ctx_lnum]);
3139}
3140
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003141typedef enum {
3142 dest_local,
3143 dest_option,
3144 dest_env,
3145 dest_global,
3146 dest_vimvar,
3147 dest_script,
3148 dest_reg,
3149} assign_dest_T;
3150
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003151/*
3152 * compile "let var [= expr]", "const var = expr" and "var = expr"
3153 * "arg" points to "var".
3154 */
3155 static char_u *
3156compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3157{
3158 char_u *p;
3159 char_u *ret = NULL;
3160 int var_count = 0;
3161 int semicolon = 0;
3162 size_t varlen;
3163 garray_T *instr = &cctx->ctx_instr;
3164 int idx = -1;
3165 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003166 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003167 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003168 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003169 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003170 int oplen = 0;
3171 int heredoc = FALSE;
3172 type_T *type;
3173 lvar_T *lvar;
3174 char_u *name;
3175 char_u *sp;
3176 int has_type = FALSE;
3177 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
3178 int instr_count = -1;
3179
3180 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
3181 if (p == NULL)
3182 return NULL;
3183 if (var_count > 0)
3184 {
3185 // TODO: let [var, var] = list
3186 emsg("Cannot handle a list yet");
3187 return NULL;
3188 }
3189
3190 varlen = p - arg;
3191 name = vim_strnsave(arg, (int)varlen);
3192 if (name == NULL)
3193 return NULL;
3194
3195 if (*arg == '&')
3196 {
3197 int cc;
3198 long numval;
3199 char_u *stringval = NULL;
3200
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003201 dest = dest_option;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003202 if (cmdidx == CMD_const)
3203 {
3204 emsg(_(e_const_option));
3205 return NULL;
3206 }
3207 if (is_decl)
3208 {
3209 semsg(_("E1052: Cannot declare an option: %s"), arg);
3210 goto theend;
3211 }
3212 p = arg;
3213 p = find_option_end(&p, &opt_flags);
3214 if (p == NULL)
3215 {
3216 emsg(_(e_letunexp));
3217 return NULL;
3218 }
3219 cc = *p;
3220 *p = NUL;
3221 opt_type = get_option_value(arg + 1, &numval, &stringval, opt_flags);
3222 *p = cc;
3223 if (opt_type == -3)
3224 {
3225 semsg(_(e_unknown_option), *arg);
3226 return NULL;
3227 }
3228 if (opt_type == -2 || opt_type == 0)
3229 type = &t_string;
3230 else
3231 type = &t_number; // both number and boolean option
3232 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003233 else if (*arg == '$')
3234 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003235 dest = dest_env;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003236 if (is_decl)
3237 {
3238 semsg(_("E1065: Cannot declare an environment variable: %s"), name);
3239 goto theend;
3240 }
3241 }
3242 else if (*arg == '@')
3243 {
3244 if (!valid_yank_reg(arg[1], TRUE))
3245 {
3246 emsg_invreg(arg[1]);
3247 return FAIL;
3248 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003249 dest = dest_reg;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003250 if (is_decl)
3251 {
3252 semsg(_("E1066: Cannot declare a register: %s"), name);
3253 goto theend;
3254 }
3255 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003256 else if (STRNCMP(arg, "g:", 2) == 0)
3257 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003258 dest = dest_global;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003259 if (is_decl)
3260 {
3261 semsg(_("E1016: Cannot declare a global variable: %s"), name);
3262 goto theend;
3263 }
3264 }
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003265 else if (STRNCMP(arg, "v:", 2) == 0)
3266 {
3267 vimvaridx = find_vim_var(name + 2);
3268 if (vimvaridx < 0)
3269 {
3270 semsg(_(e_var_notfound), arg);
3271 goto theend;
3272 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003273 dest = dest_vimvar;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003274 if (is_decl)
3275 {
3276 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
3277 goto theend;
3278 }
3279 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003280 else
3281 {
3282 for (idx = 0; reserved[idx] != NULL; ++idx)
3283 if (STRCMP(reserved[idx], name) == 0)
3284 {
3285 semsg(_("E1034: Cannot use reserved name %s"), name);
3286 goto theend;
3287 }
3288
3289 idx = lookup_local(arg, varlen, cctx);
3290 if (idx >= 0)
3291 {
3292 if (is_decl)
3293 {
3294 semsg(_("E1017: Variable already declared: %s"), name);
3295 goto theend;
3296 }
3297 else
3298 {
3299 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3300 if (lvar->lv_const)
3301 {
3302 semsg(_("E1018: Cannot assign to a constant: %s"), name);
3303 goto theend;
3304 }
3305 }
3306 }
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003307 else if (STRNCMP(arg, "s:", 2) == 0
3308 || lookup_script(arg, varlen) == OK
3309 || find_imported(arg, varlen, cctx) != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003310 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003311 dest = dest_script;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003312 if (is_decl)
3313 {
3314 semsg(_("E1054: Variable already declared in the script: %s"),
3315 name);
3316 goto theend;
3317 }
3318 }
3319 }
3320
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003321 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003322 {
3323 if (is_decl && *p == ':')
3324 {
3325 // parse optional type: "let var: type = expr"
3326 p = skipwhite(p + 1);
3327 type = parse_type(&p, cctx->ctx_type_list);
3328 if (type == NULL)
3329 goto theend;
3330 has_type = TRUE;
3331 }
3332 else if (idx < 0)
3333 {
3334 // global and new local default to "any" type
3335 type = &t_any;
3336 }
3337 else
3338 {
3339 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3340 type = lvar->lv_type;
3341 }
3342 }
3343
3344 sp = p;
3345 p = skipwhite(p);
3346 op = p;
3347 oplen = assignment_len(p, &heredoc);
3348 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
3349 {
3350 char_u buf[4];
3351
3352 vim_strncpy(buf, op, oplen);
3353 semsg(_(e_white_both), buf);
3354 }
3355
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003356 if (oplen == 3 && !heredoc && dest != dest_global
3357 && type->tt_type != VAR_STRING && type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003358 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01003359 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003360 goto theend;
3361 }
3362
3363 // +=, /=, etc. require an existing variable
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003364 if (idx < 0 && dest == dest_local)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003365 {
3366 if (oplen > 1 && !heredoc)
3367 {
3368 semsg(_("E1020: cannot use an operator on a new variable: %s"),
3369 name);
3370 goto theend;
3371 }
3372
3373 // new local variable
3374 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
3375 if (idx < 0)
3376 goto theend;
3377 }
3378
3379 if (heredoc)
3380 {
3381 list_T *l;
3382 listitem_T *li;
3383
3384 // [let] varname =<< [trim] {end}
3385 eap->getline = heredoc_getline;
3386 eap->cookie = cctx;
3387 l = heredoc_get(eap, op + 3);
3388
3389 // Push each line and the create the list.
3390 for (li = l->lv_first; li != NULL; li = li->li_next)
3391 {
3392 generate_PUSHS(cctx, li->li_tv.vval.v_string);
3393 li->li_tv.vval.v_string = NULL;
3394 }
3395 generate_NEWLIST(cctx, l->lv_len);
3396 type = &t_list_string;
3397 list_free(l);
3398 p += STRLEN(p);
3399 }
3400 else if (oplen > 0)
3401 {
3402 // for "+=", "*=", "..=" etc. first load the current value
3403 if (*op != '=')
3404 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003405 switch (dest)
3406 {
3407 case dest_option:
3408 // TODO: check the option exists
3409 generate_LOAD(cctx, ISN_LOADOPT, 0, name + 1, type);
3410 break;
3411 case dest_global:
3412 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
3413 break;
3414 case dest_script:
Bram Moolenaarc0d656c2020-02-19 21:12:40 +01003415 compile_load_scriptvar(cctx, name + (name[1] == ':' ? 2 : 0));
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003416 break;
3417 case dest_env:
3418 // Include $ in the name here
3419 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
3420 break;
3421 case dest_reg:
3422 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
3423 break;
3424 case dest_vimvar:
3425 generate_LOADV(cctx, name + 2, TRUE);
3426 break;
3427 case dest_local:
3428 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
3429 break;
3430 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003431 }
3432
3433 // compile the expression
3434 instr_count = instr->ga_len;
3435 p = skipwhite(p + oplen);
3436 if (compile_expr1(&p, cctx) == FAIL)
3437 goto theend;
3438
3439 if (idx >= 0 && (is_decl || !has_type))
3440 {
3441 garray_T *stack = &cctx->ctx_type_stack;
3442 type_T *stacktype =
3443 ((type_T **)stack->ga_data)[stack->ga_len - 1];
3444
3445 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3446 if (!has_type)
3447 {
3448 if (stacktype->tt_type == VAR_VOID)
3449 {
3450 emsg(_("E1031: Cannot use void value"));
3451 goto theend;
3452 }
3453 else
3454 lvar->lv_type = stacktype;
3455 }
3456 else
3457 if (check_type(lvar->lv_type, stacktype, TRUE) == FAIL)
3458 goto theend;
3459 }
3460 }
3461 else if (cmdidx == CMD_const)
3462 {
3463 emsg(_("E1021: const requires a value"));
3464 goto theend;
3465 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003466 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003467 {
3468 emsg(_("E1022: type or initialization required"));
3469 goto theend;
3470 }
3471 else
3472 {
3473 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003474 if (ga_grow(instr, 1) == FAIL)
3475 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01003476 switch (type->tt_type)
3477 {
3478 case VAR_BOOL:
3479 generate_PUSHBOOL(cctx, VVAL_FALSE);
3480 break;
3481 case VAR_SPECIAL:
3482 generate_PUSHSPEC(cctx, VVAL_NONE);
3483 break;
3484 case VAR_FLOAT:
3485#ifdef FEAT_FLOAT
3486 generate_PUSHF(cctx, 0.0);
3487#endif
3488 break;
3489 case VAR_STRING:
3490 generate_PUSHS(cctx, NULL);
3491 break;
3492 case VAR_BLOB:
3493 generate_PUSHBLOB(cctx, NULL);
3494 break;
3495 case VAR_FUNC:
3496 // generate_PUSHS(cctx, NULL); TODO
3497 break;
3498 case VAR_PARTIAL:
3499 // generate_PUSHS(cctx, NULL); TODO
3500 break;
3501 case VAR_LIST:
3502 generate_NEWLIST(cctx, 0);
3503 break;
3504 case VAR_DICT:
3505 generate_NEWDICT(cctx, 0);
3506 break;
3507 case VAR_JOB:
3508 // generate_PUSHS(cctx, NULL); TODO
3509 break;
3510 case VAR_CHANNEL:
3511 // generate_PUSHS(cctx, NULL); TODO
3512 break;
3513 case VAR_NUMBER:
3514 case VAR_UNKNOWN:
3515 case VAR_VOID:
3516 generate_PUSHNR(cctx, 0);
3517 break;
3518 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003519 }
3520
3521 if (oplen > 0 && *op != '=')
3522 {
3523 type_T *expected = &t_number;
3524 garray_T *stack = &cctx->ctx_type_stack;
3525 type_T *stacktype;
3526
3527 // TODO: if type is known use float or any operation
3528
3529 if (*op == '.')
3530 expected = &t_string;
3531 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3532 if (need_type(stacktype, expected, -1, cctx) == FAIL)
3533 goto theend;
3534
3535 if (*op == '.')
3536 generate_instr_drop(cctx, ISN_CONCAT, 1);
3537 else
3538 {
3539 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
3540
3541 if (isn == NULL)
3542 goto theend;
3543 switch (*op)
3544 {
3545 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
3546 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
3547 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
3548 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
3549 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
3550 }
3551 }
3552 }
3553
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003554 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003555 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003556 case dest_option:
3557 generate_STOREOPT(cctx, name + 1, opt_flags);
3558 break;
3559 case dest_global:
3560 // include g: with the name, easier to execute that way
3561 generate_STORE(cctx, ISN_STOREG, 0, name);
3562 break;
3563 case dest_env:
3564 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
3565 break;
3566 case dest_reg:
3567 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
3568 break;
3569 case dest_vimvar:
3570 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
3571 break;
3572 case dest_script:
3573 {
3574 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
3575 imported_T *import = NULL;
3576 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003577
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003578 if (name[1] != ':')
3579 {
3580 import = find_imported(name, 0, cctx);
3581 if (import != NULL)
3582 sid = import->imp_sid;
3583 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003584
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003585 idx = get_script_item_idx(sid, rawname, TRUE);
3586 // TODO: specific type
3587 if (idx < 0)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003588 generate_OLDSCRIPT(cctx, ISN_STORES, name, sid, &t_any);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003589 else
3590 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
3591 sid, idx, &t_any);
3592 }
3593 break;
3594 case dest_local:
3595 {
3596 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003597
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003598 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
3599 // into ISN_STORENR
3600 if (instr->ga_len == instr_count + 1
3601 && isn->isn_type == ISN_PUSHNR)
3602 {
3603 varnumber_T val = isn->isn_arg.number;
3604 garray_T *stack = &cctx->ctx_type_stack;
3605
3606 isn->isn_type = ISN_STORENR;
3607 isn->isn_arg.storenr.str_idx = idx;
3608 isn->isn_arg.storenr.str_val = val;
3609 if (stack->ga_len > 0)
3610 --stack->ga_len;
3611 }
3612 else
3613 generate_STORE(cctx, ISN_STORE, idx, NULL);
3614 }
3615 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003616 }
3617 ret = p;
3618
3619theend:
3620 vim_free(name);
3621 return ret;
3622}
3623
3624/*
3625 * Compile an :import command.
3626 */
3627 static char_u *
3628compile_import(char_u *arg, cctx_T *cctx)
3629{
3630 return handle_import(arg, &cctx->ctx_imports, 0);
3631}
3632
3633/*
3634 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
3635 */
3636 static int
3637compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
3638{
3639 garray_T *instr = &cctx->ctx_instr;
3640 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
3641
3642 if (endlabel == NULL)
3643 return FAIL;
3644 endlabel->el_next = *el;
3645 *el = endlabel;
3646 endlabel->el_end_label = instr->ga_len;
3647
3648 generate_JUMP(cctx, when, 0);
3649 return OK;
3650}
3651
3652 static void
3653compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
3654{
3655 garray_T *instr = &cctx->ctx_instr;
3656
3657 while (*el != NULL)
3658 {
3659 endlabel_T *cur = (*el);
3660 isn_T *isn;
3661
3662 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
3663 isn->isn_arg.jump.jump_where = instr->ga_len;
3664 *el = cur->el_next;
3665 vim_free(cur);
3666 }
3667}
3668
3669/*
3670 * Create a new scope and set up the generic items.
3671 */
3672 static scope_T *
3673new_scope(cctx_T *cctx, scopetype_T type)
3674{
3675 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
3676
3677 if (scope == NULL)
3678 return NULL;
3679 scope->se_outer = cctx->ctx_scope;
3680 cctx->ctx_scope = scope;
3681 scope->se_type = type;
3682 scope->se_local_count = cctx->ctx_locals.ga_len;
3683 return scope;
3684}
3685
3686/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003687 * Evaluate an expression that is a constant:
3688 * has(arg)
3689 *
3690 * Also handle:
3691 * ! in front logical NOT
3692 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003693 * Return FAIL if the expression is not a constant.
3694 */
3695 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003696evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003697{
3698 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003699 char_u *start_leader, *end_leader;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003700
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003701 /*
3702 * Skip '!' characters. They are handled later.
3703 */
3704 start_leader = *arg;
3705 while (**arg == '!')
3706 *arg = skipwhite(*arg + 1);
3707 end_leader = *arg;
3708
3709 /*
3710 * Recognize only has() for now.
3711 */
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003712 if (STRNCMP("has(", *arg, 4) != 0)
3713 return FAIL;
3714 *arg = skipwhite(*arg + 4);
3715
3716 if (**arg == '"')
3717 {
3718 if (get_string_tv(arg, tv, TRUE) == FAIL)
3719 return FAIL;
3720 }
3721 else if (**arg == '\'')
3722 {
3723 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
3724 return FAIL;
3725 }
3726 else
3727 return FAIL;
3728
3729 *arg = skipwhite(*arg);
3730 if (**arg != ')')
3731 return FAIL;
3732 *arg = skipwhite(*arg + 1);
3733
3734 argvars[0] = *tv;
3735 argvars[1].v_type = VAR_UNKNOWN;
3736 tv->v_type = VAR_NUMBER;
3737 tv->vval.v_number = 0;
3738 f_has(argvars, tv);
3739 clear_tv(&argvars[0]);
3740
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003741 while (start_leader < end_leader)
3742 {
3743 if (*start_leader == '!')
3744 tv->vval.v_number = !tv->vval.v_number;
3745 ++start_leader;
3746 }
3747
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003748 return OK;
3749}
3750
3751static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
3752
3753/*
3754 * Compile constant || or &&.
3755 */
3756 static int
3757evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
3758{
3759 char_u *p = skipwhite(*arg);
3760 int opchar = *op;
3761
3762 if (p[0] == opchar && p[1] == opchar)
3763 {
3764 int val = tv2bool(tv);
3765
3766 /*
3767 * Repeat until there is no following "||" or "&&"
3768 */
3769 while (p[0] == opchar && p[1] == opchar)
3770 {
3771 typval_T tv2;
3772
3773 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
3774 return FAIL;
3775
3776 // eval the next expression
3777 *arg = skipwhite(p + 2);
3778 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01003779 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003780 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003781 : evaluate_const_expr7(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003782 {
3783 clear_tv(&tv2);
3784 return FAIL;
3785 }
3786 if ((opchar == '&') == val)
3787 {
3788 // false || tv2 or true && tv2: use tv2
3789 clear_tv(tv);
3790 *tv = tv2;
3791 val = tv2bool(tv);
3792 }
3793 else
3794 clear_tv(&tv2);
3795 p = skipwhite(*arg);
3796 }
3797 }
3798
3799 return OK;
3800}
3801
3802/*
3803 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
3804 * Return FAIL if the expression is not a constant.
3805 */
3806 static int
3807evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
3808{
3809 // evaluate the first expression
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003810 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003811 return FAIL;
3812
3813 // || and && work almost the same
3814 return evaluate_const_and_or(arg, cctx, "&&", tv);
3815}
3816
3817/*
3818 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
3819 * Return FAIL if the expression is not a constant.
3820 */
3821 static int
3822evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
3823{
3824 // evaluate the first expression
3825 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
3826 return FAIL;
3827
3828 // || and && work almost the same
3829 return evaluate_const_and_or(arg, cctx, "||", tv);
3830}
3831
3832/*
3833 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
3834 * E.g. for "has('feature')".
3835 * This does not produce error messages. "tv" should be cleared afterwards.
3836 * Return FAIL if the expression is not a constant.
3837 */
3838 static int
3839evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
3840{
3841 char_u *p;
3842
3843 // evaluate the first expression
3844 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
3845 return FAIL;
3846
3847 p = skipwhite(*arg);
3848 if (*p == '?')
3849 {
3850 int val = tv2bool(tv);
3851 typval_T tv2;
3852
3853 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3854 return FAIL;
3855
3856 // evaluate the second expression; any type is accepted
3857 clear_tv(tv);
3858 *arg = skipwhite(p + 1);
3859 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
3860 return FAIL;
3861
3862 // Check for the ":".
3863 p = skipwhite(*arg);
3864 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3865 return FAIL;
3866
3867 // evaluate the third expression
3868 *arg = skipwhite(p + 1);
3869 tv2.v_type = VAR_UNKNOWN;
3870 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
3871 {
3872 clear_tv(&tv2);
3873 return FAIL;
3874 }
3875 if (val)
3876 {
3877 // use the expr after "?"
3878 clear_tv(&tv2);
3879 }
3880 else
3881 {
3882 // use the expr after ":"
3883 clear_tv(tv);
3884 *tv = tv2;
3885 }
3886 }
3887 return OK;
3888}
3889
3890/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003891 * compile "if expr"
3892 *
3893 * "if expr" Produces instructions:
3894 * EVAL expr Push result of "expr"
3895 * JUMP_IF_FALSE end
3896 * ... body ...
3897 * end:
3898 *
3899 * "if expr | else" Produces instructions:
3900 * EVAL expr Push result of "expr"
3901 * JUMP_IF_FALSE else
3902 * ... body ...
3903 * JUMP_ALWAYS end
3904 * else:
3905 * ... body ...
3906 * end:
3907 *
3908 * "if expr1 | elseif expr2 | else" Produces instructions:
3909 * EVAL expr Push result of "expr"
3910 * JUMP_IF_FALSE elseif
3911 * ... body ...
3912 * JUMP_ALWAYS end
3913 * elseif:
3914 * EVAL expr Push result of "expr"
3915 * JUMP_IF_FALSE else
3916 * ... body ...
3917 * JUMP_ALWAYS end
3918 * else:
3919 * ... body ...
3920 * end:
3921 */
3922 static char_u *
3923compile_if(char_u *arg, cctx_T *cctx)
3924{
3925 char_u *p = arg;
3926 garray_T *instr = &cctx->ctx_instr;
3927 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003928 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003929
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003930 // compile "expr"; if we know it evaluates to FALSE skip the block
3931 tv.v_type = VAR_UNKNOWN;
3932 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
3933 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
3934 else
3935 cctx->ctx_skip = MAYBE;
3936 clear_tv(&tv);
3937 if (cctx->ctx_skip == MAYBE)
3938 {
3939 p = arg;
3940 if (compile_expr1(&p, cctx) == FAIL)
3941 return NULL;
3942 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003943
3944 scope = new_scope(cctx, IF_SCOPE);
3945 if (scope == NULL)
3946 return NULL;
3947
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003948 if (cctx->ctx_skip == MAYBE)
3949 {
3950 // "where" is set when ":elseif", "else" or ":endif" is found
3951 scope->se_u.se_if.is_if_label = instr->ga_len;
3952 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3953 }
3954 else
3955 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003956
3957 return p;
3958}
3959
3960 static char_u *
3961compile_elseif(char_u *arg, cctx_T *cctx)
3962{
3963 char_u *p = arg;
3964 garray_T *instr = &cctx->ctx_instr;
3965 isn_T *isn;
3966 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003967 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003968
3969 if (scope == NULL || scope->se_type != IF_SCOPE)
3970 {
3971 emsg(_(e_elseif_without_if));
3972 return NULL;
3973 }
3974 cctx->ctx_locals.ga_len = scope->se_local_count;
3975
Bram Moolenaar158906c2020-02-06 20:39:45 +01003976 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003977 {
3978 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003979 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003980 return NULL;
3981 // previous "if" or "elseif" jumps here
3982 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
3983 isn->isn_arg.jump.jump_where = instr->ga_len;
3984 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003985
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003986 // compile "expr"; if we know it evaluates to FALSE skip the block
3987 tv.v_type = VAR_UNKNOWN;
3988 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
3989 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
3990 else
3991 cctx->ctx_skip = MAYBE;
3992 clear_tv(&tv);
3993 if (cctx->ctx_skip == MAYBE)
3994 {
3995 p = arg;
3996 if (compile_expr1(&p, cctx) == FAIL)
3997 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003998
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003999 // "where" is set when ":elseif", "else" or ":endif" is found
4000 scope->se_u.se_if.is_if_label = instr->ga_len;
4001 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4002 }
4003 else
4004 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004005
4006 return p;
4007}
4008
4009 static char_u *
4010compile_else(char_u *arg, cctx_T *cctx)
4011{
4012 char_u *p = arg;
4013 garray_T *instr = &cctx->ctx_instr;
4014 isn_T *isn;
4015 scope_T *scope = cctx->ctx_scope;
4016
4017 if (scope == NULL || scope->se_type != IF_SCOPE)
4018 {
4019 emsg(_(e_else_without_if));
4020 return NULL;
4021 }
4022 cctx->ctx_locals.ga_len = scope->se_local_count;
4023
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004024 // jump from previous block to the end, unless the else block is empty
4025 if (cctx->ctx_skip == MAYBE)
4026 {
4027 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004028 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004029 return NULL;
4030 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004031
Bram Moolenaar158906c2020-02-06 20:39:45 +01004032 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004033 {
4034 if (scope->se_u.se_if.is_if_label >= 0)
4035 {
4036 // previous "if" or "elseif" jumps here
4037 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4038 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01004039 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004040 }
4041 }
4042
4043 if (cctx->ctx_skip != MAYBE)
4044 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004045
4046 return p;
4047}
4048
4049 static char_u *
4050compile_endif(char_u *arg, cctx_T *cctx)
4051{
4052 scope_T *scope = cctx->ctx_scope;
4053 ifscope_T *ifscope;
4054 garray_T *instr = &cctx->ctx_instr;
4055 isn_T *isn;
4056
4057 if (scope == NULL || scope->se_type != IF_SCOPE)
4058 {
4059 emsg(_(e_endif_without_if));
4060 return NULL;
4061 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004062 ifscope = &scope->se_u.se_if;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004063 cctx->ctx_scope = scope->se_outer;
4064 cctx->ctx_locals.ga_len = scope->se_local_count;
4065
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004066 if (scope->se_u.se_if.is_if_label >= 0)
4067 {
4068 // previous "if" or "elseif" jumps here
4069 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4070 isn->isn_arg.jump.jump_where = instr->ga_len;
4071 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004072 // Fill in the "end" label in jumps at the end of the blocks.
4073 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004074 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004075
4076 vim_free(scope);
4077 return arg;
4078}
4079
4080/*
4081 * compile "for var in expr"
4082 *
4083 * Produces instructions:
4084 * PUSHNR -1
4085 * STORE loop-idx Set index to -1
4086 * EVAL expr Push result of "expr"
4087 * top: FOR loop-idx, end Increment index, use list on bottom of stack
4088 * - if beyond end, jump to "end"
4089 * - otherwise get item from list and push it
4090 * STORE var Store item in "var"
4091 * ... body ...
4092 * JUMP top Jump back to repeat
4093 * end: DROP Drop the result of "expr"
4094 *
4095 */
4096 static char_u *
4097compile_for(char_u *arg, cctx_T *cctx)
4098{
4099 char_u *p;
4100 size_t varlen;
4101 garray_T *instr = &cctx->ctx_instr;
4102 garray_T *stack = &cctx->ctx_type_stack;
4103 scope_T *scope;
4104 int loop_idx; // index of loop iteration variable
4105 int var_idx; // index of "var"
4106 type_T *vartype;
4107
4108 // TODO: list of variables: "for [key, value] in dict"
4109 // parse "var"
4110 for (p = arg; eval_isnamec1(*p); ++p)
4111 ;
4112 varlen = p - arg;
4113 var_idx = lookup_local(arg, varlen, cctx);
4114 if (var_idx >= 0)
4115 {
4116 semsg(_("E1023: variable already defined: %s"), arg);
4117 return NULL;
4118 }
4119
4120 // consume "in"
4121 p = skipwhite(p);
4122 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
4123 {
4124 emsg(_(e_missing_in));
4125 return NULL;
4126 }
4127 p = skipwhite(p + 2);
4128
4129
4130 scope = new_scope(cctx, FOR_SCOPE);
4131 if (scope == NULL)
4132 return NULL;
4133
4134 // Reserve a variable to store the loop iteration counter.
4135 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
4136 if (loop_idx < 0)
4137 return NULL;
4138
4139 // Reserve a variable to store "var"
4140 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
4141 if (var_idx < 0)
4142 return NULL;
4143
4144 generate_STORENR(cctx, loop_idx, -1);
4145
4146 // compile "expr", it remains on the stack until "endfor"
4147 arg = p;
4148 if (compile_expr1(&arg, cctx) == FAIL)
4149 return NULL;
4150
4151 // now we know the type of "var"
4152 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4153 if (vartype->tt_type != VAR_LIST)
4154 {
4155 emsg(_("E1024: need a List to iterate over"));
4156 return NULL;
4157 }
4158 if (vartype->tt_member->tt_type != VAR_UNKNOWN)
4159 {
4160 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
4161
4162 lvar->lv_type = vartype->tt_member;
4163 }
4164
4165 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004166 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004167
4168 generate_FOR(cctx, loop_idx);
4169 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
4170
4171 return arg;
4172}
4173
4174/*
4175 * compile "endfor"
4176 */
4177 static char_u *
4178compile_endfor(char_u *arg, cctx_T *cctx)
4179{
4180 garray_T *instr = &cctx->ctx_instr;
4181 scope_T *scope = cctx->ctx_scope;
4182 forscope_T *forscope;
4183 isn_T *isn;
4184
4185 if (scope == NULL || scope->se_type != FOR_SCOPE)
4186 {
4187 emsg(_(e_for));
4188 return NULL;
4189 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004190 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004191 cctx->ctx_scope = scope->se_outer;
4192 cctx->ctx_locals.ga_len = scope->se_local_count;
4193
4194 // At end of ":for" scope jump back to the FOR instruction.
4195 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
4196
4197 // Fill in the "end" label in the FOR statement so it can jump here
4198 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
4199 isn->isn_arg.forloop.for_end = instr->ga_len;
4200
4201 // Fill in the "end" label any BREAK statements
4202 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
4203
4204 // Below the ":for" scope drop the "expr" list from the stack.
4205 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
4206 return NULL;
4207
4208 vim_free(scope);
4209
4210 return arg;
4211}
4212
4213/*
4214 * compile "while expr"
4215 *
4216 * Produces instructions:
4217 * top: EVAL expr Push result of "expr"
4218 * JUMP_IF_FALSE end jump if false
4219 * ... body ...
4220 * JUMP top Jump back to repeat
4221 * end:
4222 *
4223 */
4224 static char_u *
4225compile_while(char_u *arg, cctx_T *cctx)
4226{
4227 char_u *p = arg;
4228 garray_T *instr = &cctx->ctx_instr;
4229 scope_T *scope;
4230
4231 scope = new_scope(cctx, WHILE_SCOPE);
4232 if (scope == NULL)
4233 return NULL;
4234
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004235 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004236
4237 // compile "expr"
4238 if (compile_expr1(&p, cctx) == FAIL)
4239 return NULL;
4240
4241 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004242 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004243 JUMP_IF_FALSE, cctx) == FAIL)
4244 return FAIL;
4245
4246 return p;
4247}
4248
4249/*
4250 * compile "endwhile"
4251 */
4252 static char_u *
4253compile_endwhile(char_u *arg, cctx_T *cctx)
4254{
4255 scope_T *scope = cctx->ctx_scope;
4256
4257 if (scope == NULL || scope->se_type != WHILE_SCOPE)
4258 {
4259 emsg(_(e_while));
4260 return NULL;
4261 }
4262 cctx->ctx_scope = scope->se_outer;
4263 cctx->ctx_locals.ga_len = scope->se_local_count;
4264
4265 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004266 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004267
4268 // Fill in the "end" label in the WHILE statement so it can jump here.
4269 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004270 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004271
4272 vim_free(scope);
4273
4274 return arg;
4275}
4276
4277/*
4278 * compile "continue"
4279 */
4280 static char_u *
4281compile_continue(char_u *arg, cctx_T *cctx)
4282{
4283 scope_T *scope = cctx->ctx_scope;
4284
4285 for (;;)
4286 {
4287 if (scope == NULL)
4288 {
4289 emsg(_(e_continue));
4290 return NULL;
4291 }
4292 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
4293 break;
4294 scope = scope->se_outer;
4295 }
4296
4297 // Jump back to the FOR or WHILE instruction.
4298 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004299 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
4300 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004301 return arg;
4302}
4303
4304/*
4305 * compile "break"
4306 */
4307 static char_u *
4308compile_break(char_u *arg, cctx_T *cctx)
4309{
4310 scope_T *scope = cctx->ctx_scope;
4311 endlabel_T **el;
4312
4313 for (;;)
4314 {
4315 if (scope == NULL)
4316 {
4317 emsg(_(e_break));
4318 return NULL;
4319 }
4320 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
4321 break;
4322 scope = scope->se_outer;
4323 }
4324
4325 // Jump to the end of the FOR or WHILE loop.
4326 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004327 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004328 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004329 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004330 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
4331 return FAIL;
4332
4333 return arg;
4334}
4335
4336/*
4337 * compile "{" start of block
4338 */
4339 static char_u *
4340compile_block(char_u *arg, cctx_T *cctx)
4341{
4342 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
4343 return NULL;
4344 return skipwhite(arg + 1);
4345}
4346
4347/*
4348 * compile end of block: drop one scope
4349 */
4350 static void
4351compile_endblock(cctx_T *cctx)
4352{
4353 scope_T *scope = cctx->ctx_scope;
4354
4355 cctx->ctx_scope = scope->se_outer;
4356 cctx->ctx_locals.ga_len = scope->se_local_count;
4357 vim_free(scope);
4358}
4359
4360/*
4361 * compile "try"
4362 * Creates a new scope for the try-endtry, pointing to the first catch and
4363 * finally.
4364 * Creates another scope for the "try" block itself.
4365 * TRY instruction sets up exception handling at runtime.
4366 *
4367 * "try"
4368 * TRY -> catch1, -> finally push trystack entry
4369 * ... try block
4370 * "throw {exception}"
4371 * EVAL {exception}
4372 * THROW create exception
4373 * ... try block
4374 * " catch {expr}"
4375 * JUMP -> finally
4376 * catch1: PUSH exeception
4377 * EVAL {expr}
4378 * MATCH
4379 * JUMP nomatch -> catch2
4380 * CATCH remove exception
4381 * ... catch block
4382 * " catch"
4383 * JUMP -> finally
4384 * catch2: CATCH remove exception
4385 * ... catch block
4386 * " finally"
4387 * finally:
4388 * ... finally block
4389 * " endtry"
4390 * ENDTRY pop trystack entry, may rethrow
4391 */
4392 static char_u *
4393compile_try(char_u *arg, cctx_T *cctx)
4394{
4395 garray_T *instr = &cctx->ctx_instr;
4396 scope_T *try_scope;
4397 scope_T *scope;
4398
4399 // scope that holds the jumps that go to catch/finally/endtry
4400 try_scope = new_scope(cctx, TRY_SCOPE);
4401 if (try_scope == NULL)
4402 return NULL;
4403
4404 // "catch" is set when the first ":catch" is found.
4405 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004406 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004407 if (generate_instr(cctx, ISN_TRY) == NULL)
4408 return NULL;
4409
4410 // scope for the try block itself
4411 scope = new_scope(cctx, BLOCK_SCOPE);
4412 if (scope == NULL)
4413 return NULL;
4414
4415 return arg;
4416}
4417
4418/*
4419 * compile "catch {expr}"
4420 */
4421 static char_u *
4422compile_catch(char_u *arg, cctx_T *cctx UNUSED)
4423{
4424 scope_T *scope = cctx->ctx_scope;
4425 garray_T *instr = &cctx->ctx_instr;
4426 char_u *p;
4427 isn_T *isn;
4428
4429 // end block scope from :try or :catch
4430 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
4431 compile_endblock(cctx);
4432 scope = cctx->ctx_scope;
4433
4434 // Error if not in a :try scope
4435 if (scope == NULL || scope->se_type != TRY_SCOPE)
4436 {
4437 emsg(_(e_catch));
4438 return NULL;
4439 }
4440
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004441 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004442 {
4443 emsg(_("E1033: catch unreachable after catch-all"));
4444 return NULL;
4445 }
4446
4447 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004448 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004449 JUMP_ALWAYS, cctx) == FAIL)
4450 return NULL;
4451
4452 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004453 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004454 if (isn->isn_arg.try.try_catch == 0)
4455 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004456 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004457 {
4458 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004459 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004460 isn->isn_arg.jump.jump_where = instr->ga_len;
4461 }
4462
4463 p = skipwhite(arg);
4464 if (ends_excmd(*p))
4465 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004466 scope->se_u.se_try.ts_caught_all = TRUE;
4467 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004468 }
4469 else
4470 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004471 char_u *end;
4472 char_u *pat;
4473 char_u *tofree = NULL;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01004474 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004475
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004476 // Push v:exception, push {expr} and MATCH
4477 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
4478
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004479 end = skip_regexp(p + 1, *p, TRUE, &tofree);
4480 if (*end != *p)
4481 {
4482 semsg(_("E1067: Separator mismatch: %s"), p);
4483 vim_free(tofree);
4484 return FAIL;
4485 }
4486 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01004487 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004488 else
Bram Moolenaar3dd64602020-02-13 20:31:28 +01004489 len = (int)(end - (tofree + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004490 pat = vim_strnsave(p + 1, len);
4491 vim_free(tofree);
4492 p += len + 2;
4493 if (pat == NULL)
4494 return FAIL;
4495 if (generate_PUSHS(cctx, pat) == FAIL)
4496 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004497
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004498 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
4499 return NULL;
4500
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004501 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004502 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
4503 return NULL;
4504 }
4505
4506 if (generate_instr(cctx, ISN_CATCH) == NULL)
4507 return NULL;
4508
4509 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
4510 return NULL;
4511 return p;
4512}
4513
4514 static char_u *
4515compile_finally(char_u *arg, cctx_T *cctx)
4516{
4517 scope_T *scope = cctx->ctx_scope;
4518 garray_T *instr = &cctx->ctx_instr;
4519 isn_T *isn;
4520
4521 // end block scope from :try or :catch
4522 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
4523 compile_endblock(cctx);
4524 scope = cctx->ctx_scope;
4525
4526 // Error if not in a :try scope
4527 if (scope == NULL || scope->se_type != TRY_SCOPE)
4528 {
4529 emsg(_(e_finally));
4530 return NULL;
4531 }
4532
4533 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004534 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004535 if (isn->isn_arg.try.try_finally != 0)
4536 {
4537 emsg(_(e_finally_dup));
4538 return NULL;
4539 }
4540
4541 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004542 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004543
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004544 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004545 {
4546 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004547 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004548 isn->isn_arg.jump.jump_where = instr->ga_len;
4549 }
4550
4551 isn->isn_arg.try.try_finally = instr->ga_len;
4552 // TODO: set index in ts_finally_label jumps
4553
4554 return arg;
4555}
4556
4557 static char_u *
4558compile_endtry(char_u *arg, cctx_T *cctx)
4559{
4560 scope_T *scope = cctx->ctx_scope;
4561 garray_T *instr = &cctx->ctx_instr;
4562 isn_T *isn;
4563
4564 // end block scope from :catch or :finally
4565 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
4566 compile_endblock(cctx);
4567 scope = cctx->ctx_scope;
4568
4569 // Error if not in a :try scope
4570 if (scope == NULL || scope->se_type != TRY_SCOPE)
4571 {
4572 if (scope == NULL)
4573 emsg(_(e_no_endtry));
4574 else if (scope->se_type == WHILE_SCOPE)
4575 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01004576 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004577 emsg(_(e_endfor));
4578 else
4579 emsg(_(e_endif));
4580 return NULL;
4581 }
4582
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004583 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004584 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
4585 {
4586 emsg(_("E1032: missing :catch or :finally"));
4587 return NULL;
4588 }
4589
4590 // Fill in the "end" label in jumps at the end of the blocks, if not done
4591 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004592 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004593
4594 // End :catch or :finally scope: set value in ISN_TRY instruction
4595 if (isn->isn_arg.try.try_finally == 0)
4596 isn->isn_arg.try.try_finally = instr->ga_len;
4597 compile_endblock(cctx);
4598
4599 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
4600 return NULL;
4601 return arg;
4602}
4603
4604/*
4605 * compile "throw {expr}"
4606 */
4607 static char_u *
4608compile_throw(char_u *arg, cctx_T *cctx UNUSED)
4609{
4610 char_u *p = skipwhite(arg);
4611
4612 if (ends_excmd(*p))
4613 {
4614 emsg(_(e_argreq));
4615 return NULL;
4616 }
4617 if (compile_expr1(&p, cctx) == FAIL)
4618 return NULL;
4619 if (may_generate_2STRING(-1, cctx) == FAIL)
4620 return NULL;
4621 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
4622 return NULL;
4623
4624 return p;
4625}
4626
4627/*
4628 * compile "echo expr"
4629 */
4630 static char_u *
4631compile_echo(char_u *arg, int with_white, cctx_T *cctx)
4632{
4633 char_u *p = arg;
4634 int count = 0;
4635
4636 // for ()
4637 {
4638 if (compile_expr1(&p, cctx) == FAIL)
4639 return NULL;
4640 ++count;
4641 }
4642
4643 generate_ECHO(cctx, with_white, count);
4644
4645 return p;
4646}
4647
4648/*
4649 * After ex_function() has collected all the function lines: parse and compile
4650 * the lines into instructions.
4651 * Adds the function to "def_functions".
4652 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
4653 * return statement (used for lambda).
4654 */
4655 void
4656compile_def_function(ufunc_T *ufunc, int set_return_type)
4657{
4658 dfunc_T *dfunc;
4659 char_u *line = NULL;
4660 char_u *p;
4661 exarg_T ea;
4662 char *errormsg = NULL; // error message
4663 int had_return = FALSE;
4664 cctx_T cctx;
4665 garray_T *instr;
4666 int called_emsg_before = called_emsg;
4667 int ret = FAIL;
4668 sctx_T save_current_sctx = current_sctx;
4669
4670 if (ufunc->uf_dfunc_idx >= 0)
4671 {
4672 // redefining a function that was compiled before
4673 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
4674 dfunc->df_deleted = FALSE;
4675 }
4676 else
4677 {
4678 // Add the function to "def_functions".
4679 if (ga_grow(&def_functions, 1) == FAIL)
4680 return;
4681 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
4682 vim_memset(dfunc, 0, sizeof(dfunc_T));
4683 dfunc->df_idx = def_functions.ga_len;
4684 ufunc->uf_dfunc_idx = dfunc->df_idx;
4685 dfunc->df_ufunc = ufunc;
4686 ++def_functions.ga_len;
4687 }
4688
4689 vim_memset(&cctx, 0, sizeof(cctx));
4690 cctx.ctx_ufunc = ufunc;
4691 cctx.ctx_lnum = -1;
4692 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
4693 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
4694 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
4695 cctx.ctx_type_list = &ufunc->uf_type_list;
4696 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
4697 instr = &cctx.ctx_instr;
4698
4699 // Most modern script version.
4700 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
4701
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01004702 if (ufunc->uf_def_args.ga_len > 0)
4703 {
4704 int count = ufunc->uf_def_args.ga_len;
4705 int i;
4706 char_u *arg;
4707 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
4708
4709 // Produce instructions for the default values of optional arguments.
4710 // Store the instruction index in uf_def_arg_idx[] so that we know
4711 // where to start when the function is called, depending on the number
4712 // of arguments.
4713 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
4714 if (ufunc->uf_def_arg_idx == NULL)
4715 goto erret;
4716 for (i = 0; i < count; ++i)
4717 {
4718 ufunc->uf_def_arg_idx[i] = instr->ga_len;
4719 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
4720 if (compile_expr1(&arg, &cctx) == FAIL
4721 || generate_STORE(&cctx, ISN_STORE,
4722 i - count - off, NULL) == FAIL)
4723 goto erret;
4724 }
4725
4726 // If a varargs is following, push an empty list.
4727 if (ufunc->uf_va_name != NULL)
4728 {
4729 if (generate_NEWLIST(&cctx, 0) == FAIL
4730 || generate_STORE(&cctx, ISN_STORE, -off, NULL) == FAIL)
4731 goto erret;
4732 }
4733
4734 ufunc->uf_def_arg_idx[count] = instr->ga_len;
4735 }
4736
4737 /*
4738 * Loop over all the lines of the function and generate instructions.
4739 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004740 for (;;)
4741 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004742 int is_ex_command;
4743
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004744 if (line != NULL && *line == '|')
4745 // the line continues after a '|'
4746 ++line;
4747 else if (line != NULL && *line != NUL)
4748 {
4749 semsg(_("E488: Trailing characters: %s"), line);
4750 goto erret;
4751 }
4752 else
4753 {
4754 do
4755 {
4756 ++cctx.ctx_lnum;
4757 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
4758 break;
4759 line = ((char_u **)ufunc->uf_lines.ga_data)[cctx.ctx_lnum];
4760 } while (line == NULL);
4761 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
4762 break;
4763 SOURCING_LNUM = ufunc->uf_script_ctx.sc_lnum + cctx.ctx_lnum + 1;
4764 }
4765
4766 had_return = FALSE;
4767 vim_memset(&ea, 0, sizeof(ea));
4768 ea.cmdlinep = &line;
4769 ea.cmd = skipwhite(line);
4770
4771 // "}" ends a block scope
4772 if (*ea.cmd == '}')
4773 {
4774 scopetype_T stype = cctx.ctx_scope == NULL
4775 ? NO_SCOPE : cctx.ctx_scope->se_type;
4776
4777 if (stype == BLOCK_SCOPE)
4778 {
4779 compile_endblock(&cctx);
4780 line = ea.cmd;
4781 }
4782 else
4783 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004784 emsg(_("E1025: using } outside of a block scope"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004785 goto erret;
4786 }
4787 if (line != NULL)
4788 line = skipwhite(ea.cmd + 1);
4789 continue;
4790 }
4791
4792 // "{" starts a block scope
4793 if (*ea.cmd == '{')
4794 {
4795 line = compile_block(ea.cmd, &cctx);
4796 continue;
4797 }
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004798 is_ex_command = *ea.cmd == ':';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004799
4800 /*
4801 * COMMAND MODIFIERS
4802 */
4803 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
4804 {
4805 if (errormsg != NULL)
4806 goto erret;
4807 // empty line or comment
4808 line = (char_u *)"";
4809 continue;
4810 }
4811
4812 // Skip ":call" to get to the function name.
4813 if (checkforcmd(&ea.cmd, "call", 3))
4814 ea.cmd = skipwhite(ea.cmd);
4815
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004816 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004817 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004818 // Assuming the command starts with a variable or function name,
4819 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
4820 // val".
4821 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
4822 ? ea.cmd + 1 : ea.cmd;
4823 p = to_name_end(p);
4824 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004825 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004826 int oplen;
4827 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004828
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004829 // "funcname(" is always a function call.
4830 // "varname[]" is an expression.
4831 // "varname->expr" is an expression.
4832 if (*p == '('
4833 || *p == '['
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004834 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004835 || (*p == '-' && p[1] == '>'))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004836 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004837 // TODO
4838 }
4839
4840 oplen = assignment_len(skipwhite(p), &heredoc);
4841 if (oplen > 0)
4842 {
4843 // Recognize an assignment if we recognize the variable
4844 // name:
4845 // "g:var = expr"
4846 // "var = expr" where "var" is a local var name.
4847 // "&opt = expr"
4848 // "$ENV = expr"
4849 // "@r = expr"
4850 if (*ea.cmd == '&'
4851 || *ea.cmd == '$'
4852 || *ea.cmd == '@'
4853 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
4854 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
4855 || lookup_script(ea.cmd, p - ea.cmd) == OK
4856 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
4857 {
4858 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
4859 if (line == NULL)
4860 goto erret;
4861 continue;
4862 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004863 }
4864 }
4865 }
4866
4867 /*
4868 * COMMAND after range
4869 */
4870 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01004871 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
4872 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004873
4874 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
4875 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004876 if (cctx.ctx_skip == TRUE)
4877 {
4878 line += STRLEN(line);
4879 continue;
4880 }
4881
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004882 // Expression or function call.
4883 if (ea.cmdidx == CMD_eval)
4884 {
4885 p = ea.cmd;
4886 if (compile_expr1(&p, &cctx) == FAIL)
4887 goto erret;
4888
4889 // drop the return value
4890 generate_instr_drop(&cctx, ISN_DROP, 1);
4891 line = p;
4892 continue;
4893 }
4894 if (ea.cmdidx == CMD_let)
4895 {
4896 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
4897 if (line == NULL)
4898 goto erret;
4899 continue;
4900 }
4901 iemsg("Command from find_ex_command() not handled");
4902 goto erret;
4903 }
4904
4905 p = skipwhite(p);
4906
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004907 if (cctx.ctx_skip == TRUE
4908 && ea.cmdidx != CMD_elseif
4909 && ea.cmdidx != CMD_else
4910 && ea.cmdidx != CMD_endif)
4911 {
4912 line += STRLEN(line);
4913 continue;
4914 }
4915
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004916 switch (ea.cmdidx)
4917 {
4918 case CMD_def:
4919 case CMD_function:
4920 // TODO: Nested function
4921 emsg("Nested function not implemented yet");
4922 goto erret;
4923
4924 case CMD_return:
4925 line = compile_return(p, set_return_type, &cctx);
4926 had_return = TRUE;
4927 break;
4928
4929 case CMD_let:
4930 case CMD_const:
4931 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
4932 break;
4933
4934 case CMD_import:
4935 line = compile_import(p, &cctx);
4936 break;
4937
4938 case CMD_if:
4939 line = compile_if(p, &cctx);
4940 break;
4941 case CMD_elseif:
4942 line = compile_elseif(p, &cctx);
4943 break;
4944 case CMD_else:
4945 line = compile_else(p, &cctx);
4946 break;
4947 case CMD_endif:
4948 line = compile_endif(p, &cctx);
4949 break;
4950
4951 case CMD_while:
4952 line = compile_while(p, &cctx);
4953 break;
4954 case CMD_endwhile:
4955 line = compile_endwhile(p, &cctx);
4956 break;
4957
4958 case CMD_for:
4959 line = compile_for(p, &cctx);
4960 break;
4961 case CMD_endfor:
4962 line = compile_endfor(p, &cctx);
4963 break;
4964 case CMD_continue:
4965 line = compile_continue(p, &cctx);
4966 break;
4967 case CMD_break:
4968 line = compile_break(p, &cctx);
4969 break;
4970
4971 case CMD_try:
4972 line = compile_try(p, &cctx);
4973 break;
4974 case CMD_catch:
4975 line = compile_catch(p, &cctx);
4976 break;
4977 case CMD_finally:
4978 line = compile_finally(p, &cctx);
4979 break;
4980 case CMD_endtry:
4981 line = compile_endtry(p, &cctx);
4982 break;
4983 case CMD_throw:
4984 line = compile_throw(p, &cctx);
4985 break;
4986
4987 case CMD_echo:
4988 line = compile_echo(p, TRUE, &cctx);
4989 break;
4990 case CMD_echon:
4991 line = compile_echo(p, FALSE, &cctx);
4992 break;
4993
4994 default:
4995 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01004996 // TODO:
4997 // CMD_echomsg
4998 // CMD_execute
4999 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005000 generate_EXEC(&cctx, line);
5001 line = (char_u *)"";
5002 break;
5003 }
5004 if (line == NULL)
5005 goto erret;
5006
5007 if (cctx.ctx_type_stack.ga_len < 0)
5008 {
5009 iemsg("Type stack underflow");
5010 goto erret;
5011 }
5012 }
5013
5014 if (cctx.ctx_scope != NULL)
5015 {
5016 if (cctx.ctx_scope->se_type == IF_SCOPE)
5017 emsg(_(e_endif));
5018 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
5019 emsg(_(e_endwhile));
5020 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
5021 emsg(_(e_endfor));
5022 else
5023 emsg(_("E1026: Missing }"));
5024 goto erret;
5025 }
5026
5027 if (!had_return)
5028 {
5029 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
5030 {
5031 emsg(_("E1027: Missing return statement"));
5032 goto erret;
5033 }
5034
5035 // Return zero if there is no return at the end.
5036 generate_PUSHNR(&cctx, 0);
5037 generate_instr(&cctx, ISN_RETURN);
5038 }
5039
5040 dfunc->df_instr = instr->ga_data;
5041 dfunc->df_instr_count = instr->ga_len;
5042 dfunc->df_varcount = cctx.ctx_max_local;
5043
5044 ret = OK;
5045
5046erret:
5047 if (ret == FAIL)
5048 {
5049 ga_clear(instr);
5050 ufunc->uf_dfunc_idx = -1;
5051 --def_functions.ga_len;
5052 if (errormsg != NULL)
5053 emsg(errormsg);
5054 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005055 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005056
5057 // don't execute this function body
5058 ufunc->uf_lines.ga_len = 0;
5059 }
5060
5061 current_sctx = save_current_sctx;
5062 ga_clear(&cctx.ctx_type_stack);
5063 ga_clear(&cctx.ctx_locals);
5064}
5065
5066/*
5067 * Delete an instruction, free what it contains.
5068 */
5069 static void
5070delete_instr(isn_T *isn)
5071{
5072 switch (isn->isn_type)
5073 {
5074 case ISN_EXEC:
5075 case ISN_LOADENV:
5076 case ISN_LOADG:
5077 case ISN_LOADOPT:
5078 case ISN_MEMBER:
5079 case ISN_PUSHEXC:
5080 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005081 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005082 case ISN_STOREG:
5083 vim_free(isn->isn_arg.string);
5084 break;
5085
5086 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005087 case ISN_STORES:
5088 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005089 break;
5090
5091 case ISN_STOREOPT:
5092 vim_free(isn->isn_arg.storeopt.so_name);
5093 break;
5094
5095 case ISN_PUSHBLOB: // push blob isn_arg.blob
5096 blob_unref(isn->isn_arg.blob);
5097 break;
5098
5099 case ISN_UCALL:
5100 vim_free(isn->isn_arg.ufunc.cuf_name);
5101 break;
5102
5103 case ISN_2BOOL:
5104 case ISN_2STRING:
5105 case ISN_ADDBLOB:
5106 case ISN_ADDLIST:
5107 case ISN_BCALL:
5108 case ISN_CATCH:
5109 case ISN_CHECKNR:
5110 case ISN_CHECKTYPE:
5111 case ISN_COMPAREANY:
5112 case ISN_COMPAREBLOB:
5113 case ISN_COMPAREBOOL:
5114 case ISN_COMPAREDICT:
5115 case ISN_COMPAREFLOAT:
5116 case ISN_COMPAREFUNC:
5117 case ISN_COMPARELIST:
5118 case ISN_COMPARENR:
5119 case ISN_COMPAREPARTIAL:
5120 case ISN_COMPARESPECIAL:
5121 case ISN_COMPARESTRING:
5122 case ISN_CONCAT:
5123 case ISN_DCALL:
5124 case ISN_DROP:
5125 case ISN_ECHO:
5126 case ISN_ENDTRY:
5127 case ISN_FOR:
5128 case ISN_FUNCREF:
5129 case ISN_INDEX:
5130 case ISN_JUMP:
5131 case ISN_LOAD:
5132 case ISN_LOADSCRIPT:
5133 case ISN_LOADREG:
5134 case ISN_LOADV:
5135 case ISN_NEGATENR:
5136 case ISN_NEWDICT:
5137 case ISN_NEWLIST:
5138 case ISN_OPNR:
5139 case ISN_OPFLOAT:
5140 case ISN_OPANY:
5141 case ISN_PCALL:
5142 case ISN_PUSHF:
5143 case ISN_PUSHNR:
5144 case ISN_PUSHBOOL:
5145 case ISN_PUSHSPEC:
5146 case ISN_RETURN:
5147 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005148 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005149 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005150 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005151 case ISN_STORESCRIPT:
5152 case ISN_THROW:
5153 case ISN_TRY:
5154 // nothing allocated
5155 break;
5156 }
5157}
5158
5159/*
5160 * When a user function is deleted, delete any associated def function.
5161 */
5162 void
5163delete_def_function(ufunc_T *ufunc)
5164{
5165 int idx;
5166
5167 if (ufunc->uf_dfunc_idx >= 0)
5168 {
5169 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5170 + ufunc->uf_dfunc_idx;
5171 ga_clear(&dfunc->df_def_args_isn);
5172
5173 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
5174 delete_instr(dfunc->df_instr + idx);
5175 VIM_CLEAR(dfunc->df_instr);
5176
5177 dfunc->df_deleted = TRUE;
5178 }
5179}
5180
5181#if defined(EXITFREE) || defined(PROTO)
5182 void
5183free_def_functions(void)
5184{
5185 vim_free(def_functions.ga_data);
5186}
5187#endif
5188
5189
5190#endif // FEAT_EVAL