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