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