blob: a595580dbe4a6d89ce3a2ad92d4419d40eed1530 [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);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100132static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100133
134/*
135 * Lookup variable "name" in the local scope and return the index.
136 */
137 static int
138lookup_local(char_u *name, size_t len, cctx_T *cctx)
139{
140 int idx;
141
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100142 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100143 return -1;
144 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
145 {
146 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
147
148 if (STRNCMP(name, lvar->lv_name, len) == 0
149 && STRLEN(lvar->lv_name) == len)
150 return idx;
151 }
152 return -1;
153}
154
155/*
156 * Lookup an argument in the current function.
157 * Returns the argument index or -1 if not found.
158 */
159 static int
160lookup_arg(char_u *name, size_t len, cctx_T *cctx)
161{
162 int idx;
163
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100164 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100165 return -1;
166 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
167 {
168 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
169
170 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
171 return idx;
172 }
173 return -1;
174}
175
176/*
177 * Lookup a vararg argument in the current function.
178 * Returns TRUE if there is a match.
179 */
180 static int
181lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
182{
183 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
184
185 return len > 0 && va_name != NULL
186 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
187}
188
189/*
190 * Lookup a variable in the current script.
191 * Returns OK or FAIL.
192 */
193 static int
194lookup_script(char_u *name, size_t len)
195{
196 int cc;
197 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
198 dictitem_T *di;
199
200 cc = name[len];
201 name[len] = NUL;
202 di = find_var_in_ht(ht, 0, name, TRUE);
203 name[len] = cc;
204 return di == NULL ? FAIL: OK;
205}
206
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100207/*
208 * Check if "p[len]" is already defined, either in script "import_sid" or in
209 * compilation context "cctx".
210 * Return FAIL and give an error if it defined.
211 */
212 int
213check_defined(char_u *p, int len, cctx_T *cctx)
214{
215 if (lookup_script(p, len) == OK
216 || (cctx != NULL
217 && (lookup_local(p, len, cctx) >= 0
218 || find_imported(p, len, cctx) != NULL)))
219 {
220 semsg("E1073: imported name already defined: %s", p);
221 return FAIL;
222 }
223 return OK;
224}
225
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100226 static type_T *
227get_list_type(type_T *member_type, garray_T *type_list)
228{
229 type_T *type;
230
231 // recognize commonly used types
232 if (member_type->tt_type == VAR_UNKNOWN)
233 return &t_list_any;
Bram Moolenaar436472f2020-02-20 22:54:43 +0100234 if (member_type->tt_type == VAR_VOID)
235 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100236 if (member_type->tt_type == VAR_BOOL)
237 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100238 if (member_type->tt_type == VAR_NUMBER)
239 return &t_list_number;
240 if (member_type->tt_type == VAR_STRING)
241 return &t_list_string;
242
243 // Not a common type, create a new entry.
244 if (ga_grow(type_list, 1) == FAIL)
245 return FAIL;
246 type = ((type_T *)type_list->ga_data) + type_list->ga_len;
247 ++type_list->ga_len;
248 type->tt_type = VAR_LIST;
249 type->tt_member = member_type;
250 return type;
251}
252
253 static type_T *
254get_dict_type(type_T *member_type, garray_T *type_list)
255{
256 type_T *type;
257
258 // recognize commonly used types
259 if (member_type->tt_type == VAR_UNKNOWN)
260 return &t_dict_any;
Bram Moolenaar436472f2020-02-20 22:54:43 +0100261 if (member_type->tt_type == VAR_VOID)
262 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100263 if (member_type->tt_type == VAR_BOOL)
264 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100265 if (member_type->tt_type == VAR_NUMBER)
266 return &t_dict_number;
267 if (member_type->tt_type == VAR_STRING)
268 return &t_dict_string;
269
270 // Not a common type, create a new entry.
271 if (ga_grow(type_list, 1) == FAIL)
272 return FAIL;
273 type = ((type_T *)type_list->ga_data) + type_list->ga_len;
274 ++type_list->ga_len;
275 type->tt_type = VAR_DICT;
276 type->tt_member = member_type;
277 return type;
278}
279
280/////////////////////////////////////////////////////////////////////
281// Following generate_ functions expect the caller to call ga_grow().
282
Bram Moolenaar080457c2020-03-03 21:53:32 +0100283#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
284#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
285
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100286/*
287 * Generate an instruction without arguments.
288 * Returns a pointer to the new instruction, NULL if failed.
289 */
290 static isn_T *
291generate_instr(cctx_T *cctx, isntype_T isn_type)
292{
293 garray_T *instr = &cctx->ctx_instr;
294 isn_T *isn;
295
Bram Moolenaar080457c2020-03-03 21:53:32 +0100296 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100297 if (ga_grow(instr, 1) == FAIL)
298 return NULL;
299 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
300 isn->isn_type = isn_type;
301 isn->isn_lnum = cctx->ctx_lnum + 1;
302 ++instr->ga_len;
303
304 return isn;
305}
306
307/*
308 * Generate an instruction without arguments.
309 * "drop" will be removed from the stack.
310 * Returns a pointer to the new instruction, NULL if failed.
311 */
312 static isn_T *
313generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
314{
315 garray_T *stack = &cctx->ctx_type_stack;
316
Bram Moolenaar080457c2020-03-03 21:53:32 +0100317 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100318 stack->ga_len -= drop;
319 return generate_instr(cctx, isn_type);
320}
321
322/*
323 * Generate instruction "isn_type" and put "type" on the type stack.
324 */
325 static isn_T *
326generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
327{
328 isn_T *isn;
329 garray_T *stack = &cctx->ctx_type_stack;
330
331 if ((isn = generate_instr(cctx, isn_type)) == NULL)
332 return NULL;
333
334 if (ga_grow(stack, 1) == FAIL)
335 return NULL;
336 ((type_T **)stack->ga_data)[stack->ga_len] = type;
337 ++stack->ga_len;
338
339 return isn;
340}
341
342/*
343 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
344 */
345 static int
346may_generate_2STRING(int offset, cctx_T *cctx)
347{
348 isn_T *isn;
349 garray_T *stack = &cctx->ctx_type_stack;
350 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
351
352 if ((*type)->tt_type == VAR_STRING)
353 return OK;
354 *type = &t_string;
355
356 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
357 return FAIL;
358 isn->isn_arg.number = offset;
359
360 return OK;
361}
362
363 static int
364check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
365{
366 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_UNKNOWN)
367 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
368 || type2 == VAR_UNKNOWN)))
369 {
370 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100371 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100372 else
373 semsg(_("E1036: %c requires number or float arguments"), *op);
374 return FAIL;
375 }
376 return OK;
377}
378
379/*
380 * Generate an instruction with two arguments. The instruction depends on the
381 * type of the arguments.
382 */
383 static int
384generate_two_op(cctx_T *cctx, char_u *op)
385{
386 garray_T *stack = &cctx->ctx_type_stack;
387 type_T *type1;
388 type_T *type2;
389 vartype_T vartype;
390 isn_T *isn;
391
Bram Moolenaar080457c2020-03-03 21:53:32 +0100392 RETURN_OK_IF_SKIP(cctx);
393
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100394 // Get the known type of the two items on the stack. If they are matching
395 // use a type-specific instruction. Otherwise fall back to runtime type
396 // checking.
397 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
398 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
399 vartype = VAR_UNKNOWN;
400 if (type1->tt_type == type2->tt_type
401 && (type1->tt_type == VAR_NUMBER
402 || type1->tt_type == VAR_LIST
403#ifdef FEAT_FLOAT
404 || type1->tt_type == VAR_FLOAT
405#endif
406 || type1->tt_type == VAR_BLOB))
407 vartype = type1->tt_type;
408
409 switch (*op)
410 {
411 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar0062c2d2020-02-20 22:14:31 +0100412 && type1->tt_type != VAR_UNKNOWN
413 && type2->tt_type != VAR_UNKNOWN
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100414 && check_number_or_float(
415 type1->tt_type, type2->tt_type, op) == FAIL)
416 return FAIL;
417 isn = generate_instr_drop(cctx,
418 vartype == VAR_NUMBER ? ISN_OPNR
419 : vartype == VAR_LIST ? ISN_ADDLIST
420 : vartype == VAR_BLOB ? ISN_ADDBLOB
421#ifdef FEAT_FLOAT
422 : vartype == VAR_FLOAT ? ISN_OPFLOAT
423#endif
424 : ISN_OPANY, 1);
425 if (isn != NULL)
426 isn->isn_arg.op.op_type = EXPR_ADD;
427 break;
428
429 case '-':
430 case '*':
431 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
432 op) == FAIL)
433 return FAIL;
434 if (vartype == VAR_NUMBER)
435 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
436#ifdef FEAT_FLOAT
437 else if (vartype == VAR_FLOAT)
438 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
439#endif
440 else
441 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
442 if (isn != NULL)
443 isn->isn_arg.op.op_type = *op == '*'
444 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
445 break;
446
447 case '%': if ((type1->tt_type != VAR_UNKNOWN
448 && type1->tt_type != VAR_NUMBER)
449 || (type2->tt_type != VAR_UNKNOWN
450 && type2->tt_type != VAR_NUMBER))
451 {
452 emsg(_("E1035: % requires number arguments"));
453 return FAIL;
454 }
455 isn = generate_instr_drop(cctx,
456 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
457 if (isn != NULL)
458 isn->isn_arg.op.op_type = EXPR_REM;
459 break;
460 }
461
462 // correct type of result
463 if (vartype == VAR_UNKNOWN)
464 {
465 type_T *type = &t_any;
466
467#ifdef FEAT_FLOAT
468 // float+number and number+float results in float
469 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
470 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
471 type = &t_float;
472#endif
473 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
474 }
475
476 return OK;
477}
478
479/*
480 * Generate an ISN_COMPARE* instruction with a boolean result.
481 */
482 static int
483generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
484{
485 isntype_T isntype = ISN_DROP;
486 isn_T *isn;
487 garray_T *stack = &cctx->ctx_type_stack;
488 vartype_T type1;
489 vartype_T type2;
490
Bram Moolenaar080457c2020-03-03 21:53:32 +0100491 RETURN_OK_IF_SKIP(cctx);
492
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100493 // Get the known type of the two items on the stack. If they are matching
494 // use a type-specific instruction. Otherwise fall back to runtime type
495 // checking.
496 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
497 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
498 if (type1 == type2)
499 {
500 switch (type1)
501 {
502 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
503 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
504 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
505 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
506 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
507 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
508 case VAR_LIST: isntype = ISN_COMPARELIST; break;
509 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
510 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
511 case VAR_PARTIAL: isntype = ISN_COMPAREPARTIAL; break;
512 default: isntype = ISN_COMPAREANY; break;
513 }
514 }
515 else if (type1 == VAR_UNKNOWN || type2 == VAR_UNKNOWN
516 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
517 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
518 isntype = ISN_COMPAREANY;
519
520 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
521 && (isntype == ISN_COMPAREBOOL
522 || isntype == ISN_COMPARESPECIAL
523 || isntype == ISN_COMPARENR
524 || isntype == ISN_COMPAREFLOAT))
525 {
526 semsg(_("E1037: Cannot use \"%s\" with %s"),
527 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
528 return FAIL;
529 }
530 if (isntype == ISN_DROP
531 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
532 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
533 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
534 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
535 && exptype != EXPR_IS && exptype != EXPR_ISNOT
536 && (type1 == VAR_BLOB || type2 == VAR_BLOB
537 || type1 == VAR_LIST || type2 == VAR_LIST))))
538 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100539 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100540 vartype_name(type1), vartype_name(type2));
541 return FAIL;
542 }
543
544 if ((isn = generate_instr(cctx, isntype)) == NULL)
545 return FAIL;
546 isn->isn_arg.op.op_type = exptype;
547 isn->isn_arg.op.op_ic = ic;
548
549 // takes two arguments, puts one bool back
550 if (stack->ga_len >= 2)
551 {
552 --stack->ga_len;
553 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
554 }
555
556 return OK;
557}
558
559/*
560 * Generate an ISN_2BOOL instruction.
561 */
562 static int
563generate_2BOOL(cctx_T *cctx, int invert)
564{
565 isn_T *isn;
566 garray_T *stack = &cctx->ctx_type_stack;
567
Bram Moolenaar080457c2020-03-03 21:53:32 +0100568 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100569 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
570 return FAIL;
571 isn->isn_arg.number = invert;
572
573 // type becomes bool
574 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
575
576 return OK;
577}
578
579 static int
580generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
581{
582 isn_T *isn;
583 garray_T *stack = &cctx->ctx_type_stack;
584
Bram Moolenaar080457c2020-03-03 21:53:32 +0100585 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100586 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
587 return FAIL;
588 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
589 isn->isn_arg.type.ct_off = offset;
590
591 // type becomes vartype
592 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
593
594 return OK;
595}
596
597/*
598 * Generate an ISN_PUSHNR instruction.
599 */
600 static int
601generate_PUSHNR(cctx_T *cctx, varnumber_T number)
602{
603 isn_T *isn;
604
Bram Moolenaar080457c2020-03-03 21:53:32 +0100605 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100606 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
607 return FAIL;
608 isn->isn_arg.number = number;
609
610 return OK;
611}
612
613/*
614 * Generate an ISN_PUSHBOOL instruction.
615 */
616 static int
617generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
618{
619 isn_T *isn;
620
Bram Moolenaar080457c2020-03-03 21:53:32 +0100621 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100622 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
623 return FAIL;
624 isn->isn_arg.number = number;
625
626 return OK;
627}
628
629/*
630 * Generate an ISN_PUSHSPEC instruction.
631 */
632 static int
633generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
634{
635 isn_T *isn;
636
Bram Moolenaar080457c2020-03-03 21:53:32 +0100637 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100638 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
639 return FAIL;
640 isn->isn_arg.number = number;
641
642 return OK;
643}
644
645#ifdef FEAT_FLOAT
646/*
647 * Generate an ISN_PUSHF instruction.
648 */
649 static int
650generate_PUSHF(cctx_T *cctx, float_T fnumber)
651{
652 isn_T *isn;
653
Bram Moolenaar080457c2020-03-03 21:53:32 +0100654 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100655 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
656 return FAIL;
657 isn->isn_arg.fnumber = fnumber;
658
659 return OK;
660}
661#endif
662
663/*
664 * Generate an ISN_PUSHS instruction.
665 * Consumes "str".
666 */
667 static int
668generate_PUSHS(cctx_T *cctx, char_u *str)
669{
670 isn_T *isn;
671
Bram Moolenaar080457c2020-03-03 21:53:32 +0100672 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100673 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
674 return FAIL;
675 isn->isn_arg.string = str;
676
677 return OK;
678}
679
680/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100681 * Generate an ISN_PUSHCHANNEL instruction.
682 * Consumes "channel".
683 */
684 static int
685generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
686{
687 isn_T *isn;
688
Bram Moolenaar080457c2020-03-03 21:53:32 +0100689 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100690 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
691 return FAIL;
692 isn->isn_arg.channel = channel;
693
694 return OK;
695}
696
697/*
698 * Generate an ISN_PUSHJOB instruction.
699 * Consumes "job".
700 */
701 static int
702generate_PUSHJOB(cctx_T *cctx, job_T *job)
703{
704 isn_T *isn;
705
Bram Moolenaar080457c2020-03-03 21:53:32 +0100706 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100707 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100708 return FAIL;
709 isn->isn_arg.job = job;
710
711 return OK;
712}
713
714/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100715 * Generate an ISN_PUSHBLOB instruction.
716 * Consumes "blob".
717 */
718 static int
719generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
720{
721 isn_T *isn;
722
Bram Moolenaar080457c2020-03-03 21:53:32 +0100723 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100724 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
725 return FAIL;
726 isn->isn_arg.blob = blob;
727
728 return OK;
729}
730
731/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100732 * Generate an ISN_PUSHFUNC instruction with name "name".
733 * Consumes "name".
734 */
735 static int
736generate_PUSHFUNC(cctx_T *cctx, char_u *name)
737{
738 isn_T *isn;
739
Bram Moolenaar080457c2020-03-03 21:53:32 +0100740 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100741 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, &t_func_void)) == NULL)
742 return FAIL;
743 isn->isn_arg.string = name;
744
745 return OK;
746}
747
748/*
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100749 * Generate an ISN_PUSHPARTIAL instruction with partial "part".
750 * Consumes "name".
751 */
752 static int
753generate_PUSHPARTIAL(cctx_T *cctx, partial_T *part)
754{
755 isn_T *isn;
756
Bram Moolenaar080457c2020-03-03 21:53:32 +0100757 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100758 if ((isn = generate_instr_type(cctx, ISN_PUSHPARTIAL,
759 &t_partial_any)) == NULL)
760 return FAIL;
761 isn->isn_arg.partial = part;
762
763 return OK;
764}
765
766/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100767 * Generate an ISN_STORE instruction.
768 */
769 static int
770generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
771{
772 isn_T *isn;
773
Bram Moolenaar080457c2020-03-03 21:53:32 +0100774 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100775 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
776 return FAIL;
777 if (name != NULL)
778 isn->isn_arg.string = vim_strsave(name);
779 else
780 isn->isn_arg.number = idx;
781
782 return OK;
783}
784
785/*
786 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
787 */
788 static int
789generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
790{
791 isn_T *isn;
792
Bram Moolenaar080457c2020-03-03 21:53:32 +0100793 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100794 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
795 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100796 isn->isn_arg.storenr.stnr_idx = idx;
797 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100798
799 return OK;
800}
801
802/*
803 * Generate an ISN_STOREOPT instruction
804 */
805 static int
806generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
807{
808 isn_T *isn;
809
Bram Moolenaar080457c2020-03-03 21:53:32 +0100810 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100811 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
812 return FAIL;
813 isn->isn_arg.storeopt.so_name = vim_strsave(name);
814 isn->isn_arg.storeopt.so_flags = opt_flags;
815
816 return OK;
817}
818
819/*
820 * Generate an ISN_LOAD or similar instruction.
821 */
822 static int
823generate_LOAD(
824 cctx_T *cctx,
825 isntype_T isn_type,
826 int idx,
827 char_u *name,
828 type_T *type)
829{
830 isn_T *isn;
831
Bram Moolenaar080457c2020-03-03 21:53:32 +0100832 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100833 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
834 return FAIL;
835 if (name != NULL)
836 isn->isn_arg.string = vim_strsave(name);
837 else
838 isn->isn_arg.number = idx;
839
840 return OK;
841}
842
843/*
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100844 * Generate an ISN_LOADV instruction.
845 */
846 static int
847generate_LOADV(
848 cctx_T *cctx,
849 char_u *name,
850 int error)
851{
852 // load v:var
853 int vidx = find_vim_var(name);
854
Bram Moolenaar080457c2020-03-03 21:53:32 +0100855 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100856 if (vidx < 0)
857 {
858 if (error)
859 semsg(_(e_var_notfound), name);
860 return FAIL;
861 }
862
863 // TODO: get actual type
864 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, &t_any);
865}
866
867/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100868 * Generate an ISN_LOADS instruction.
869 */
870 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100871generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100872 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100873 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100874 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100875 int sid,
876 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100877{
878 isn_T *isn;
879
Bram Moolenaar080457c2020-03-03 21:53:32 +0100880 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100881 if (isn_type == ISN_LOADS)
882 isn = generate_instr_type(cctx, isn_type, type);
883 else
884 isn = generate_instr_drop(cctx, isn_type, 1);
885 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100886 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100887 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
888 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100889
890 return OK;
891}
892
893/*
894 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
895 */
896 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100897generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100898 cctx_T *cctx,
899 isntype_T isn_type,
900 int sid,
901 int idx,
902 type_T *type)
903{
904 isn_T *isn;
905
Bram Moolenaar080457c2020-03-03 21:53:32 +0100906 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100907 if (isn_type == ISN_LOADSCRIPT)
908 isn = generate_instr_type(cctx, isn_type, type);
909 else
910 isn = generate_instr_drop(cctx, isn_type, 1);
911 if (isn == NULL)
912 return FAIL;
913 isn->isn_arg.script.script_sid = sid;
914 isn->isn_arg.script.script_idx = idx;
915 return OK;
916}
917
918/*
919 * Generate an ISN_NEWLIST instruction.
920 */
921 static int
922generate_NEWLIST(cctx_T *cctx, int count)
923{
924 isn_T *isn;
925 garray_T *stack = &cctx->ctx_type_stack;
926 garray_T *type_list = cctx->ctx_type_list;
927 type_T *type;
928 type_T *member;
929
Bram Moolenaar080457c2020-03-03 21:53:32 +0100930 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100931 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
932 return FAIL;
933 isn->isn_arg.number = count;
934
935 // drop the value types
936 stack->ga_len -= count;
937
Bram Moolenaar436472f2020-02-20 22:54:43 +0100938 // Use the first value type for the list member type. Use "void" for an
939 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100940 if (count > 0)
941 member = ((type_T **)stack->ga_data)[stack->ga_len];
942 else
Bram Moolenaar436472f2020-02-20 22:54:43 +0100943 member = &t_void;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100944 type = get_list_type(member, type_list);
945
946 // add the list type to the type stack
947 if (ga_grow(stack, 1) == FAIL)
948 return FAIL;
949 ((type_T **)stack->ga_data)[stack->ga_len] = type;
950 ++stack->ga_len;
951
952 return OK;
953}
954
955/*
956 * Generate an ISN_NEWDICT instruction.
957 */
958 static int
959generate_NEWDICT(cctx_T *cctx, int count)
960{
961 isn_T *isn;
962 garray_T *stack = &cctx->ctx_type_stack;
963 garray_T *type_list = cctx->ctx_type_list;
964 type_T *type;
965 type_T *member;
966
Bram Moolenaar080457c2020-03-03 21:53:32 +0100967 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100968 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
969 return FAIL;
970 isn->isn_arg.number = count;
971
972 // drop the key and value types
973 stack->ga_len -= 2 * count;
974
Bram Moolenaar436472f2020-02-20 22:54:43 +0100975 // Use the first value type for the list member type. Use "void" for an
976 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100977 if (count > 0)
978 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
979 else
Bram Moolenaar436472f2020-02-20 22:54:43 +0100980 member = &t_void;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100981 type = get_dict_type(member, type_list);
982
983 // add the dict type to the type stack
984 if (ga_grow(stack, 1) == FAIL)
985 return FAIL;
986 ((type_T **)stack->ga_data)[stack->ga_len] = type;
987 ++stack->ga_len;
988
989 return OK;
990}
991
992/*
993 * Generate an ISN_FUNCREF instruction.
994 */
995 static int
996generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
997{
998 isn_T *isn;
999 garray_T *stack = &cctx->ctx_type_stack;
1000
Bram Moolenaar080457c2020-03-03 21:53:32 +01001001 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001002 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1003 return FAIL;
1004 isn->isn_arg.number = dfunc_idx;
1005
1006 if (ga_grow(stack, 1) == FAIL)
1007 return FAIL;
1008 ((type_T **)stack->ga_data)[stack->ga_len] = &t_partial_any;
1009 // TODO: argument and return types
1010 ++stack->ga_len;
1011
1012 return OK;
1013}
1014
1015/*
1016 * Generate an ISN_JUMP instruction.
1017 */
1018 static int
1019generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1020{
1021 isn_T *isn;
1022 garray_T *stack = &cctx->ctx_type_stack;
1023
Bram Moolenaar080457c2020-03-03 21:53:32 +01001024 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001025 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1026 return FAIL;
1027 isn->isn_arg.jump.jump_when = when;
1028 isn->isn_arg.jump.jump_where = where;
1029
1030 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1031 --stack->ga_len;
1032
1033 return OK;
1034}
1035
1036 static int
1037generate_FOR(cctx_T *cctx, int loop_idx)
1038{
1039 isn_T *isn;
1040 garray_T *stack = &cctx->ctx_type_stack;
1041
Bram Moolenaar080457c2020-03-03 21:53:32 +01001042 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001043 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1044 return FAIL;
1045 isn->isn_arg.forloop.for_idx = loop_idx;
1046
1047 if (ga_grow(stack, 1) == FAIL)
1048 return FAIL;
1049 // type doesn't matter, will be stored next
1050 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1051 ++stack->ga_len;
1052
1053 return OK;
1054}
1055
1056/*
1057 * Generate an ISN_BCALL instruction.
1058 * Return FAIL if the number of arguments is wrong.
1059 */
1060 static int
1061generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1062{
1063 isn_T *isn;
1064 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001065 type_T *argtypes[MAX_FUNC_ARGS];
1066 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001067
Bram Moolenaar080457c2020-03-03 21:53:32 +01001068 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001069 if (check_internal_func(func_idx, argcount) == FAIL)
1070 return FAIL;
1071
1072 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1073 return FAIL;
1074 isn->isn_arg.bfunc.cbf_idx = func_idx;
1075 isn->isn_arg.bfunc.cbf_argcount = argcount;
1076
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001077 for (i = 0; i < argcount; ++i)
1078 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1079
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001080 stack->ga_len -= argcount; // drop the arguments
1081 if (ga_grow(stack, 1) == FAIL)
1082 return FAIL;
1083 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001084 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001085 ++stack->ga_len; // add return value
1086
1087 return OK;
1088}
1089
1090/*
1091 * Generate an ISN_DCALL or ISN_UCALL instruction.
1092 * Return FAIL if the number of arguments is wrong.
1093 */
1094 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001095generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001096{
1097 isn_T *isn;
1098 garray_T *stack = &cctx->ctx_type_stack;
1099 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001100 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001101
Bram Moolenaar080457c2020-03-03 21:53:32 +01001102 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001103 if (argcount > regular_args && !has_varargs(ufunc))
1104 {
1105 semsg(_(e_toomanyarg), ufunc->uf_name);
1106 return FAIL;
1107 }
1108 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1109 {
1110 semsg(_(e_toofewarg), ufunc->uf_name);
1111 return FAIL;
1112 }
1113
1114 // Turn varargs into a list.
1115 if (ufunc->uf_va_name != NULL)
1116 {
1117 int count = argcount - regular_args;
1118
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001119 // If count is negative an empty list will be added after evaluating
1120 // default values for missing optional arguments.
1121 if (count >= 0)
1122 {
1123 generate_NEWLIST(cctx, count);
1124 argcount = regular_args + 1;
1125 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001126 }
1127
1128 if ((isn = generate_instr(cctx,
1129 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1130 return FAIL;
1131 if (ufunc->uf_dfunc_idx >= 0)
1132 {
1133 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1134 isn->isn_arg.dfunc.cdf_argcount = argcount;
1135 }
1136 else
1137 {
1138 // A user function may be deleted and redefined later, can't use the
1139 // ufunc pointer, need to look it up again at runtime.
1140 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1141 isn->isn_arg.ufunc.cuf_argcount = argcount;
1142 }
1143
1144 stack->ga_len -= argcount; // drop the arguments
1145 if (ga_grow(stack, 1) == FAIL)
1146 return FAIL;
1147 // add return value
1148 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1149 ++stack->ga_len;
1150
1151 return OK;
1152}
1153
1154/*
1155 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1156 */
1157 static int
1158generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1159{
1160 isn_T *isn;
1161 garray_T *stack = &cctx->ctx_type_stack;
1162
Bram Moolenaar080457c2020-03-03 21:53:32 +01001163 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001164 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1165 return FAIL;
1166 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1167 isn->isn_arg.ufunc.cuf_argcount = argcount;
1168
1169 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001170 if (ga_grow(stack, 1) == FAIL)
1171 return FAIL;
1172 // add return value
1173 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1174 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001175
1176 return OK;
1177}
1178
1179/*
1180 * Generate an ISN_PCALL instruction.
1181 */
1182 static int
1183generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1184{
1185 isn_T *isn;
1186 garray_T *stack = &cctx->ctx_type_stack;
1187
Bram Moolenaar080457c2020-03-03 21:53:32 +01001188 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001189 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1190 return FAIL;
1191 isn->isn_arg.pfunc.cpf_top = at_top;
1192 isn->isn_arg.pfunc.cpf_argcount = argcount;
1193
1194 stack->ga_len -= argcount; // drop the arguments
1195
1196 // drop the funcref/partial, get back the return value
1197 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1198
1199 return OK;
1200}
1201
1202/*
1203 * Generate an ISN_MEMBER instruction.
1204 */
1205 static int
1206generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1207{
1208 isn_T *isn;
1209 garray_T *stack = &cctx->ctx_type_stack;
1210 type_T *type;
1211
Bram Moolenaar080457c2020-03-03 21:53:32 +01001212 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001213 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1214 return FAIL;
1215 isn->isn_arg.string = vim_strnsave(name, (int)len);
1216
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001217 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001218 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001219 if (type->tt_type != VAR_DICT && type != &t_any)
1220 {
1221 emsg(_(e_dictreq));
1222 return FAIL;
1223 }
1224 // change dict type to dict member type
1225 if (type->tt_type == VAR_DICT)
1226 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001227
1228 return OK;
1229}
1230
1231/*
1232 * Generate an ISN_ECHO instruction.
1233 */
1234 static int
1235generate_ECHO(cctx_T *cctx, int with_white, int count)
1236{
1237 isn_T *isn;
1238
Bram Moolenaar080457c2020-03-03 21:53:32 +01001239 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001240 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1241 return FAIL;
1242 isn->isn_arg.echo.echo_with_white = with_white;
1243 isn->isn_arg.echo.echo_count = count;
1244
1245 return OK;
1246}
1247
Bram Moolenaarad39c092020-02-26 18:23:43 +01001248/*
1249 * Generate an ISN_EXECUTE instruction.
1250 */
1251 static int
1252generate_EXECUTE(cctx_T *cctx, int count)
1253{
1254 isn_T *isn;
1255
1256 if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL)
1257 return FAIL;
1258 isn->isn_arg.number = count;
1259
1260 return OK;
1261}
1262
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001263 static int
1264generate_EXEC(cctx_T *cctx, char_u *line)
1265{
1266 isn_T *isn;
1267
Bram Moolenaar080457c2020-03-03 21:53:32 +01001268 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001269 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1270 return FAIL;
1271 isn->isn_arg.string = vim_strsave(line);
1272 return OK;
1273}
1274
1275static char e_white_both[] =
1276 N_("E1004: white space required before and after '%s'");
1277
1278/*
1279 * Reserve space for a local variable.
1280 * Return the index or -1 if it failed.
1281 */
1282 static int
1283reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1284{
1285 int idx;
1286 lvar_T *lvar;
1287
1288 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1289 {
1290 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1291 return -1;
1292 }
1293
1294 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1295 return -1;
1296 idx = cctx->ctx_locals.ga_len;
1297 if (cctx->ctx_max_local < idx + 1)
1298 cctx->ctx_max_local = idx + 1;
1299 ++cctx->ctx_locals.ga_len;
1300
1301 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1302 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1303 lvar->lv_const = isConst;
1304 lvar->lv_type = type;
1305
1306 return idx;
1307}
1308
1309/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001310 * Remove local variables above "new_top".
1311 */
1312 static void
1313unwind_locals(cctx_T *cctx, int new_top)
1314{
1315 if (cctx->ctx_locals.ga_len > new_top)
1316 {
1317 int idx;
1318 lvar_T *lvar;
1319
1320 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1321 {
1322 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1323 vim_free(lvar->lv_name);
1324 }
1325 }
1326 cctx->ctx_locals.ga_len = new_top;
1327}
1328
1329/*
1330 * Free all local variables.
1331 */
1332 static void
1333free_local(cctx_T *cctx)
1334{
1335 unwind_locals(cctx, 0);
1336 ga_clear(&cctx->ctx_locals);
1337}
1338
1339/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001340 * Skip over a type definition and return a pointer to just after it.
1341 */
1342 char_u *
1343skip_type(char_u *start)
1344{
1345 char_u *p = start;
1346
1347 while (ASCII_ISALNUM(*p) || *p == '_')
1348 ++p;
1349
1350 // Skip over "<type>"; this is permissive about white space.
1351 if (*skipwhite(p) == '<')
1352 {
1353 p = skipwhite(p);
1354 p = skip_type(skipwhite(p + 1));
1355 p = skipwhite(p);
1356 if (*p == '>')
1357 ++p;
1358 }
1359 return p;
1360}
1361
1362/*
1363 * Parse the member type: "<type>" and return "type" with the member set.
1364 * Use "type_list" if a new type needs to be added.
1365 * Returns NULL in case of failure.
1366 */
1367 static type_T *
1368parse_type_member(char_u **arg, type_T *type, garray_T *type_list)
1369{
1370 type_T *member_type;
1371
1372 if (**arg != '<')
1373 {
1374 if (*skipwhite(*arg) == '<')
1375 emsg(_("E1007: No white space allowed before <"));
1376 else
1377 emsg(_("E1008: Missing <type>"));
1378 return NULL;
1379 }
1380 *arg = skipwhite(*arg + 1);
1381
1382 member_type = parse_type(arg, type_list);
1383 if (member_type == NULL)
1384 return NULL;
1385
1386 *arg = skipwhite(*arg);
1387 if (**arg != '>')
1388 {
1389 emsg(_("E1009: Missing > after type"));
1390 return NULL;
1391 }
1392 ++*arg;
1393
1394 if (type->tt_type == VAR_LIST)
1395 return get_list_type(member_type, type_list);
1396 return get_dict_type(member_type, type_list);
1397}
1398
1399/*
1400 * Parse a type at "arg" and advance over it.
1401 * Return NULL for failure.
1402 */
1403 type_T *
1404parse_type(char_u **arg, garray_T *type_list)
1405{
1406 char_u *p = *arg;
1407 size_t len;
1408
1409 // skip over the first word
1410 while (ASCII_ISALNUM(*p) || *p == '_')
1411 ++p;
1412 len = p - *arg;
1413
1414 switch (**arg)
1415 {
1416 case 'a':
1417 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1418 {
1419 *arg += len;
1420 return &t_any;
1421 }
1422 break;
1423 case 'b':
1424 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1425 {
1426 *arg += len;
1427 return &t_bool;
1428 }
1429 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1430 {
1431 *arg += len;
1432 return &t_blob;
1433 }
1434 break;
1435 case 'c':
1436 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1437 {
1438 *arg += len;
1439 return &t_channel;
1440 }
1441 break;
1442 case 'd':
1443 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1444 {
1445 *arg += len;
1446 return parse_type_member(arg, &t_dict_any, type_list);
1447 }
1448 break;
1449 case 'f':
1450 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1451 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001452#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001453 *arg += len;
1454 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001455#else
1456 emsg(_("E1055: This Vim is not compiled with float support"));
1457 return &t_any;
1458#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001459 }
1460 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1461 {
1462 *arg += len;
1463 // TODO: arguments and return type
1464 return &t_func_any;
1465 }
1466 break;
1467 case 'j':
1468 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1469 {
1470 *arg += len;
1471 return &t_job;
1472 }
1473 break;
1474 case 'l':
1475 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1476 {
1477 *arg += len;
1478 return parse_type_member(arg, &t_list_any, type_list);
1479 }
1480 break;
1481 case 'n':
1482 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1483 {
1484 *arg += len;
1485 return &t_number;
1486 }
1487 break;
1488 case 'p':
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001489 if (len == 7 && STRNCMP(*arg, "partial", len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001490 {
1491 *arg += len;
1492 // TODO: arguments and return type
1493 return &t_partial_any;
1494 }
1495 break;
1496 case 's':
1497 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1498 {
1499 *arg += len;
1500 return &t_string;
1501 }
1502 break;
1503 case 'v':
1504 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1505 {
1506 *arg += len;
1507 return &t_void;
1508 }
1509 break;
1510 }
1511
1512 semsg(_("E1010: Type not recognized: %s"), *arg);
1513 return &t_any;
1514}
1515
1516/*
1517 * Check if "type1" and "type2" are exactly the same.
1518 */
1519 static int
1520equal_type(type_T *type1, type_T *type2)
1521{
1522 if (type1->tt_type != type2->tt_type)
1523 return FALSE;
1524 switch (type1->tt_type)
1525 {
1526 case VAR_VOID:
1527 case VAR_UNKNOWN:
1528 case VAR_SPECIAL:
1529 case VAR_BOOL:
1530 case VAR_NUMBER:
1531 case VAR_FLOAT:
1532 case VAR_STRING:
1533 case VAR_BLOB:
1534 case VAR_JOB:
1535 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001536 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001537 case VAR_LIST:
1538 case VAR_DICT:
1539 return equal_type(type1->tt_member, type2->tt_member);
1540 case VAR_FUNC:
1541 case VAR_PARTIAL:
1542 // TODO; check argument types.
1543 return equal_type(type1->tt_member, type2->tt_member)
1544 && type1->tt_argcount == type2->tt_argcount;
1545 }
1546 return TRUE;
1547}
1548
1549/*
1550 * Find the common type of "type1" and "type2" and put it in "dest".
1551 * "type2" and "dest" may be the same.
1552 */
1553 static void
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001554common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_list)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001555{
1556 if (equal_type(type1, type2))
1557 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001558 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001559 return;
1560 }
1561
1562 if (type1->tt_type == type2->tt_type)
1563 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001564 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1565 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001566 type_T *common;
1567
1568 common_type(type1->tt_member, type2->tt_member, &common, type_list);
1569 if (type1->tt_type == VAR_LIST)
1570 *dest = get_list_type(common, type_list);
1571 else
1572 *dest = get_dict_type(common, type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001573 return;
1574 }
1575 // TODO: VAR_FUNC and VAR_PARTIAL
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001576 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001577 }
1578
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001579 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001580}
1581
1582 char *
1583vartype_name(vartype_T type)
1584{
1585 switch (type)
1586 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001587 case VAR_UNKNOWN: break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001588 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001589 case VAR_SPECIAL: return "special";
1590 case VAR_BOOL: return "bool";
1591 case VAR_NUMBER: return "number";
1592 case VAR_FLOAT: return "float";
1593 case VAR_STRING: return "string";
1594 case VAR_BLOB: return "blob";
1595 case VAR_JOB: return "job";
1596 case VAR_CHANNEL: return "channel";
1597 case VAR_LIST: return "list";
1598 case VAR_DICT: return "dict";
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001599 case VAR_FUNC: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001600 case VAR_PARTIAL: return "partial";
1601 }
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001602 return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001603}
1604
1605/*
1606 * Return the name of a type.
1607 * The result may be in allocated memory, in which case "tofree" is set.
1608 */
1609 char *
1610type_name(type_T *type, char **tofree)
1611{
1612 char *name = vartype_name(type->tt_type);
1613
1614 *tofree = NULL;
1615 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1616 {
1617 char *member_free;
1618 char *member_name = type_name(type->tt_member, &member_free);
1619 size_t len;
1620
1621 len = STRLEN(name) + STRLEN(member_name) + 3;
1622 *tofree = alloc(len);
1623 if (*tofree != NULL)
1624 {
1625 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1626 vim_free(member_free);
1627 return *tofree;
1628 }
1629 }
1630 // TODO: function and partial argument types
1631
1632 return name;
1633}
1634
1635/*
1636 * Find "name" in script-local items of script "sid".
1637 * Returns the index in "sn_var_vals" if found.
1638 * If found but not in "sn_var_vals" returns -1.
1639 * If not found returns -2.
1640 */
1641 int
1642get_script_item_idx(int sid, char_u *name, int check_writable)
1643{
1644 hashtab_T *ht;
1645 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001646 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001647 int idx;
1648
1649 // First look the name up in the hashtable.
1650 if (sid <= 0 || sid > script_items.ga_len)
1651 return -1;
1652 ht = &SCRIPT_VARS(sid);
1653 di = find_var_in_ht(ht, 0, name, TRUE);
1654 if (di == NULL)
1655 return -2;
1656
1657 // Now find the svar_T index in sn_var_vals.
1658 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
1659 {
1660 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1661
1662 if (sv->sv_tv == &di->di_tv)
1663 {
1664 if (check_writable && sv->sv_const)
1665 semsg(_(e_readonlyvar), name);
1666 return idx;
1667 }
1668 }
1669 return -1;
1670}
1671
1672/*
1673 * Find "name" in imported items of the current script/
1674 */
1675 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001676find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001677{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001678 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001679 int idx;
1680
1681 if (cctx != NULL)
1682 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1683 {
1684 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
1685 + idx;
1686
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001687 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1688 : STRLEN(import->imp_name) == len
1689 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001690 return import;
1691 }
1692
1693 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
1694 {
1695 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
1696
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001697 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1698 : STRLEN(import->imp_name) == len
1699 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001700 return import;
1701 }
1702 return NULL;
1703}
1704
1705/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001706 * Free all imported variables.
1707 */
1708 static void
1709free_imported(cctx_T *cctx)
1710{
1711 int idx;
1712
1713 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1714 {
1715 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
1716
1717 vim_free(import->imp_name);
1718 }
1719 ga_clear(&cctx->ctx_imports);
1720}
1721
1722/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001723 * Generate an instruction to load script-local variable "name".
1724 */
1725 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001726compile_load_scriptvar(
1727 cctx_T *cctx,
1728 char_u *name, // variable NUL terminated
1729 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001730 char_u **end, // end of variable
1731 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001732{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001733 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001734 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
1735 imported_T *import;
1736
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001737 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001738 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001739 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001740 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
1741 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001742 }
1743 if (idx >= 0)
1744 {
1745 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1746
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001747 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001748 current_sctx.sc_sid, idx, sv->sv_type);
1749 return OK;
1750 }
1751
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001752 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001753 if (import != NULL)
1754 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001755 if (import->imp_all)
1756 {
1757 char_u *p = skipwhite(*end);
1758 int name_len;
1759 ufunc_T *ufunc;
1760 type_T *type;
1761
1762 // Used "import * as Name", need to lookup the member.
1763 if (*p != '.')
1764 {
1765 semsg(_("E1060: expected dot after name: %s"), start);
1766 return FAIL;
1767 }
1768 ++p;
1769
1770 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
1771 // TODO: what if it is a function?
1772 if (idx < 0)
1773 return FAIL;
1774 *end = p;
1775
1776 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
1777 import->imp_sid,
1778 idx,
1779 type);
1780 }
1781 else
1782 {
1783 // TODO: check this is a variable, not a function
1784 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
1785 import->imp_sid,
1786 import->imp_var_vals_idx,
1787 import->imp_type);
1788 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001789 return OK;
1790 }
1791
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001792 if (error)
1793 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001794 return FAIL;
1795}
1796
1797/*
1798 * Compile a variable name into a load instruction.
1799 * "end" points to just after the name.
1800 * When "error" is FALSE do not give an error when not found.
1801 */
1802 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001803compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001804{
1805 type_T *type;
1806 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001807 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001808 int res = FAIL;
1809
1810 if (*(*arg + 1) == ':')
1811 {
1812 // load namespaced variable
1813 name = vim_strnsave(*arg + 2, end - (*arg + 2));
1814 if (name == NULL)
1815 return FAIL;
1816
1817 if (**arg == 'v')
1818 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001819 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001820 }
1821 else if (**arg == 'g')
1822 {
1823 // Global variables can be defined later, thus we don't check if it
1824 // exists, give error at runtime.
1825 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
1826 }
1827 else if (**arg == 's')
1828 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001829 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001830 }
1831 else
1832 {
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01001833 semsg("Namespace not supported yet: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001834 goto theend;
1835 }
1836 }
1837 else
1838 {
1839 size_t len = end - *arg;
1840 int idx;
1841 int gen_load = FALSE;
1842
1843 name = vim_strnsave(*arg, end - *arg);
1844 if (name == NULL)
1845 return FAIL;
1846
1847 idx = lookup_arg(*arg, len, cctx);
1848 if (idx >= 0)
1849 {
1850 if (cctx->ctx_ufunc->uf_arg_types != NULL)
1851 type = cctx->ctx_ufunc->uf_arg_types[idx];
1852 else
1853 type = &t_any;
1854
1855 // Arguments are located above the frame pointer.
1856 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
1857 if (cctx->ctx_ufunc->uf_va_name != NULL)
1858 --idx;
1859 gen_load = TRUE;
1860 }
1861 else if (lookup_vararg(*arg, len, cctx))
1862 {
1863 // varargs is always the last argument
1864 idx = -STACK_FRAME_SIZE - 1;
1865 type = cctx->ctx_ufunc->uf_va_type;
1866 gen_load = TRUE;
1867 }
1868 else
1869 {
1870 idx = lookup_local(*arg, len, cctx);
1871 if (idx >= 0)
1872 {
1873 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
1874 gen_load = TRUE;
1875 }
1876 else
1877 {
1878 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
1879 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
1880 res = generate_PUSHBOOL(cctx, **arg == 't'
1881 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001882 else if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
1883 == SCRIPT_VERSION_VIM9)
1884 // in Vim9 script "var" can be script-local.
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001885 res = compile_load_scriptvar(cctx, name, *arg, &end, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001886 }
1887 }
1888 if (gen_load)
1889 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
1890 }
1891
1892 *arg = end;
1893
1894theend:
1895 if (res == FAIL && error)
1896 semsg(_(e_var_notfound), name);
1897 vim_free(name);
1898 return res;
1899}
1900
1901/*
1902 * Compile the argument expressions.
1903 * "arg" points to just after the "(" and is advanced to after the ")"
1904 */
1905 static int
1906compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
1907{
1908 char_u *p = *arg;
1909
1910 while (*p != NUL && *p != ')')
1911 {
1912 if (compile_expr1(&p, cctx) == FAIL)
1913 return FAIL;
1914 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01001915
1916 if (*p != ',' && *skipwhite(p) == ',')
1917 {
1918 emsg(_("E1068: No white space allowed before ,"));
1919 p = skipwhite(p);
1920 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001921 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01001922 {
1923 ++p;
1924 if (!VIM_ISWHITE(*p))
1925 emsg(_("E1069: white space required after ,"));
1926 }
1927 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001928 }
Bram Moolenaar38a5f512020-02-19 12:40:39 +01001929 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001930 if (*p != ')')
1931 {
1932 emsg(_(e_missing_close));
1933 return FAIL;
1934 }
1935 *arg = p + 1;
1936 return OK;
1937}
1938
1939/*
1940 * Compile a function call: name(arg1, arg2)
1941 * "arg" points to "name", "arg + varlen" to the "(".
1942 * "argcount_init" is 1 for "value->method()"
1943 * Instructions:
1944 * EVAL arg1
1945 * EVAL arg2
1946 * BCALL / DCALL / UCALL
1947 */
1948 static int
1949compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
1950{
1951 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01001952 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001953 int argcount = argcount_init;
1954 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001955 char_u fname_buf[FLEN_FIXED + 1];
1956 char_u *tofree = NULL;
1957 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001958 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001959 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001960
1961 if (varlen >= sizeof(namebuf))
1962 {
1963 semsg(_("E1011: name too long: %s"), name);
1964 return FAIL;
1965 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001966 vim_strncpy(namebuf, *arg, varlen);
1967 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001968
1969 *arg = skipwhite(*arg + varlen + 1);
1970 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001971 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001972
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001973 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001974 {
1975 int idx;
1976
1977 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001978 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001979 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001980 {
1981 res = generate_BCALL(cctx, idx, argcount);
1982 goto theend;
1983 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001984 semsg(_(e_unknownfunc), namebuf);
1985 }
1986
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001987 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001988 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001989 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001990 {
1991 res = generate_CALL(cctx, ufunc, argcount);
1992 goto theend;
1993 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001994
1995 // If the name is a variable, load it and use PCALL.
1996 p = namebuf;
1997 if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001998 {
1999 res = generate_PCALL(cctx, argcount, FALSE);
2000 goto theend;
2001 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002002
2003 // The function may be defined only later. Need to figure out at runtime.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002004 res = generate_UCALL(cctx, name, argcount);
2005
2006theend:
2007 vim_free(tofree);
2008 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002009}
2010
2011// like NAMESPACE_CHAR but with 'a' and 'l'.
2012#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2013
2014/*
2015 * Find the end of a variable or function name. Unlike find_name_end() this
2016 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002017 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002018 * Return a pointer to just after the name. Equal to "arg" if there is no
2019 * valid name.
2020 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002021 static char_u *
2022to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002023{
2024 char_u *p;
2025
2026 // Quick check for valid starting character.
2027 if (!eval_isnamec1(*arg))
2028 return arg;
2029
2030 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2031 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2032 // and can be used in slice "[n:]".
2033 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002034 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002035 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2036 break;
2037 return p;
2038}
2039
2040/*
2041 * Like to_name_end() but also skip over a list or dict constant.
2042 */
2043 char_u *
2044to_name_const_end(char_u *arg)
2045{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002046 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002047 typval_T rettv;
2048
2049 if (p == arg && *arg == '[')
2050 {
2051
2052 // Can be "[1, 2, 3]->Func()".
2053 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2054 p = arg;
2055 }
2056 else if (p == arg && *arg == '#' && arg[1] == '{')
2057 {
2058 ++p;
2059 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2060 p = arg;
2061 }
2062 else if (p == arg && *arg == '{')
2063 {
2064 int ret = get_lambda_tv(&p, &rettv, FALSE);
2065
2066 if (ret == NOTDONE)
2067 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2068 if (ret != OK)
2069 p = arg;
2070 }
2071
2072 return p;
2073}
2074
2075 static void
2076type_mismatch(type_T *expected, type_T *actual)
2077{
2078 char *tofree1, *tofree2;
2079
2080 semsg(_("E1013: type mismatch, expected %s but got %s"),
2081 type_name(expected, &tofree1), type_name(actual, &tofree2));
2082 vim_free(tofree1);
2083 vim_free(tofree2);
2084}
2085
2086/*
2087 * Check if the expected and actual types match.
2088 */
2089 static int
2090check_type(type_T *expected, type_T *actual, int give_msg)
2091{
2092 if (expected->tt_type != VAR_UNKNOWN)
2093 {
2094 if (expected->tt_type != actual->tt_type)
2095 {
2096 if (give_msg)
2097 type_mismatch(expected, actual);
2098 return FAIL;
2099 }
2100 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2101 {
Bram Moolenaar436472f2020-02-20 22:54:43 +01002102 int ret;
2103
2104 // void is used for an empty list or dict
2105 if (actual->tt_member == &t_void)
2106 ret = OK;
2107 else
2108 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002109 if (ret == FAIL && give_msg)
2110 type_mismatch(expected, actual);
2111 return ret;
2112 }
2113 }
2114 return OK;
2115}
2116
2117/*
2118 * Check that
2119 * - "actual" is "expected" type or
2120 * - "actual" is a type that can be "expected" type: add a runtime check; or
2121 * - return FAIL.
2122 */
2123 static int
2124need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2125{
Bram Moolenaar436472f2020-02-20 22:54:43 +01002126 if (check_type(expected, actual, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002127 return OK;
2128 if (actual->tt_type != VAR_UNKNOWN)
2129 {
2130 type_mismatch(expected, actual);
2131 return FAIL;
2132 }
2133 generate_TYPECHECK(cctx, expected, offset);
2134 return OK;
2135}
2136
2137/*
2138 * parse a list: [expr, expr]
2139 * "*arg" points to the '['.
2140 */
2141 static int
2142compile_list(char_u **arg, cctx_T *cctx)
2143{
2144 char_u *p = skipwhite(*arg + 1);
2145 int count = 0;
2146
2147 while (*p != ']')
2148 {
2149 if (*p == NUL)
2150 return FAIL;
2151 if (compile_expr1(&p, cctx) == FAIL)
2152 break;
2153 ++count;
2154 if (*p == ',')
2155 ++p;
2156 p = skipwhite(p);
2157 }
2158 *arg = p + 1;
2159
2160 generate_NEWLIST(cctx, count);
2161 return OK;
2162}
2163
2164/*
2165 * parse a lambda: {arg, arg -> expr}
2166 * "*arg" points to the '{'.
2167 */
2168 static int
2169compile_lambda(char_u **arg, cctx_T *cctx)
2170{
2171 garray_T *instr = &cctx->ctx_instr;
2172 typval_T rettv;
2173 ufunc_T *ufunc;
2174
2175 // Get the funcref in "rettv".
2176 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2177 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002178
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002179 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002180 ++ufunc->uf_refcount;
2181 clear_tv(&rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002182
2183 // The function will have one line: "return {expr}".
2184 // Compile it into instructions.
2185 compile_def_function(ufunc, TRUE);
2186
2187 if (ufunc->uf_dfunc_idx >= 0)
2188 {
2189 if (ga_grow(instr, 1) == FAIL)
2190 return FAIL;
2191 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2192 return OK;
2193 }
2194 return FAIL;
2195}
2196
2197/*
2198 * Compile a lamda call: expr->{lambda}(args)
2199 * "arg" points to the "{".
2200 */
2201 static int
2202compile_lambda_call(char_u **arg, cctx_T *cctx)
2203{
2204 ufunc_T *ufunc;
2205 typval_T rettv;
2206 int argcount = 1;
2207 int ret = FAIL;
2208
2209 // Get the funcref in "rettv".
2210 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2211 return FAIL;
2212
2213 if (**arg != '(')
2214 {
2215 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002216 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002217 else
2218 semsg(_(e_missing_paren), "lambda");
2219 clear_tv(&rettv);
2220 return FAIL;
2221 }
2222
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002223 ufunc = rettv.vval.v_partial->pt_func;
2224 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002225 clear_tv(&rettv);
2226
2227 // The function will have one line: "return {expr}".
2228 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002229 compile_def_function(ufunc, TRUE);
2230
2231 // compile the arguments
2232 *arg = skipwhite(*arg + 1);
2233 if (compile_arguments(arg, cctx, &argcount) == OK)
2234 // call the compiled function
2235 ret = generate_CALL(cctx, ufunc, argcount);
2236
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002237 return ret;
2238}
2239
2240/*
2241 * parse a dict: {'key': val} or #{key: val}
2242 * "*arg" points to the '{'.
2243 */
2244 static int
2245compile_dict(char_u **arg, cctx_T *cctx, int literal)
2246{
2247 garray_T *instr = &cctx->ctx_instr;
2248 int count = 0;
2249 dict_T *d = dict_alloc();
2250 dictitem_T *item;
2251
2252 if (d == NULL)
2253 return FAIL;
2254 *arg = skipwhite(*arg + 1);
2255 while (**arg != '}' && **arg != NUL)
2256 {
2257 char_u *key = NULL;
2258
2259 if (literal)
2260 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002261 char_u *p = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002262
2263 if (p == *arg)
2264 {
2265 semsg(_("E1014: Invalid key: %s"), *arg);
2266 return FAIL;
2267 }
2268 key = vim_strnsave(*arg, p - *arg);
2269 if (generate_PUSHS(cctx, key) == FAIL)
2270 return FAIL;
2271 *arg = p;
2272 }
2273 else
2274 {
2275 isn_T *isn;
2276
2277 if (compile_expr1(arg, cctx) == FAIL)
2278 return FAIL;
2279 // TODO: check type is string
2280 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2281 if (isn->isn_type == ISN_PUSHS)
2282 key = isn->isn_arg.string;
2283 }
2284
2285 // Check for duplicate keys, if using string keys.
2286 if (key != NULL)
2287 {
2288 item = dict_find(d, key, -1);
2289 if (item != NULL)
2290 {
2291 semsg(_(e_duplicate_key), key);
2292 goto failret;
2293 }
2294 item = dictitem_alloc(key);
2295 if (item != NULL)
2296 {
2297 item->di_tv.v_type = VAR_UNKNOWN;
2298 item->di_tv.v_lock = 0;
2299 if (dict_add(d, item) == FAIL)
2300 dictitem_free(item);
2301 }
2302 }
2303
2304 *arg = skipwhite(*arg);
2305 if (**arg != ':')
2306 {
2307 semsg(_(e_missing_dict_colon), *arg);
2308 return FAIL;
2309 }
2310
2311 *arg = skipwhite(*arg + 1);
2312 if (compile_expr1(arg, cctx) == FAIL)
2313 return FAIL;
2314 ++count;
2315
2316 if (**arg == '}')
2317 break;
2318 if (**arg != ',')
2319 {
2320 semsg(_(e_missing_dict_comma), *arg);
2321 goto failret;
2322 }
2323 *arg = skipwhite(*arg + 1);
2324 }
2325
2326 if (**arg != '}')
2327 {
2328 semsg(_(e_missing_dict_end), *arg);
2329 goto failret;
2330 }
2331 *arg = *arg + 1;
2332
2333 dict_unref(d);
2334 return generate_NEWDICT(cctx, count);
2335
2336failret:
2337 dict_unref(d);
2338 return FAIL;
2339}
2340
2341/*
2342 * Compile "&option".
2343 */
2344 static int
2345compile_get_option(char_u **arg, cctx_T *cctx)
2346{
2347 typval_T rettv;
2348 char_u *start = *arg;
2349 int ret;
2350
2351 // parse the option and get the current value to get the type.
2352 rettv.v_type = VAR_UNKNOWN;
2353 ret = get_option_tv(arg, &rettv, TRUE);
2354 if (ret == OK)
2355 {
2356 // include the '&' in the name, get_option_tv() expects it.
2357 char_u *name = vim_strnsave(start, *arg - start);
2358 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2359
2360 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2361 vim_free(name);
2362 }
2363 clear_tv(&rettv);
2364
2365 return ret;
2366}
2367
2368/*
2369 * Compile "$VAR".
2370 */
2371 static int
2372compile_get_env(char_u **arg, cctx_T *cctx)
2373{
2374 char_u *start = *arg;
2375 int len;
2376 int ret;
2377 char_u *name;
2378
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002379 ++*arg;
2380 len = get_env_len(arg);
2381 if (len == 0)
2382 {
2383 semsg(_(e_syntax_at), start - 1);
2384 return FAIL;
2385 }
2386
2387 // include the '$' in the name, get_env_tv() expects it.
2388 name = vim_strnsave(start, len + 1);
2389 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2390 vim_free(name);
2391 return ret;
2392}
2393
2394/*
2395 * Compile "@r".
2396 */
2397 static int
2398compile_get_register(char_u **arg, cctx_T *cctx)
2399{
2400 int ret;
2401
2402 ++*arg;
2403 if (**arg == NUL)
2404 {
2405 semsg(_(e_syntax_at), *arg - 1);
2406 return FAIL;
2407 }
2408 if (!valid_yank_reg(**arg, TRUE))
2409 {
2410 emsg_invreg(**arg);
2411 return FAIL;
2412 }
2413 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2414 ++*arg;
2415 return ret;
2416}
2417
2418/*
2419 * Apply leading '!', '-' and '+' to constant "rettv".
2420 */
2421 static int
2422apply_leader(typval_T *rettv, char_u *start, char_u *end)
2423{
2424 char_u *p = end;
2425
2426 // this works from end to start
2427 while (p > start)
2428 {
2429 --p;
2430 if (*p == '-' || *p == '+')
2431 {
2432 // only '-' has an effect, for '+' we only check the type
2433#ifdef FEAT_FLOAT
2434 if (rettv->v_type == VAR_FLOAT)
2435 {
2436 if (*p == '-')
2437 rettv->vval.v_float = -rettv->vval.v_float;
2438 }
2439 else
2440#endif
2441 {
2442 varnumber_T val;
2443 int error = FALSE;
2444
2445 // tv_get_number_chk() accepts a string, but we don't want that
2446 // here
2447 if (check_not_string(rettv) == FAIL)
2448 return FAIL;
2449 val = tv_get_number_chk(rettv, &error);
2450 clear_tv(rettv);
2451 if (error)
2452 return FAIL;
2453 if (*p == '-')
2454 val = -val;
2455 rettv->v_type = VAR_NUMBER;
2456 rettv->vval.v_number = val;
2457 }
2458 }
2459 else
2460 {
2461 int v = tv2bool(rettv);
2462
2463 // '!' is permissive in the type.
2464 clear_tv(rettv);
2465 rettv->v_type = VAR_BOOL;
2466 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
2467 }
2468 }
2469 return OK;
2470}
2471
2472/*
2473 * Recognize v: variables that are constants and set "rettv".
2474 */
2475 static void
2476get_vim_constant(char_u **arg, typval_T *rettv)
2477{
2478 if (STRNCMP(*arg, "v:true", 6) == 0)
2479 {
2480 rettv->v_type = VAR_BOOL;
2481 rettv->vval.v_number = VVAL_TRUE;
2482 *arg += 6;
2483 }
2484 else if (STRNCMP(*arg, "v:false", 7) == 0)
2485 {
2486 rettv->v_type = VAR_BOOL;
2487 rettv->vval.v_number = VVAL_FALSE;
2488 *arg += 7;
2489 }
2490 else if (STRNCMP(*arg, "v:null", 6) == 0)
2491 {
2492 rettv->v_type = VAR_SPECIAL;
2493 rettv->vval.v_number = VVAL_NULL;
2494 *arg += 6;
2495 }
2496 else if (STRNCMP(*arg, "v:none", 6) == 0)
2497 {
2498 rettv->v_type = VAR_SPECIAL;
2499 rettv->vval.v_number = VVAL_NONE;
2500 *arg += 6;
2501 }
2502}
2503
2504/*
2505 * Compile code to apply '-', '+' and '!'.
2506 */
2507 static int
2508compile_leader(cctx_T *cctx, char_u *start, char_u *end)
2509{
2510 char_u *p = end;
2511
2512 // this works from end to start
2513 while (p > start)
2514 {
2515 --p;
2516 if (*p == '-' || *p == '+')
2517 {
2518 int negate = *p == '-';
2519 isn_T *isn;
2520
2521 // TODO: check type
2522 while (p > start && (p[-1] == '-' || p[-1] == '+'))
2523 {
2524 --p;
2525 if (*p == '-')
2526 negate = !negate;
2527 }
2528 // only '-' has an effect, for '+' we only check the type
2529 if (negate)
2530 isn = generate_instr(cctx, ISN_NEGATENR);
2531 else
2532 isn = generate_instr(cctx, ISN_CHECKNR);
2533 if (isn == NULL)
2534 return FAIL;
2535 }
2536 else
2537 {
2538 int invert = TRUE;
2539
2540 while (p > start && p[-1] == '!')
2541 {
2542 --p;
2543 invert = !invert;
2544 }
2545 if (generate_2BOOL(cctx, invert) == FAIL)
2546 return FAIL;
2547 }
2548 }
2549 return OK;
2550}
2551
2552/*
2553 * Compile whatever comes after "name" or "name()".
2554 */
2555 static int
2556compile_subscript(
2557 char_u **arg,
2558 cctx_T *cctx,
2559 char_u **start_leader,
2560 char_u *end_leader)
2561{
2562 for (;;)
2563 {
2564 if (**arg == '(')
2565 {
2566 int argcount = 0;
2567
2568 // funcref(arg)
2569 *arg = skipwhite(*arg + 1);
2570 if (compile_arguments(arg, cctx, &argcount) == FAIL)
2571 return FAIL;
2572 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
2573 return FAIL;
2574 }
2575 else if (**arg == '-' && (*arg)[1] == '>')
2576 {
2577 char_u *p;
2578
2579 // something->method()
2580 // Apply the '!', '-' and '+' first:
2581 // -1.0->func() works like (-1.0)->func()
2582 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
2583 return FAIL;
2584 *start_leader = end_leader; // don't apply again later
2585
2586 *arg = skipwhite(*arg + 2);
2587 if (**arg == '{')
2588 {
2589 // lambda call: list->{lambda}
2590 if (compile_lambda_call(arg, cctx) == FAIL)
2591 return FAIL;
2592 }
2593 else
2594 {
2595 // method call: list->method()
2596 for (p = *arg; eval_isnamec1(*p); ++p)
2597 ;
2598 if (*p != '(')
2599 {
2600 semsg(_(e_missing_paren), arg);
2601 return FAIL;
2602 }
2603 // TODO: base value may not be the first argument
2604 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
2605 return FAIL;
2606 }
2607 }
2608 else if (**arg == '[')
2609 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01002610 garray_T *stack;
2611 type_T **typep;
2612
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002613 // list index: list[123]
2614 // TODO: more arguments
2615 // TODO: dict member dict['name']
2616 *arg = skipwhite(*arg + 1);
2617 if (compile_expr1(arg, cctx) == FAIL)
2618 return FAIL;
2619
2620 if (**arg != ']')
2621 {
2622 emsg(_(e_missbrac));
2623 return FAIL;
2624 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01002625 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002626
2627 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
2628 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01002629 stack = &cctx->ctx_type_stack;
2630 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
2631 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
2632 {
2633 emsg(_(e_listreq));
2634 return FAIL;
2635 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01002636 if ((*typep)->tt_type == VAR_LIST)
2637 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002638 }
2639 else if (**arg == '.' && (*arg)[1] != '.')
2640 {
2641 char_u *p;
2642
2643 ++*arg;
2644 p = *arg;
2645 // dictionary member: dict.name
2646 if (eval_isnamec1(*p))
2647 while (eval_isnamec(*p))
2648 MB_PTR_ADV(p);
2649 if (p == *arg)
2650 {
2651 semsg(_(e_syntax_at), *arg);
2652 return FAIL;
2653 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002654 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
2655 return FAIL;
2656 *arg = p;
2657 }
2658 else
2659 break;
2660 }
2661
2662 // TODO - see handle_subscript():
2663 // Turn "dict.Func" into a partial for "Func" bound to "dict".
2664 // Don't do this when "Func" is already a partial that was bound
2665 // explicitly (pt_auto is FALSE).
2666
2667 return OK;
2668}
2669
2670/*
2671 * Compile an expression at "*p" and add instructions to "instr".
2672 * "p" is advanced until after the expression, skipping white space.
2673 *
2674 * This is the equivalent of eval1(), eval2(), etc.
2675 */
2676
2677/*
2678 * number number constant
2679 * 0zFFFFFFFF Blob constant
2680 * "string" string constant
2681 * 'string' literal string constant
2682 * &option-name option value
2683 * @r register contents
2684 * identifier variable value
2685 * function() function call
2686 * $VAR environment variable
2687 * (expression) nested expression
2688 * [expr, expr] List
2689 * {key: val, key: val} Dictionary
2690 * #{key: val, key: val} Dictionary with literal keys
2691 *
2692 * Also handle:
2693 * ! in front logical NOT
2694 * - in front unary minus
2695 * + in front unary plus (ignored)
2696 * trailing (arg) funcref/partial call
2697 * trailing [] subscript in String or List
2698 * trailing .name entry in Dictionary
2699 * trailing ->name() method call
2700 */
2701 static int
2702compile_expr7(char_u **arg, cctx_T *cctx)
2703{
2704 typval_T rettv;
2705 char_u *start_leader, *end_leader;
2706 int ret = OK;
2707
2708 /*
2709 * Skip '!', '-' and '+' characters. They are handled later.
2710 */
2711 start_leader = *arg;
2712 while (**arg == '!' || **arg == '-' || **arg == '+')
2713 *arg = skipwhite(*arg + 1);
2714 end_leader = *arg;
2715
2716 rettv.v_type = VAR_UNKNOWN;
2717 switch (**arg)
2718 {
2719 /*
2720 * Number constant.
2721 */
2722 case '0': // also for blob starting with 0z
2723 case '1':
2724 case '2':
2725 case '3':
2726 case '4':
2727 case '5':
2728 case '6':
2729 case '7':
2730 case '8':
2731 case '9':
2732 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
2733 return FAIL;
2734 break;
2735
2736 /*
2737 * String constant: "string".
2738 */
2739 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
2740 return FAIL;
2741 break;
2742
2743 /*
2744 * Literal string constant: 'str''ing'.
2745 */
2746 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
2747 return FAIL;
2748 break;
2749
2750 /*
2751 * Constant Vim variable.
2752 */
2753 case 'v': get_vim_constant(arg, &rettv);
2754 ret = NOTDONE;
2755 break;
2756
2757 /*
2758 * List: [expr, expr]
2759 */
2760 case '[': ret = compile_list(arg, cctx);
2761 break;
2762
2763 /*
2764 * Dictionary: #{key: val, key: val}
2765 */
2766 case '#': if ((*arg)[1] == '{')
2767 {
2768 ++*arg;
2769 ret = compile_dict(arg, cctx, TRUE);
2770 }
2771 else
2772 ret = NOTDONE;
2773 break;
2774
2775 /*
2776 * Lambda: {arg, arg -> expr}
2777 * Dictionary: {'key': val, 'key': val}
2778 */
2779 case '{': {
2780 char_u *start = skipwhite(*arg + 1);
2781
2782 // Find out what comes after the arguments.
2783 ret = get_function_args(&start, '-', NULL,
2784 NULL, NULL, NULL, TRUE);
2785 if (ret != FAIL && *start == '>')
2786 ret = compile_lambda(arg, cctx);
2787 else
2788 ret = compile_dict(arg, cctx, FALSE);
2789 }
2790 break;
2791
2792 /*
2793 * Option value: &name
2794 */
2795 case '&': ret = compile_get_option(arg, cctx);
2796 break;
2797
2798 /*
2799 * Environment variable: $VAR.
2800 */
2801 case '$': ret = compile_get_env(arg, cctx);
2802 break;
2803
2804 /*
2805 * Register contents: @r.
2806 */
2807 case '@': ret = compile_get_register(arg, cctx);
2808 break;
2809 /*
2810 * nested expression: (expression).
2811 */
2812 case '(': *arg = skipwhite(*arg + 1);
2813 ret = compile_expr1(arg, cctx); // recursive!
2814 *arg = skipwhite(*arg);
2815 if (**arg == ')')
2816 ++*arg;
2817 else if (ret == OK)
2818 {
2819 emsg(_(e_missing_close));
2820 ret = FAIL;
2821 }
2822 break;
2823
2824 default: ret = NOTDONE;
2825 break;
2826 }
2827 if (ret == FAIL)
2828 return FAIL;
2829
2830 if (rettv.v_type != VAR_UNKNOWN)
2831 {
2832 // apply the '!', '-' and '+' before the constant
2833 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
2834 {
2835 clear_tv(&rettv);
2836 return FAIL;
2837 }
2838 start_leader = end_leader; // don't apply again below
2839
2840 // push constant
2841 switch (rettv.v_type)
2842 {
2843 case VAR_BOOL:
2844 generate_PUSHBOOL(cctx, rettv.vval.v_number);
2845 break;
2846 case VAR_SPECIAL:
2847 generate_PUSHSPEC(cctx, rettv.vval.v_number);
2848 break;
2849 case VAR_NUMBER:
2850 generate_PUSHNR(cctx, rettv.vval.v_number);
2851 break;
2852#ifdef FEAT_FLOAT
2853 case VAR_FLOAT:
2854 generate_PUSHF(cctx, rettv.vval.v_float);
2855 break;
2856#endif
2857 case VAR_BLOB:
2858 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
2859 rettv.vval.v_blob = NULL;
2860 break;
2861 case VAR_STRING:
2862 generate_PUSHS(cctx, rettv.vval.v_string);
2863 rettv.vval.v_string = NULL;
2864 break;
2865 default:
2866 iemsg("constant type missing");
2867 return FAIL;
2868 }
2869 }
2870 else if (ret == NOTDONE)
2871 {
2872 char_u *p;
2873 int r;
2874
2875 if (!eval_isnamec1(**arg))
2876 {
2877 semsg(_("E1015: Name expected: %s"), *arg);
2878 return FAIL;
2879 }
2880
2881 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002882 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002883 if (*p == '(')
2884 r = compile_call(arg, p - *arg, cctx, 0);
2885 else
2886 r = compile_load(arg, p, cctx, TRUE);
2887 if (r == FAIL)
2888 return FAIL;
2889 }
2890
2891 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
2892 return FAIL;
2893
2894 // Now deal with prefixed '-', '+' and '!', if not done already.
2895 return compile_leader(cctx, start_leader, end_leader);
2896}
2897
2898/*
2899 * * number multiplication
2900 * / number division
2901 * % number modulo
2902 */
2903 static int
2904compile_expr6(char_u **arg, cctx_T *cctx)
2905{
2906 char_u *op;
2907
2908 // get the first variable
2909 if (compile_expr7(arg, cctx) == FAIL)
2910 return FAIL;
2911
2912 /*
2913 * Repeat computing, until no "*", "/" or "%" is following.
2914 */
2915 for (;;)
2916 {
2917 op = skipwhite(*arg);
2918 if (*op != '*' && *op != '/' && *op != '%')
2919 break;
2920 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[1]))
2921 {
2922 char_u buf[3];
2923
2924 vim_strncpy(buf, op, 1);
2925 semsg(_(e_white_both), buf);
2926 }
2927 *arg = skipwhite(op + 1);
2928
2929 // get the second variable
2930 if (compile_expr7(arg, cctx) == FAIL)
2931 return FAIL;
2932
2933 generate_two_op(cctx, op);
2934 }
2935
2936 return OK;
2937}
2938
2939/*
2940 * + number addition
2941 * - number subtraction
2942 * .. string concatenation
2943 */
2944 static int
2945compile_expr5(char_u **arg, cctx_T *cctx)
2946{
2947 char_u *op;
2948 int oplen;
2949
2950 // get the first variable
2951 if (compile_expr6(arg, cctx) == FAIL)
2952 return FAIL;
2953
2954 /*
2955 * Repeat computing, until no "+", "-" or ".." is following.
2956 */
2957 for (;;)
2958 {
2959 op = skipwhite(*arg);
2960 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
2961 break;
2962 oplen = (*op == '.' ? 2 : 1);
2963
2964 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[oplen]))
2965 {
2966 char_u buf[3];
2967
2968 vim_strncpy(buf, op, oplen);
2969 semsg(_(e_white_both), buf);
2970 }
2971
2972 *arg = skipwhite(op + oplen);
2973
2974 // get the second variable
2975 if (compile_expr6(arg, cctx) == FAIL)
2976 return FAIL;
2977
2978 if (*op == '.')
2979 {
2980 if (may_generate_2STRING(-2, cctx) == FAIL
2981 || may_generate_2STRING(-1, cctx) == FAIL)
2982 return FAIL;
2983 generate_instr_drop(cctx, ISN_CONCAT, 1);
2984 }
2985 else
2986 generate_two_op(cctx, op);
2987 }
2988
2989 return OK;
2990}
2991
Bram Moolenaar080457c2020-03-03 21:53:32 +01002992 static exptype_T
2993get_compare_type(char_u *p, int *len, int *type_is)
2994{
2995 exptype_T type = EXPR_UNKNOWN;
2996 int i;
2997
2998 switch (p[0])
2999 {
3000 case '=': if (p[1] == '=')
3001 type = EXPR_EQUAL;
3002 else if (p[1] == '~')
3003 type = EXPR_MATCH;
3004 break;
3005 case '!': if (p[1] == '=')
3006 type = EXPR_NEQUAL;
3007 else if (p[1] == '~')
3008 type = EXPR_NOMATCH;
3009 break;
3010 case '>': if (p[1] != '=')
3011 {
3012 type = EXPR_GREATER;
3013 *len = 1;
3014 }
3015 else
3016 type = EXPR_GEQUAL;
3017 break;
3018 case '<': if (p[1] != '=')
3019 {
3020 type = EXPR_SMALLER;
3021 *len = 1;
3022 }
3023 else
3024 type = EXPR_SEQUAL;
3025 break;
3026 case 'i': if (p[1] == 's')
3027 {
3028 // "is" and "isnot"; but not a prefix of a name
3029 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3030 *len = 5;
3031 i = p[*len];
3032 if (!isalnum(i) && i != '_')
3033 {
3034 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3035 *type_is = TRUE;
3036 }
3037 }
3038 break;
3039 }
3040 return type;
3041}
3042
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003043/*
3044 * expr5a == expr5b
3045 * expr5a =~ expr5b
3046 * expr5a != expr5b
3047 * expr5a !~ expr5b
3048 * expr5a > expr5b
3049 * expr5a >= expr5b
3050 * expr5a < expr5b
3051 * expr5a <= expr5b
3052 * expr5a is expr5b
3053 * expr5a isnot expr5b
3054 *
3055 * Produces instructions:
3056 * EVAL expr5a Push result of "expr5a"
3057 * EVAL expr5b Push result of "expr5b"
3058 * COMPARE one of the compare instructions
3059 */
3060 static int
3061compile_expr4(char_u **arg, cctx_T *cctx)
3062{
3063 exptype_T type = EXPR_UNKNOWN;
3064 char_u *p;
3065 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003066 int type_is = FALSE;
3067
3068 // get the first variable
3069 if (compile_expr5(arg, cctx) == FAIL)
3070 return FAIL;
3071
3072 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003073 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003074
3075 /*
3076 * If there is a comparative operator, use it.
3077 */
3078 if (type != EXPR_UNKNOWN)
3079 {
3080 int ic = FALSE; // Default: do not ignore case
3081
3082 if (type_is && (p[len] == '?' || p[len] == '#'))
3083 {
3084 semsg(_(e_invexpr2), *arg);
3085 return FAIL;
3086 }
3087 // extra question mark appended: ignore case
3088 if (p[len] == '?')
3089 {
3090 ic = TRUE;
3091 ++len;
3092 }
3093 // extra '#' appended: match case (ignored)
3094 else if (p[len] == '#')
3095 ++len;
3096 // nothing appended: match case
3097
3098 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[len]))
3099 {
3100 char_u buf[7];
3101
3102 vim_strncpy(buf, p, len);
3103 semsg(_(e_white_both), buf);
3104 }
3105
3106 // get the second variable
3107 *arg = skipwhite(p + len);
3108 if (compile_expr5(arg, cctx) == FAIL)
3109 return FAIL;
3110
3111 generate_COMPARE(cctx, type, ic);
3112 }
3113
3114 return OK;
3115}
3116
3117/*
3118 * Compile || or &&.
3119 */
3120 static int
3121compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3122{
3123 char_u *p = skipwhite(*arg);
3124 int opchar = *op;
3125
3126 if (p[0] == opchar && p[1] == opchar)
3127 {
3128 garray_T *instr = &cctx->ctx_instr;
3129 garray_T end_ga;
3130
3131 /*
3132 * Repeat until there is no following "||" or "&&"
3133 */
3134 ga_init2(&end_ga, sizeof(int), 10);
3135 while (p[0] == opchar && p[1] == opchar)
3136 {
3137 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
3138 semsg(_(e_white_both), op);
3139
3140 if (ga_grow(&end_ga, 1) == FAIL)
3141 {
3142 ga_clear(&end_ga);
3143 return FAIL;
3144 }
3145 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3146 ++end_ga.ga_len;
3147 generate_JUMP(cctx, opchar == '|'
3148 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3149
3150 // eval the next expression
3151 *arg = skipwhite(p + 2);
3152 if ((opchar == '|' ? compile_expr3(arg, cctx)
3153 : compile_expr4(arg, cctx)) == FAIL)
3154 {
3155 ga_clear(&end_ga);
3156 return FAIL;
3157 }
3158 p = skipwhite(*arg);
3159 }
3160
3161 // Fill in the end label in all jumps.
3162 while (end_ga.ga_len > 0)
3163 {
3164 isn_T *isn;
3165
3166 --end_ga.ga_len;
3167 isn = ((isn_T *)instr->ga_data)
3168 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3169 isn->isn_arg.jump.jump_where = instr->ga_len;
3170 }
3171 ga_clear(&end_ga);
3172 }
3173
3174 return OK;
3175}
3176
3177/*
3178 * expr4a && expr4a && expr4a logical AND
3179 *
3180 * Produces instructions:
3181 * EVAL expr4a Push result of "expr4a"
3182 * JUMP_AND_KEEP_IF_FALSE end
3183 * EVAL expr4b Push result of "expr4b"
3184 * JUMP_AND_KEEP_IF_FALSE end
3185 * EVAL expr4c Push result of "expr4c"
3186 * end:
3187 */
3188 static int
3189compile_expr3(char_u **arg, cctx_T *cctx)
3190{
3191 // get the first variable
3192 if (compile_expr4(arg, cctx) == FAIL)
3193 return FAIL;
3194
3195 // || and && work almost the same
3196 return compile_and_or(arg, cctx, "&&");
3197}
3198
3199/*
3200 * expr3a || expr3b || expr3c logical OR
3201 *
3202 * Produces instructions:
3203 * EVAL expr3a Push result of "expr3a"
3204 * JUMP_AND_KEEP_IF_TRUE end
3205 * EVAL expr3b Push result of "expr3b"
3206 * JUMP_AND_KEEP_IF_TRUE end
3207 * EVAL expr3c Push result of "expr3c"
3208 * end:
3209 */
3210 static int
3211compile_expr2(char_u **arg, cctx_T *cctx)
3212{
3213 // eval the first expression
3214 if (compile_expr3(arg, cctx) == FAIL)
3215 return FAIL;
3216
3217 // || and && work almost the same
3218 return compile_and_or(arg, cctx, "||");
3219}
3220
3221/*
3222 * Toplevel expression: expr2 ? expr1a : expr1b
3223 *
3224 * Produces instructions:
3225 * EVAL expr2 Push result of "expr"
3226 * JUMP_IF_FALSE alt jump if false
3227 * EVAL expr1a
3228 * JUMP_ALWAYS end
3229 * alt: EVAL expr1b
3230 * end:
3231 */
3232 static int
3233compile_expr1(char_u **arg, cctx_T *cctx)
3234{
3235 char_u *p;
3236
3237 // evaluate the first expression
3238 if (compile_expr2(arg, cctx) == FAIL)
3239 return FAIL;
3240
3241 p = skipwhite(*arg);
3242 if (*p == '?')
3243 {
3244 garray_T *instr = &cctx->ctx_instr;
3245 garray_T *stack = &cctx->ctx_type_stack;
3246 int alt_idx = instr->ga_len;
3247 int end_idx;
3248 isn_T *isn;
3249 type_T *type1;
3250 type_T *type2;
3251
3252 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3253 semsg(_(e_white_both), "?");
3254
3255 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3256
3257 // evaluate the second expression; any type is accepted
3258 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003259 if (compile_expr1(arg, cctx) == FAIL)
3260 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003261
3262 // remember the type and drop it
3263 --stack->ga_len;
3264 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3265
3266 end_idx = instr->ga_len;
3267 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3268
3269 // jump here from JUMP_IF_FALSE
3270 isn = ((isn_T *)instr->ga_data) + alt_idx;
3271 isn->isn_arg.jump.jump_where = instr->ga_len;
3272
3273 // Check for the ":".
3274 p = skipwhite(*arg);
3275 if (*p != ':')
3276 {
3277 emsg(_(e_missing_colon));
3278 return FAIL;
3279 }
3280 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3281 semsg(_(e_white_both), ":");
3282
3283 // evaluate the third expression
3284 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003285 if (compile_expr1(arg, cctx) == FAIL)
3286 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003287
3288 // If the types differ, the result has a more generic type.
3289 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003290 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003291
3292 // jump here from JUMP_ALWAYS
3293 isn = ((isn_T *)instr->ga_data) + end_idx;
3294 isn->isn_arg.jump.jump_where = instr->ga_len;
3295 }
3296 return OK;
3297}
3298
3299/*
3300 * compile "return [expr]"
3301 */
3302 static char_u *
3303compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3304{
3305 char_u *p = arg;
3306 garray_T *stack = &cctx->ctx_type_stack;
3307 type_T *stack_type;
3308
3309 if (*p != NUL && *p != '|' && *p != '\n')
3310 {
3311 // compile return argument into instructions
3312 if (compile_expr1(&p, cctx) == FAIL)
3313 return NULL;
3314
3315 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3316 if (set_return_type)
3317 cctx->ctx_ufunc->uf_ret_type = stack_type;
3318 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3319 == FAIL)
3320 return NULL;
3321 }
3322 else
3323 {
3324 if (set_return_type)
3325 cctx->ctx_ufunc->uf_ret_type = &t_void;
3326 else if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID)
3327 {
3328 emsg(_("E1003: Missing return value"));
3329 return NULL;
3330 }
3331
3332 // No argument, return zero.
3333 generate_PUSHNR(cctx, 0);
3334 }
3335
3336 if (generate_instr(cctx, ISN_RETURN) == NULL)
3337 return NULL;
3338
3339 // "return val | endif" is possible
3340 return skipwhite(p);
3341}
3342
3343/*
3344 * Return the length of an assignment operator, or zero if there isn't one.
3345 */
3346 int
3347assignment_len(char_u *p, int *heredoc)
3348{
3349 if (*p == '=')
3350 {
3351 if (p[1] == '<' && p[2] == '<')
3352 {
3353 *heredoc = TRUE;
3354 return 3;
3355 }
3356 return 1;
3357 }
3358 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3359 return 2;
3360 if (STRNCMP(p, "..=", 3) == 0)
3361 return 3;
3362 return 0;
3363}
3364
3365// words that cannot be used as a variable
3366static char *reserved[] = {
3367 "true",
3368 "false",
3369 NULL
3370};
3371
3372/*
3373 * Get a line for "=<<".
3374 * Return a pointer to the line in allocated memory.
3375 * Return NULL for end-of-file or some error.
3376 */
3377 static char_u *
3378heredoc_getline(
3379 int c UNUSED,
3380 void *cookie,
3381 int indent UNUSED,
3382 int do_concat UNUSED)
3383{
3384 cctx_T *cctx = (cctx_T *)cookie;
3385
3386 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
3387 NULL;
3388 ++cctx->ctx_lnum;
3389 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3390 [cctx->ctx_lnum]);
3391}
3392
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003393typedef enum {
3394 dest_local,
3395 dest_option,
3396 dest_env,
3397 dest_global,
3398 dest_vimvar,
3399 dest_script,
3400 dest_reg,
3401} assign_dest_T;
3402
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003403/*
3404 * compile "let var [= expr]", "const var = expr" and "var = expr"
3405 * "arg" points to "var".
3406 */
3407 static char_u *
3408compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3409{
3410 char_u *p;
3411 char_u *ret = NULL;
3412 int var_count = 0;
3413 int semicolon = 0;
3414 size_t varlen;
3415 garray_T *instr = &cctx->ctx_instr;
3416 int idx = -1;
3417 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003418 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003419 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003420 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003421 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003422 int oplen = 0;
3423 int heredoc = FALSE;
3424 type_T *type;
3425 lvar_T *lvar;
3426 char_u *name;
3427 char_u *sp;
3428 int has_type = FALSE;
3429 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
3430 int instr_count = -1;
3431
3432 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
3433 if (p == NULL)
3434 return NULL;
3435 if (var_count > 0)
3436 {
3437 // TODO: let [var, var] = list
3438 emsg("Cannot handle a list yet");
3439 return NULL;
3440 }
3441
3442 varlen = p - arg;
3443 name = vim_strnsave(arg, (int)varlen);
3444 if (name == NULL)
3445 return NULL;
3446
Bram Moolenaar080457c2020-03-03 21:53:32 +01003447 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003448 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003449 if (*arg == '&')
3450 {
3451 int cc;
3452 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003453
Bram Moolenaar080457c2020-03-03 21:53:32 +01003454 dest = dest_option;
3455 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003456 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003457 emsg(_(e_const_option));
3458 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003459 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003460 if (is_decl)
3461 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003462 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003463 goto theend;
3464 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01003465 p = arg;
3466 p = find_option_end(&p, &opt_flags);
3467 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003468 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003469 emsg(_(e_letunexp));
3470 return NULL;
3471 }
3472 cc = *p;
3473 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003474 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003475 *p = cc;
3476 if (opt_type == -3)
3477 {
3478 semsg(_(e_unknown_option), *arg);
3479 return NULL;
3480 }
3481 if (opt_type == -2 || opt_type == 0)
3482 type = &t_string;
3483 else
3484 type = &t_number; // both number and boolean option
3485 }
3486 else if (*arg == '$')
3487 {
3488 dest = dest_env;
3489 if (is_decl)
3490 {
3491 semsg(_("E1065: Cannot declare an environment variable: %s"), name);
3492 goto theend;
3493 }
3494 }
3495 else if (*arg == '@')
3496 {
3497 if (!valid_yank_reg(arg[1], TRUE))
3498 {
3499 emsg_invreg(arg[1]);
3500 return FAIL;
3501 }
3502 dest = dest_reg;
3503 if (is_decl)
3504 {
3505 semsg(_("E1066: Cannot declare a register: %s"), name);
3506 goto theend;
3507 }
3508 }
3509 else if (STRNCMP(arg, "g:", 2) == 0)
3510 {
3511 dest = dest_global;
3512 if (is_decl)
3513 {
3514 semsg(_("E1016: Cannot declare a global variable: %s"), name);
3515 goto theend;
3516 }
3517 }
3518 else if (STRNCMP(arg, "v:", 2) == 0)
3519 {
3520 vimvaridx = find_vim_var(name + 2);
3521 if (vimvaridx < 0)
3522 {
3523 semsg(_(e_var_notfound), arg);
3524 goto theend;
3525 }
3526 dest = dest_vimvar;
3527 if (is_decl)
3528 {
3529 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
3530 goto theend;
3531 }
3532 }
3533 else
3534 {
3535 for (idx = 0; reserved[idx] != NULL; ++idx)
3536 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003537 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003538 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003539 goto theend;
3540 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01003541
3542 idx = lookup_local(arg, varlen, cctx);
3543 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003544 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003545 if (is_decl)
3546 {
3547 semsg(_("E1017: Variable already declared: %s"), name);
3548 goto theend;
3549 }
3550 else
3551 {
3552 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3553 if (lvar->lv_const)
3554 {
3555 semsg(_("E1018: Cannot assign to a constant: %s"), name);
3556 goto theend;
3557 }
3558 }
3559 }
3560 else if (STRNCMP(arg, "s:", 2) == 0
3561 || lookup_script(arg, varlen) == OK
3562 || find_imported(arg, varlen, cctx) != NULL)
3563 {
3564 dest = dest_script;
3565 if (is_decl)
3566 {
3567 semsg(_("E1054: Variable already declared in the script: %s"),
3568 name);
3569 goto theend;
3570 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003571 }
3572 }
3573 }
3574
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003575 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003576 {
3577 if (is_decl && *p == ':')
3578 {
3579 // parse optional type: "let var: type = expr"
3580 p = skipwhite(p + 1);
3581 type = parse_type(&p, cctx->ctx_type_list);
3582 if (type == NULL)
3583 goto theend;
3584 has_type = TRUE;
3585 }
3586 else if (idx < 0)
3587 {
3588 // global and new local default to "any" type
3589 type = &t_any;
3590 }
3591 else
3592 {
3593 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3594 type = lvar->lv_type;
3595 }
3596 }
3597
3598 sp = p;
3599 p = skipwhite(p);
3600 op = p;
3601 oplen = assignment_len(p, &heredoc);
3602 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
3603 {
3604 char_u buf[4];
3605
3606 vim_strncpy(buf, op, oplen);
3607 semsg(_(e_white_both), buf);
3608 }
3609
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003610 if (oplen == 3 && !heredoc && dest != dest_global
3611 && type->tt_type != VAR_STRING && type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003612 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01003613 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003614 goto theend;
3615 }
3616
3617 // +=, /=, etc. require an existing variable
Bram Moolenaar080457c2020-03-03 21:53:32 +01003618 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003619 {
3620 if (oplen > 1 && !heredoc)
3621 {
3622 semsg(_("E1020: cannot use an operator on a new variable: %s"),
3623 name);
3624 goto theend;
3625 }
3626
3627 // new local variable
3628 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
3629 if (idx < 0)
3630 goto theend;
3631 }
3632
3633 if (heredoc)
3634 {
3635 list_T *l;
3636 listitem_T *li;
3637
3638 // [let] varname =<< [trim] {end}
3639 eap->getline = heredoc_getline;
3640 eap->cookie = cctx;
3641 l = heredoc_get(eap, op + 3);
3642
3643 // Push each line and the create the list.
3644 for (li = l->lv_first; li != NULL; li = li->li_next)
3645 {
3646 generate_PUSHS(cctx, li->li_tv.vval.v_string);
3647 li->li_tv.vval.v_string = NULL;
3648 }
3649 generate_NEWLIST(cctx, l->lv_len);
3650 type = &t_list_string;
3651 list_free(l);
3652 p += STRLEN(p);
3653 }
3654 else if (oplen > 0)
3655 {
3656 // for "+=", "*=", "..=" etc. first load the current value
3657 if (*op != '=')
3658 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003659 switch (dest)
3660 {
3661 case dest_option:
3662 // TODO: check the option exists
3663 generate_LOAD(cctx, ISN_LOADOPT, 0, name + 1, type);
3664 break;
3665 case dest_global:
3666 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
3667 break;
3668 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01003669 compile_load_scriptvar(cctx,
3670 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003671 break;
3672 case dest_env:
3673 // Include $ in the name here
3674 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
3675 break;
3676 case dest_reg:
3677 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
3678 break;
3679 case dest_vimvar:
3680 generate_LOADV(cctx, name + 2, TRUE);
3681 break;
3682 case dest_local:
3683 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
3684 break;
3685 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003686 }
3687
3688 // compile the expression
3689 instr_count = instr->ga_len;
3690 p = skipwhite(p + oplen);
3691 if (compile_expr1(&p, cctx) == FAIL)
3692 goto theend;
3693
3694 if (idx >= 0 && (is_decl || !has_type))
3695 {
3696 garray_T *stack = &cctx->ctx_type_stack;
3697 type_T *stacktype =
3698 ((type_T **)stack->ga_data)[stack->ga_len - 1];
3699
3700 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3701 if (!has_type)
3702 {
3703 if (stacktype->tt_type == VAR_VOID)
3704 {
3705 emsg(_("E1031: Cannot use void value"));
3706 goto theend;
3707 }
3708 else
3709 lvar->lv_type = stacktype;
3710 }
3711 else
3712 if (check_type(lvar->lv_type, stacktype, TRUE) == FAIL)
3713 goto theend;
3714 }
3715 }
3716 else if (cmdidx == CMD_const)
3717 {
3718 emsg(_("E1021: const requires a value"));
3719 goto theend;
3720 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003721 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003722 {
3723 emsg(_("E1022: type or initialization required"));
3724 goto theend;
3725 }
3726 else
3727 {
3728 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003729 if (ga_grow(instr, 1) == FAIL)
3730 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01003731 switch (type->tt_type)
3732 {
3733 case VAR_BOOL:
3734 generate_PUSHBOOL(cctx, VVAL_FALSE);
3735 break;
3736 case VAR_SPECIAL:
3737 generate_PUSHSPEC(cctx, VVAL_NONE);
3738 break;
3739 case VAR_FLOAT:
3740#ifdef FEAT_FLOAT
3741 generate_PUSHF(cctx, 0.0);
3742#endif
3743 break;
3744 case VAR_STRING:
3745 generate_PUSHS(cctx, NULL);
3746 break;
3747 case VAR_BLOB:
3748 generate_PUSHBLOB(cctx, NULL);
3749 break;
3750 case VAR_FUNC:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003751 generate_PUSHFUNC(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01003752 break;
3753 case VAR_PARTIAL:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01003754 generate_PUSHPARTIAL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01003755 break;
3756 case VAR_LIST:
3757 generate_NEWLIST(cctx, 0);
3758 break;
3759 case VAR_DICT:
3760 generate_NEWDICT(cctx, 0);
3761 break;
3762 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003763 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01003764 break;
3765 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003766 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01003767 break;
3768 case VAR_NUMBER:
3769 case VAR_UNKNOWN:
3770 case VAR_VOID:
3771 generate_PUSHNR(cctx, 0);
3772 break;
3773 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003774 }
3775
3776 if (oplen > 0 && *op != '=')
3777 {
3778 type_T *expected = &t_number;
3779 garray_T *stack = &cctx->ctx_type_stack;
3780 type_T *stacktype;
3781
3782 // TODO: if type is known use float or any operation
3783
3784 if (*op == '.')
3785 expected = &t_string;
3786 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3787 if (need_type(stacktype, expected, -1, cctx) == FAIL)
3788 goto theend;
3789
3790 if (*op == '.')
3791 generate_instr_drop(cctx, ISN_CONCAT, 1);
3792 else
3793 {
3794 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
3795
3796 if (isn == NULL)
3797 goto theend;
3798 switch (*op)
3799 {
3800 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
3801 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
3802 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
3803 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
3804 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
3805 }
3806 }
3807 }
3808
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003809 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003810 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003811 case dest_option:
3812 generate_STOREOPT(cctx, name + 1, opt_flags);
3813 break;
3814 case dest_global:
3815 // include g: with the name, easier to execute that way
3816 generate_STORE(cctx, ISN_STOREG, 0, name);
3817 break;
3818 case dest_env:
3819 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
3820 break;
3821 case dest_reg:
3822 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
3823 break;
3824 case dest_vimvar:
3825 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
3826 break;
3827 case dest_script:
3828 {
3829 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
3830 imported_T *import = NULL;
3831 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003832
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003833 if (name[1] != ':')
3834 {
3835 import = find_imported(name, 0, cctx);
3836 if (import != NULL)
3837 sid = import->imp_sid;
3838 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003839
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003840 idx = get_script_item_idx(sid, rawname, TRUE);
3841 // TODO: specific type
3842 if (idx < 0)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01003843 generate_OLDSCRIPT(cctx, ISN_STORES, name, sid, &t_any);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003844 else
3845 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
3846 sid, idx, &t_any);
3847 }
3848 break;
3849 case dest_local:
3850 {
3851 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003852
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003853 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
3854 // into ISN_STORENR
3855 if (instr->ga_len == instr_count + 1
3856 && isn->isn_type == ISN_PUSHNR)
3857 {
3858 varnumber_T val = isn->isn_arg.number;
3859 garray_T *stack = &cctx->ctx_type_stack;
3860
3861 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01003862 isn->isn_arg.storenr.stnr_idx = idx;
3863 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003864 if (stack->ga_len > 0)
3865 --stack->ga_len;
3866 }
3867 else
3868 generate_STORE(cctx, ISN_STORE, idx, NULL);
3869 }
3870 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003871 }
3872 ret = p;
3873
3874theend:
3875 vim_free(name);
3876 return ret;
3877}
3878
3879/*
3880 * Compile an :import command.
3881 */
3882 static char_u *
3883compile_import(char_u *arg, cctx_T *cctx)
3884{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01003885 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003886}
3887
3888/*
3889 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
3890 */
3891 static int
3892compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
3893{
3894 garray_T *instr = &cctx->ctx_instr;
3895 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
3896
3897 if (endlabel == NULL)
3898 return FAIL;
3899 endlabel->el_next = *el;
3900 *el = endlabel;
3901 endlabel->el_end_label = instr->ga_len;
3902
3903 generate_JUMP(cctx, when, 0);
3904 return OK;
3905}
3906
3907 static void
3908compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
3909{
3910 garray_T *instr = &cctx->ctx_instr;
3911
3912 while (*el != NULL)
3913 {
3914 endlabel_T *cur = (*el);
3915 isn_T *isn;
3916
3917 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
3918 isn->isn_arg.jump.jump_where = instr->ga_len;
3919 *el = cur->el_next;
3920 vim_free(cur);
3921 }
3922}
3923
3924/*
3925 * Create a new scope and set up the generic items.
3926 */
3927 static scope_T *
3928new_scope(cctx_T *cctx, scopetype_T type)
3929{
3930 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
3931
3932 if (scope == NULL)
3933 return NULL;
3934 scope->se_outer = cctx->ctx_scope;
3935 cctx->ctx_scope = scope;
3936 scope->se_type = type;
3937 scope->se_local_count = cctx->ctx_locals.ga_len;
3938 return scope;
3939}
3940
3941/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003942 * Evaluate an expression that is a constant:
3943 * has(arg)
3944 *
3945 * Also handle:
3946 * ! in front logical NOT
3947 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003948 * Return FAIL if the expression is not a constant.
3949 */
3950 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003951evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003952{
3953 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003954 char_u *start_leader, *end_leader;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003955
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003956 /*
3957 * Skip '!' characters. They are handled later.
3958 */
3959 start_leader = *arg;
3960 while (**arg == '!')
3961 *arg = skipwhite(*arg + 1);
3962 end_leader = *arg;
3963
3964 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01003965 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01003966 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01003967 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
3968 {
3969 tv->v_type = VAR_SPECIAL;
3970 tv->vval.v_number = VVAL_TRUE;
3971 *arg += 4;
3972 return OK;
3973 }
3974 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
3975 {
3976 tv->v_type = VAR_SPECIAL;
3977 tv->vval.v_number = VVAL_FALSE;
3978 *arg += 5;
3979 return OK;
3980 }
3981
Bram Moolenaara259d8d2020-01-31 20:10:50 +01003982 if (STRNCMP("has(", *arg, 4) != 0)
3983 return FAIL;
3984 *arg = skipwhite(*arg + 4);
3985
3986 if (**arg == '"')
3987 {
3988 if (get_string_tv(arg, tv, TRUE) == FAIL)
3989 return FAIL;
3990 }
3991 else if (**arg == '\'')
3992 {
3993 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
3994 return FAIL;
3995 }
3996 else
3997 return FAIL;
3998
3999 *arg = skipwhite(*arg);
4000 if (**arg != ')')
4001 return FAIL;
4002 *arg = skipwhite(*arg + 1);
4003
4004 argvars[0] = *tv;
4005 argvars[1].v_type = VAR_UNKNOWN;
4006 tv->v_type = VAR_NUMBER;
4007 tv->vval.v_number = 0;
4008 f_has(argvars, tv);
4009 clear_tv(&argvars[0]);
4010
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004011 while (start_leader < end_leader)
4012 {
4013 if (*start_leader == '!')
4014 tv->vval.v_number = !tv->vval.v_number;
4015 ++start_leader;
4016 }
4017
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004018 return OK;
4019}
4020
Bram Moolenaar080457c2020-03-03 21:53:32 +01004021 static int
4022evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4023{
4024 exptype_T type = EXPR_UNKNOWN;
4025 char_u *p;
4026 int len = 2;
4027 int type_is = FALSE;
4028
4029 // get the first variable
4030 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4031 return FAIL;
4032
4033 p = skipwhite(*arg);
4034 type = get_compare_type(p, &len, &type_is);
4035
4036 /*
4037 * If there is a comparative operator, use it.
4038 */
4039 if (type != EXPR_UNKNOWN)
4040 {
4041 // TODO
4042 return FAIL;
4043 }
4044
4045 return OK;
4046}
4047
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004048static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4049
4050/*
4051 * Compile constant || or &&.
4052 */
4053 static int
4054evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4055{
4056 char_u *p = skipwhite(*arg);
4057 int opchar = *op;
4058
4059 if (p[0] == opchar && p[1] == opchar)
4060 {
4061 int val = tv2bool(tv);
4062
4063 /*
4064 * Repeat until there is no following "||" or "&&"
4065 */
4066 while (p[0] == opchar && p[1] == opchar)
4067 {
4068 typval_T tv2;
4069
4070 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4071 return FAIL;
4072
4073 // eval the next expression
4074 *arg = skipwhite(p + 2);
4075 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004076 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004077 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004078 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004079 {
4080 clear_tv(&tv2);
4081 return FAIL;
4082 }
4083 if ((opchar == '&') == val)
4084 {
4085 // false || tv2 or true && tv2: use tv2
4086 clear_tv(tv);
4087 *tv = tv2;
4088 val = tv2bool(tv);
4089 }
4090 else
4091 clear_tv(&tv2);
4092 p = skipwhite(*arg);
4093 }
4094 }
4095
4096 return OK;
4097}
4098
4099/*
4100 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4101 * Return FAIL if the expression is not a constant.
4102 */
4103 static int
4104evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4105{
4106 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004107 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004108 return FAIL;
4109
4110 // || and && work almost the same
4111 return evaluate_const_and_or(arg, cctx, "&&", tv);
4112}
4113
4114/*
4115 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4116 * Return FAIL if the expression is not a constant.
4117 */
4118 static int
4119evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4120{
4121 // evaluate the first expression
4122 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4123 return FAIL;
4124
4125 // || and && work almost the same
4126 return evaluate_const_and_or(arg, cctx, "||", tv);
4127}
4128
4129/*
4130 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4131 * E.g. for "has('feature')".
4132 * This does not produce error messages. "tv" should be cleared afterwards.
4133 * Return FAIL if the expression is not a constant.
4134 */
4135 static int
4136evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4137{
4138 char_u *p;
4139
4140 // evaluate the first expression
4141 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4142 return FAIL;
4143
4144 p = skipwhite(*arg);
4145 if (*p == '?')
4146 {
4147 int val = tv2bool(tv);
4148 typval_T tv2;
4149
4150 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4151 return FAIL;
4152
4153 // evaluate the second expression; any type is accepted
4154 clear_tv(tv);
4155 *arg = skipwhite(p + 1);
4156 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
4157 return FAIL;
4158
4159 // Check for the ":".
4160 p = skipwhite(*arg);
4161 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4162 return FAIL;
4163
4164 // evaluate the third expression
4165 *arg = skipwhite(p + 1);
4166 tv2.v_type = VAR_UNKNOWN;
4167 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
4168 {
4169 clear_tv(&tv2);
4170 return FAIL;
4171 }
4172 if (val)
4173 {
4174 // use the expr after "?"
4175 clear_tv(&tv2);
4176 }
4177 else
4178 {
4179 // use the expr after ":"
4180 clear_tv(tv);
4181 *tv = tv2;
4182 }
4183 }
4184 return OK;
4185}
4186
4187/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004188 * compile "if expr"
4189 *
4190 * "if expr" Produces instructions:
4191 * EVAL expr Push result of "expr"
4192 * JUMP_IF_FALSE end
4193 * ... body ...
4194 * end:
4195 *
4196 * "if expr | else" Produces instructions:
4197 * EVAL expr Push result of "expr"
4198 * JUMP_IF_FALSE else
4199 * ... body ...
4200 * JUMP_ALWAYS end
4201 * else:
4202 * ... body ...
4203 * end:
4204 *
4205 * "if expr1 | elseif expr2 | else" Produces instructions:
4206 * EVAL expr Push result of "expr"
4207 * JUMP_IF_FALSE elseif
4208 * ... body ...
4209 * JUMP_ALWAYS end
4210 * elseif:
4211 * EVAL expr Push result of "expr"
4212 * JUMP_IF_FALSE else
4213 * ... body ...
4214 * JUMP_ALWAYS end
4215 * else:
4216 * ... body ...
4217 * end:
4218 */
4219 static char_u *
4220compile_if(char_u *arg, cctx_T *cctx)
4221{
4222 char_u *p = arg;
4223 garray_T *instr = &cctx->ctx_instr;
4224 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004225 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004226
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004227 // compile "expr"; if we know it evaluates to FALSE skip the block
4228 tv.v_type = VAR_UNKNOWN;
4229 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4230 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4231 else
4232 cctx->ctx_skip = MAYBE;
4233 clear_tv(&tv);
4234 if (cctx->ctx_skip == MAYBE)
4235 {
4236 p = arg;
4237 if (compile_expr1(&p, cctx) == FAIL)
4238 return NULL;
4239 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004240
4241 scope = new_scope(cctx, IF_SCOPE);
4242 if (scope == NULL)
4243 return NULL;
4244
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004245 if (cctx->ctx_skip == MAYBE)
4246 {
4247 // "where" is set when ":elseif", "else" or ":endif" is found
4248 scope->se_u.se_if.is_if_label = instr->ga_len;
4249 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4250 }
4251 else
4252 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004253
4254 return p;
4255}
4256
4257 static char_u *
4258compile_elseif(char_u *arg, cctx_T *cctx)
4259{
4260 char_u *p = arg;
4261 garray_T *instr = &cctx->ctx_instr;
4262 isn_T *isn;
4263 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004264 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004265
4266 if (scope == NULL || scope->se_type != IF_SCOPE)
4267 {
4268 emsg(_(e_elseif_without_if));
4269 return NULL;
4270 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004271 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004272
Bram Moolenaar158906c2020-02-06 20:39:45 +01004273 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004274 {
4275 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004276 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004277 return NULL;
4278 // previous "if" or "elseif" jumps here
4279 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4280 isn->isn_arg.jump.jump_where = instr->ga_len;
4281 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004282
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004283 // compile "expr"; if we know it evaluates to FALSE skip the block
4284 tv.v_type = VAR_UNKNOWN;
4285 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4286 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4287 else
4288 cctx->ctx_skip = MAYBE;
4289 clear_tv(&tv);
4290 if (cctx->ctx_skip == MAYBE)
4291 {
4292 p = arg;
4293 if (compile_expr1(&p, cctx) == FAIL)
4294 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004295
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004296 // "where" is set when ":elseif", "else" or ":endif" is found
4297 scope->se_u.se_if.is_if_label = instr->ga_len;
4298 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4299 }
4300 else
4301 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004302
4303 return p;
4304}
4305
4306 static char_u *
4307compile_else(char_u *arg, cctx_T *cctx)
4308{
4309 char_u *p = arg;
4310 garray_T *instr = &cctx->ctx_instr;
4311 isn_T *isn;
4312 scope_T *scope = cctx->ctx_scope;
4313
4314 if (scope == NULL || scope->se_type != IF_SCOPE)
4315 {
4316 emsg(_(e_else_without_if));
4317 return NULL;
4318 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004319 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004320
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004321 // jump from previous block to the end, unless the else block is empty
4322 if (cctx->ctx_skip == MAYBE)
4323 {
4324 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004325 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004326 return NULL;
4327 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004328
Bram Moolenaar158906c2020-02-06 20:39:45 +01004329 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004330 {
4331 if (scope->se_u.se_if.is_if_label >= 0)
4332 {
4333 // previous "if" or "elseif" jumps here
4334 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4335 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01004336 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004337 }
4338 }
4339
4340 if (cctx->ctx_skip != MAYBE)
4341 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004342
4343 return p;
4344}
4345
4346 static char_u *
4347compile_endif(char_u *arg, cctx_T *cctx)
4348{
4349 scope_T *scope = cctx->ctx_scope;
4350 ifscope_T *ifscope;
4351 garray_T *instr = &cctx->ctx_instr;
4352 isn_T *isn;
4353
4354 if (scope == NULL || scope->se_type != IF_SCOPE)
4355 {
4356 emsg(_(e_endif_without_if));
4357 return NULL;
4358 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004359 ifscope = &scope->se_u.se_if;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004360 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004361 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004362
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004363 if (scope->se_u.se_if.is_if_label >= 0)
4364 {
4365 // previous "if" or "elseif" jumps here
4366 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4367 isn->isn_arg.jump.jump_where = instr->ga_len;
4368 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004369 // Fill in the "end" label in jumps at the end of the blocks.
4370 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004371 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004372
4373 vim_free(scope);
4374 return arg;
4375}
4376
4377/*
4378 * compile "for var in expr"
4379 *
4380 * Produces instructions:
4381 * PUSHNR -1
4382 * STORE loop-idx Set index to -1
4383 * EVAL expr Push result of "expr"
4384 * top: FOR loop-idx, end Increment index, use list on bottom of stack
4385 * - if beyond end, jump to "end"
4386 * - otherwise get item from list and push it
4387 * STORE var Store item in "var"
4388 * ... body ...
4389 * JUMP top Jump back to repeat
4390 * end: DROP Drop the result of "expr"
4391 *
4392 */
4393 static char_u *
4394compile_for(char_u *arg, cctx_T *cctx)
4395{
4396 char_u *p;
4397 size_t varlen;
4398 garray_T *instr = &cctx->ctx_instr;
4399 garray_T *stack = &cctx->ctx_type_stack;
4400 scope_T *scope;
4401 int loop_idx; // index of loop iteration variable
4402 int var_idx; // index of "var"
4403 type_T *vartype;
4404
4405 // TODO: list of variables: "for [key, value] in dict"
4406 // parse "var"
4407 for (p = arg; eval_isnamec1(*p); ++p)
4408 ;
4409 varlen = p - arg;
4410 var_idx = lookup_local(arg, varlen, cctx);
4411 if (var_idx >= 0)
4412 {
4413 semsg(_("E1023: variable already defined: %s"), arg);
4414 return NULL;
4415 }
4416
4417 // consume "in"
4418 p = skipwhite(p);
4419 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
4420 {
4421 emsg(_(e_missing_in));
4422 return NULL;
4423 }
4424 p = skipwhite(p + 2);
4425
4426
4427 scope = new_scope(cctx, FOR_SCOPE);
4428 if (scope == NULL)
4429 return NULL;
4430
4431 // Reserve a variable to store the loop iteration counter.
4432 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
4433 if (loop_idx < 0)
4434 return NULL;
4435
4436 // Reserve a variable to store "var"
4437 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
4438 if (var_idx < 0)
4439 return NULL;
4440
4441 generate_STORENR(cctx, loop_idx, -1);
4442
4443 // compile "expr", it remains on the stack until "endfor"
4444 arg = p;
4445 if (compile_expr1(&arg, cctx) == FAIL)
4446 return NULL;
4447
4448 // now we know the type of "var"
4449 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4450 if (vartype->tt_type != VAR_LIST)
4451 {
4452 emsg(_("E1024: need a List to iterate over"));
4453 return NULL;
4454 }
4455 if (vartype->tt_member->tt_type != VAR_UNKNOWN)
4456 {
4457 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
4458
4459 lvar->lv_type = vartype->tt_member;
4460 }
4461
4462 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004463 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004464
4465 generate_FOR(cctx, loop_idx);
4466 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
4467
4468 return arg;
4469}
4470
4471/*
4472 * compile "endfor"
4473 */
4474 static char_u *
4475compile_endfor(char_u *arg, cctx_T *cctx)
4476{
4477 garray_T *instr = &cctx->ctx_instr;
4478 scope_T *scope = cctx->ctx_scope;
4479 forscope_T *forscope;
4480 isn_T *isn;
4481
4482 if (scope == NULL || scope->se_type != FOR_SCOPE)
4483 {
4484 emsg(_(e_for));
4485 return NULL;
4486 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004487 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004488 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004489 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004490
4491 // At end of ":for" scope jump back to the FOR instruction.
4492 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
4493
4494 // Fill in the "end" label in the FOR statement so it can jump here
4495 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
4496 isn->isn_arg.forloop.for_end = instr->ga_len;
4497
4498 // Fill in the "end" label any BREAK statements
4499 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
4500
4501 // Below the ":for" scope drop the "expr" list from the stack.
4502 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
4503 return NULL;
4504
4505 vim_free(scope);
4506
4507 return arg;
4508}
4509
4510/*
4511 * compile "while expr"
4512 *
4513 * Produces instructions:
4514 * top: EVAL expr Push result of "expr"
4515 * JUMP_IF_FALSE end jump if false
4516 * ... body ...
4517 * JUMP top Jump back to repeat
4518 * end:
4519 *
4520 */
4521 static char_u *
4522compile_while(char_u *arg, cctx_T *cctx)
4523{
4524 char_u *p = arg;
4525 garray_T *instr = &cctx->ctx_instr;
4526 scope_T *scope;
4527
4528 scope = new_scope(cctx, WHILE_SCOPE);
4529 if (scope == NULL)
4530 return NULL;
4531
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004532 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004533
4534 // compile "expr"
4535 if (compile_expr1(&p, cctx) == FAIL)
4536 return NULL;
4537
4538 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004539 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004540 JUMP_IF_FALSE, cctx) == FAIL)
4541 return FAIL;
4542
4543 return p;
4544}
4545
4546/*
4547 * compile "endwhile"
4548 */
4549 static char_u *
4550compile_endwhile(char_u *arg, cctx_T *cctx)
4551{
4552 scope_T *scope = cctx->ctx_scope;
4553
4554 if (scope == NULL || scope->se_type != WHILE_SCOPE)
4555 {
4556 emsg(_(e_while));
4557 return NULL;
4558 }
4559 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004560 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004561
4562 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004563 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004564
4565 // Fill in the "end" label in the WHILE statement so it can jump here.
4566 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004567 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004568
4569 vim_free(scope);
4570
4571 return arg;
4572}
4573
4574/*
4575 * compile "continue"
4576 */
4577 static char_u *
4578compile_continue(char_u *arg, cctx_T *cctx)
4579{
4580 scope_T *scope = cctx->ctx_scope;
4581
4582 for (;;)
4583 {
4584 if (scope == NULL)
4585 {
4586 emsg(_(e_continue));
4587 return NULL;
4588 }
4589 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
4590 break;
4591 scope = scope->se_outer;
4592 }
4593
4594 // Jump back to the FOR or WHILE instruction.
4595 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004596 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
4597 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004598 return arg;
4599}
4600
4601/*
4602 * compile "break"
4603 */
4604 static char_u *
4605compile_break(char_u *arg, cctx_T *cctx)
4606{
4607 scope_T *scope = cctx->ctx_scope;
4608 endlabel_T **el;
4609
4610 for (;;)
4611 {
4612 if (scope == NULL)
4613 {
4614 emsg(_(e_break));
4615 return NULL;
4616 }
4617 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
4618 break;
4619 scope = scope->se_outer;
4620 }
4621
4622 // Jump to the end of the FOR or WHILE loop.
4623 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004624 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004625 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004626 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004627 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
4628 return FAIL;
4629
4630 return arg;
4631}
4632
4633/*
4634 * compile "{" start of block
4635 */
4636 static char_u *
4637compile_block(char_u *arg, cctx_T *cctx)
4638{
4639 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
4640 return NULL;
4641 return skipwhite(arg + 1);
4642}
4643
4644/*
4645 * compile end of block: drop one scope
4646 */
4647 static void
4648compile_endblock(cctx_T *cctx)
4649{
4650 scope_T *scope = cctx->ctx_scope;
4651
4652 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004653 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004654 vim_free(scope);
4655}
4656
4657/*
4658 * compile "try"
4659 * Creates a new scope for the try-endtry, pointing to the first catch and
4660 * finally.
4661 * Creates another scope for the "try" block itself.
4662 * TRY instruction sets up exception handling at runtime.
4663 *
4664 * "try"
4665 * TRY -> catch1, -> finally push trystack entry
4666 * ... try block
4667 * "throw {exception}"
4668 * EVAL {exception}
4669 * THROW create exception
4670 * ... try block
4671 * " catch {expr}"
4672 * JUMP -> finally
4673 * catch1: PUSH exeception
4674 * EVAL {expr}
4675 * MATCH
4676 * JUMP nomatch -> catch2
4677 * CATCH remove exception
4678 * ... catch block
4679 * " catch"
4680 * JUMP -> finally
4681 * catch2: CATCH remove exception
4682 * ... catch block
4683 * " finally"
4684 * finally:
4685 * ... finally block
4686 * " endtry"
4687 * ENDTRY pop trystack entry, may rethrow
4688 */
4689 static char_u *
4690compile_try(char_u *arg, cctx_T *cctx)
4691{
4692 garray_T *instr = &cctx->ctx_instr;
4693 scope_T *try_scope;
4694 scope_T *scope;
4695
4696 // scope that holds the jumps that go to catch/finally/endtry
4697 try_scope = new_scope(cctx, TRY_SCOPE);
4698 if (try_scope == NULL)
4699 return NULL;
4700
4701 // "catch" is set when the first ":catch" is found.
4702 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004703 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004704 if (generate_instr(cctx, ISN_TRY) == NULL)
4705 return NULL;
4706
4707 // scope for the try block itself
4708 scope = new_scope(cctx, BLOCK_SCOPE);
4709 if (scope == NULL)
4710 return NULL;
4711
4712 return arg;
4713}
4714
4715/*
4716 * compile "catch {expr}"
4717 */
4718 static char_u *
4719compile_catch(char_u *arg, cctx_T *cctx UNUSED)
4720{
4721 scope_T *scope = cctx->ctx_scope;
4722 garray_T *instr = &cctx->ctx_instr;
4723 char_u *p;
4724 isn_T *isn;
4725
4726 // end block scope from :try or :catch
4727 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
4728 compile_endblock(cctx);
4729 scope = cctx->ctx_scope;
4730
4731 // Error if not in a :try scope
4732 if (scope == NULL || scope->se_type != TRY_SCOPE)
4733 {
4734 emsg(_(e_catch));
4735 return NULL;
4736 }
4737
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004738 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004739 {
4740 emsg(_("E1033: catch unreachable after catch-all"));
4741 return NULL;
4742 }
4743
4744 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004745 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004746 JUMP_ALWAYS, cctx) == FAIL)
4747 return NULL;
4748
4749 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004750 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004751 if (isn->isn_arg.try.try_catch == 0)
4752 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004753 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004754 {
4755 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004756 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004757 isn->isn_arg.jump.jump_where = instr->ga_len;
4758 }
4759
4760 p = skipwhite(arg);
4761 if (ends_excmd(*p))
4762 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004763 scope->se_u.se_try.ts_caught_all = TRUE;
4764 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004765 }
4766 else
4767 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004768 char_u *end;
4769 char_u *pat;
4770 char_u *tofree = NULL;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01004771 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004772
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004773 // Push v:exception, push {expr} and MATCH
4774 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
4775
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004776 end = skip_regexp(p + 1, *p, TRUE, &tofree);
4777 if (*end != *p)
4778 {
4779 semsg(_("E1067: Separator mismatch: %s"), p);
4780 vim_free(tofree);
4781 return FAIL;
4782 }
4783 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01004784 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004785 else
Bram Moolenaar3dd64602020-02-13 20:31:28 +01004786 len = (int)(end - (tofree + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01004787 pat = vim_strnsave(p + 1, len);
4788 vim_free(tofree);
4789 p += len + 2;
4790 if (pat == NULL)
4791 return FAIL;
4792 if (generate_PUSHS(cctx, pat) == FAIL)
4793 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004794
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004795 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
4796 return NULL;
4797
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004798 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004799 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
4800 return NULL;
4801 }
4802
4803 if (generate_instr(cctx, ISN_CATCH) == NULL)
4804 return NULL;
4805
4806 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
4807 return NULL;
4808 return p;
4809}
4810
4811 static char_u *
4812compile_finally(char_u *arg, cctx_T *cctx)
4813{
4814 scope_T *scope = cctx->ctx_scope;
4815 garray_T *instr = &cctx->ctx_instr;
4816 isn_T *isn;
4817
4818 // end block scope from :try or :catch
4819 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
4820 compile_endblock(cctx);
4821 scope = cctx->ctx_scope;
4822
4823 // Error if not in a :try scope
4824 if (scope == NULL || scope->se_type != TRY_SCOPE)
4825 {
4826 emsg(_(e_finally));
4827 return NULL;
4828 }
4829
4830 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004831 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004832 if (isn->isn_arg.try.try_finally != 0)
4833 {
4834 emsg(_(e_finally_dup));
4835 return NULL;
4836 }
4837
4838 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004839 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004840
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004841 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004842 {
4843 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004844 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004845 isn->isn_arg.jump.jump_where = instr->ga_len;
4846 }
4847
4848 isn->isn_arg.try.try_finally = instr->ga_len;
4849 // TODO: set index in ts_finally_label jumps
4850
4851 return arg;
4852}
4853
4854 static char_u *
4855compile_endtry(char_u *arg, cctx_T *cctx)
4856{
4857 scope_T *scope = cctx->ctx_scope;
4858 garray_T *instr = &cctx->ctx_instr;
4859 isn_T *isn;
4860
4861 // end block scope from :catch or :finally
4862 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
4863 compile_endblock(cctx);
4864 scope = cctx->ctx_scope;
4865
4866 // Error if not in a :try scope
4867 if (scope == NULL || scope->se_type != TRY_SCOPE)
4868 {
4869 if (scope == NULL)
4870 emsg(_(e_no_endtry));
4871 else if (scope->se_type == WHILE_SCOPE)
4872 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01004873 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004874 emsg(_(e_endfor));
4875 else
4876 emsg(_(e_endif));
4877 return NULL;
4878 }
4879
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004880 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004881 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
4882 {
4883 emsg(_("E1032: missing :catch or :finally"));
4884 return NULL;
4885 }
4886
4887 // Fill in the "end" label in jumps at the end of the blocks, if not done
4888 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004889 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004890
4891 // End :catch or :finally scope: set value in ISN_TRY instruction
4892 if (isn->isn_arg.try.try_finally == 0)
4893 isn->isn_arg.try.try_finally = instr->ga_len;
4894 compile_endblock(cctx);
4895
4896 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
4897 return NULL;
4898 return arg;
4899}
4900
4901/*
4902 * compile "throw {expr}"
4903 */
4904 static char_u *
4905compile_throw(char_u *arg, cctx_T *cctx UNUSED)
4906{
4907 char_u *p = skipwhite(arg);
4908
4909 if (ends_excmd(*p))
4910 {
4911 emsg(_(e_argreq));
4912 return NULL;
4913 }
4914 if (compile_expr1(&p, cctx) == FAIL)
4915 return NULL;
4916 if (may_generate_2STRING(-1, cctx) == FAIL)
4917 return NULL;
4918 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
4919 return NULL;
4920
4921 return p;
4922}
4923
4924/*
4925 * compile "echo expr"
4926 */
4927 static char_u *
4928compile_echo(char_u *arg, int with_white, cctx_T *cctx)
4929{
4930 char_u *p = arg;
4931 int count = 0;
4932
Bram Moolenaarad39c092020-02-26 18:23:43 +01004933 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004934 {
4935 if (compile_expr1(&p, cctx) == FAIL)
4936 return NULL;
4937 ++count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01004938 p = skipwhite(p);
4939 if (ends_excmd(*p))
4940 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004941 }
4942
4943 generate_ECHO(cctx, with_white, count);
Bram Moolenaarad39c092020-02-26 18:23:43 +01004944 return p;
4945}
4946
4947/*
4948 * compile "execute expr"
4949 */
4950 static char_u *
4951compile_execute(char_u *arg, cctx_T *cctx)
4952{
4953 char_u *p = arg;
4954 int count = 0;
4955
4956 for (;;)
4957 {
4958 if (compile_expr1(&p, cctx) == FAIL)
4959 return NULL;
4960 ++count;
4961 p = skipwhite(p);
4962 if (ends_excmd(*p))
4963 break;
4964 }
4965
4966 generate_EXECUTE(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004967
4968 return p;
4969}
4970
4971/*
4972 * After ex_function() has collected all the function lines: parse and compile
4973 * the lines into instructions.
4974 * Adds the function to "def_functions".
4975 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
4976 * return statement (used for lambda).
4977 */
4978 void
4979compile_def_function(ufunc_T *ufunc, int set_return_type)
4980{
4981 dfunc_T *dfunc;
4982 char_u *line = NULL;
4983 char_u *p;
4984 exarg_T ea;
4985 char *errormsg = NULL; // error message
4986 int had_return = FALSE;
4987 cctx_T cctx;
4988 garray_T *instr;
4989 int called_emsg_before = called_emsg;
4990 int ret = FAIL;
4991 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004992 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004993
4994 if (ufunc->uf_dfunc_idx >= 0)
4995 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01004996 // Redefining a function that was compiled before.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004997 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004998
4999 // Free old instructions.
5000 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005001 }
5002 else
5003 {
5004 // Add the function to "def_functions".
5005 if (ga_grow(&def_functions, 1) == FAIL)
5006 return;
5007 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
5008 vim_memset(dfunc, 0, sizeof(dfunc_T));
5009 dfunc->df_idx = def_functions.ga_len;
5010 ufunc->uf_dfunc_idx = dfunc->df_idx;
5011 dfunc->df_ufunc = ufunc;
5012 ++def_functions.ga_len;
5013 }
5014
5015 vim_memset(&cctx, 0, sizeof(cctx));
5016 cctx.ctx_ufunc = ufunc;
5017 cctx.ctx_lnum = -1;
5018 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5019 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5020 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5021 cctx.ctx_type_list = &ufunc->uf_type_list;
5022 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5023 instr = &cctx.ctx_instr;
5024
5025 // Most modern script version.
5026 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5027
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005028 if (ufunc->uf_def_args.ga_len > 0)
5029 {
5030 int count = ufunc->uf_def_args.ga_len;
5031 int i;
5032 char_u *arg;
5033 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5034
5035 // Produce instructions for the default values of optional arguments.
5036 // Store the instruction index in uf_def_arg_idx[] so that we know
5037 // where to start when the function is called, depending on the number
5038 // of arguments.
5039 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5040 if (ufunc->uf_def_arg_idx == NULL)
5041 goto erret;
5042 for (i = 0; i < count; ++i)
5043 {
5044 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5045 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
5046 if (compile_expr1(&arg, &cctx) == FAIL
5047 || generate_STORE(&cctx, ISN_STORE,
5048 i - count - off, NULL) == FAIL)
5049 goto erret;
5050 }
5051
5052 // If a varargs is following, push an empty list.
5053 if (ufunc->uf_va_name != NULL)
5054 {
5055 if (generate_NEWLIST(&cctx, 0) == FAIL
5056 || generate_STORE(&cctx, ISN_STORE, -off, NULL) == FAIL)
5057 goto erret;
5058 }
5059
5060 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5061 }
5062
5063 /*
5064 * Loop over all the lines of the function and generate instructions.
5065 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005066 for (;;)
5067 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005068 int is_ex_command;
5069
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005070 if (line != NULL && *line == '|')
5071 // the line continues after a '|'
5072 ++line;
5073 else if (line != NULL && *line != NUL)
5074 {
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005075 if (emsg_before == called_emsg)
5076 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005077 goto erret;
5078 }
5079 else
5080 {
5081 do
5082 {
5083 ++cctx.ctx_lnum;
5084 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
5085 break;
5086 line = ((char_u **)ufunc->uf_lines.ga_data)[cctx.ctx_lnum];
5087 } while (line == NULL);
5088 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
5089 break;
5090 SOURCING_LNUM = ufunc->uf_script_ctx.sc_lnum + cctx.ctx_lnum + 1;
5091 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005092 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005093
5094 had_return = FALSE;
5095 vim_memset(&ea, 0, sizeof(ea));
5096 ea.cmdlinep = &line;
5097 ea.cmd = skipwhite(line);
5098
5099 // "}" ends a block scope
5100 if (*ea.cmd == '}')
5101 {
5102 scopetype_T stype = cctx.ctx_scope == NULL
5103 ? NO_SCOPE : cctx.ctx_scope->se_type;
5104
5105 if (stype == BLOCK_SCOPE)
5106 {
5107 compile_endblock(&cctx);
5108 line = ea.cmd;
5109 }
5110 else
5111 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005112 emsg(_("E1025: using } outside of a block scope"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005113 goto erret;
5114 }
5115 if (line != NULL)
5116 line = skipwhite(ea.cmd + 1);
5117 continue;
5118 }
5119
5120 // "{" starts a block scope
5121 if (*ea.cmd == '{')
5122 {
5123 line = compile_block(ea.cmd, &cctx);
5124 continue;
5125 }
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005126 is_ex_command = *ea.cmd == ':';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005127
5128 /*
5129 * COMMAND MODIFIERS
5130 */
5131 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
5132 {
5133 if (errormsg != NULL)
5134 goto erret;
5135 // empty line or comment
5136 line = (char_u *)"";
5137 continue;
5138 }
5139
5140 // Skip ":call" to get to the function name.
5141 if (checkforcmd(&ea.cmd, "call", 3))
5142 ea.cmd = skipwhite(ea.cmd);
5143
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005144 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005145 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005146 // Assuming the command starts with a variable or function name,
5147 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
5148 // val".
5149 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
5150 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005151 p = to_name_end(p, TRUE);
Bram Moolenaar0c6ceaf2020-02-22 18:36:32 +01005152 if ((p > ea.cmd && *p != NUL) || *p == '(')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005153 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005154 int oplen;
5155 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005156
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005157 oplen = assignment_len(skipwhite(p), &heredoc);
5158 if (oplen > 0)
5159 {
5160 // Recognize an assignment if we recognize the variable
5161 // name:
5162 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005163 // "local = expr" where "local" is a local var.
5164 // "script = expr" where "script" is a script-local var.
5165 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005166 // "&opt = expr"
5167 // "$ENV = expr"
5168 // "@r = expr"
5169 if (*ea.cmd == '&'
5170 || *ea.cmd == '$'
5171 || *ea.cmd == '@'
5172 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
5173 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
5174 || lookup_script(ea.cmd, p - ea.cmd) == OK
5175 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
5176 {
5177 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
5178 if (line == NULL)
5179 goto erret;
5180 continue;
5181 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005182 }
5183 }
5184 }
5185
5186 /*
5187 * COMMAND after range
5188 */
5189 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005190 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
5191 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005192
5193 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
5194 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005195 if (cctx.ctx_skip == TRUE)
5196 {
5197 line += STRLEN(line);
5198 continue;
5199 }
5200
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005201 // Expression or function call.
5202 if (ea.cmdidx == CMD_eval)
5203 {
5204 p = ea.cmd;
5205 if (compile_expr1(&p, &cctx) == FAIL)
5206 goto erret;
5207
5208 // drop the return value
5209 generate_instr_drop(&cctx, ISN_DROP, 1);
5210 line = p;
5211 continue;
5212 }
5213 if (ea.cmdidx == CMD_let)
5214 {
5215 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
5216 if (line == NULL)
5217 goto erret;
5218 continue;
5219 }
5220 iemsg("Command from find_ex_command() not handled");
5221 goto erret;
5222 }
5223
5224 p = skipwhite(p);
5225
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005226 if (cctx.ctx_skip == TRUE
5227 && ea.cmdidx != CMD_elseif
5228 && ea.cmdidx != CMD_else
5229 && ea.cmdidx != CMD_endif)
5230 {
5231 line += STRLEN(line);
5232 continue;
5233 }
5234
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005235 switch (ea.cmdidx)
5236 {
5237 case CMD_def:
5238 case CMD_function:
5239 // TODO: Nested function
5240 emsg("Nested function not implemented yet");
5241 goto erret;
5242
5243 case CMD_return:
5244 line = compile_return(p, set_return_type, &cctx);
5245 had_return = TRUE;
5246 break;
5247
5248 case CMD_let:
5249 case CMD_const:
5250 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
5251 break;
5252
5253 case CMD_import:
5254 line = compile_import(p, &cctx);
5255 break;
5256
5257 case CMD_if:
5258 line = compile_if(p, &cctx);
5259 break;
5260 case CMD_elseif:
5261 line = compile_elseif(p, &cctx);
5262 break;
5263 case CMD_else:
5264 line = compile_else(p, &cctx);
5265 break;
5266 case CMD_endif:
5267 line = compile_endif(p, &cctx);
5268 break;
5269
5270 case CMD_while:
5271 line = compile_while(p, &cctx);
5272 break;
5273 case CMD_endwhile:
5274 line = compile_endwhile(p, &cctx);
5275 break;
5276
5277 case CMD_for:
5278 line = compile_for(p, &cctx);
5279 break;
5280 case CMD_endfor:
5281 line = compile_endfor(p, &cctx);
5282 break;
5283 case CMD_continue:
5284 line = compile_continue(p, &cctx);
5285 break;
5286 case CMD_break:
5287 line = compile_break(p, &cctx);
5288 break;
5289
5290 case CMD_try:
5291 line = compile_try(p, &cctx);
5292 break;
5293 case CMD_catch:
5294 line = compile_catch(p, &cctx);
5295 break;
5296 case CMD_finally:
5297 line = compile_finally(p, &cctx);
5298 break;
5299 case CMD_endtry:
5300 line = compile_endtry(p, &cctx);
5301 break;
5302 case CMD_throw:
5303 line = compile_throw(p, &cctx);
5304 break;
5305
5306 case CMD_echo:
5307 line = compile_echo(p, TRUE, &cctx);
5308 break;
5309 case CMD_echon:
5310 line = compile_echo(p, FALSE, &cctx);
5311 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005312 case CMD_execute:
5313 line = compile_execute(p, &cctx);
5314 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005315
5316 default:
5317 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01005318 // TODO:
5319 // CMD_echomsg
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01005320 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005321 generate_EXEC(&cctx, line);
5322 line = (char_u *)"";
5323 break;
5324 }
5325 if (line == NULL)
5326 goto erret;
5327
5328 if (cctx.ctx_type_stack.ga_len < 0)
5329 {
5330 iemsg("Type stack underflow");
5331 goto erret;
5332 }
5333 }
5334
5335 if (cctx.ctx_scope != NULL)
5336 {
5337 if (cctx.ctx_scope->se_type == IF_SCOPE)
5338 emsg(_(e_endif));
5339 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
5340 emsg(_(e_endwhile));
5341 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
5342 emsg(_(e_endfor));
5343 else
5344 emsg(_("E1026: Missing }"));
5345 goto erret;
5346 }
5347
5348 if (!had_return)
5349 {
5350 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
5351 {
5352 emsg(_("E1027: Missing return statement"));
5353 goto erret;
5354 }
5355
5356 // Return zero if there is no return at the end.
5357 generate_PUSHNR(&cctx, 0);
5358 generate_instr(&cctx, ISN_RETURN);
5359 }
5360
Bram Moolenaar20431c92020-03-20 18:39:46 +01005361 dfunc->df_deleted = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005362 dfunc->df_instr = instr->ga_data;
5363 dfunc->df_instr_count = instr->ga_len;
5364 dfunc->df_varcount = cctx.ctx_max_local;
5365
5366 ret = OK;
5367
5368erret:
5369 if (ret == FAIL)
5370 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01005371 int idx;
5372
5373 for (idx = 0; idx < instr->ga_len; ++idx)
5374 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005375 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01005376
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005377 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005378 if (!dfunc->df_deleted)
5379 --def_functions.ga_len;
5380
5381 // Don't execute this function body.
5382 ga_clear_strings(&ufunc->uf_lines);
5383
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005384 if (errormsg != NULL)
5385 emsg(errormsg);
5386 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005387 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005388 }
5389
5390 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005391 free_imported(&cctx);
5392 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005393 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005394}
5395
5396/*
5397 * Delete an instruction, free what it contains.
5398 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01005399 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005400delete_instr(isn_T *isn)
5401{
5402 switch (isn->isn_type)
5403 {
5404 case ISN_EXEC:
5405 case ISN_LOADENV:
5406 case ISN_LOADG:
5407 case ISN_LOADOPT:
5408 case ISN_MEMBER:
5409 case ISN_PUSHEXC:
5410 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005411 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005412 case ISN_STOREG:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005413 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005414 vim_free(isn->isn_arg.string);
5415 break;
5416
5417 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005418 case ISN_STORES:
5419 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005420 break;
5421
5422 case ISN_STOREOPT:
5423 vim_free(isn->isn_arg.storeopt.so_name);
5424 break;
5425
5426 case ISN_PUSHBLOB: // push blob isn_arg.blob
5427 blob_unref(isn->isn_arg.blob);
5428 break;
5429
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005430 case ISN_PUSHPARTIAL:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01005431 partial_unref(isn->isn_arg.partial);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005432 break;
5433
5434 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005435#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005436 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005437#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005438 break;
5439
5440 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005441#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005442 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005443#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005444 break;
5445
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005446 case ISN_UCALL:
5447 vim_free(isn->isn_arg.ufunc.cuf_name);
5448 break;
5449
5450 case ISN_2BOOL:
5451 case ISN_2STRING:
5452 case ISN_ADDBLOB:
5453 case ISN_ADDLIST:
5454 case ISN_BCALL:
5455 case ISN_CATCH:
5456 case ISN_CHECKNR:
5457 case ISN_CHECKTYPE:
5458 case ISN_COMPAREANY:
5459 case ISN_COMPAREBLOB:
5460 case ISN_COMPAREBOOL:
5461 case ISN_COMPAREDICT:
5462 case ISN_COMPAREFLOAT:
5463 case ISN_COMPAREFUNC:
5464 case ISN_COMPARELIST:
5465 case ISN_COMPARENR:
5466 case ISN_COMPAREPARTIAL:
5467 case ISN_COMPARESPECIAL:
5468 case ISN_COMPARESTRING:
5469 case ISN_CONCAT:
5470 case ISN_DCALL:
5471 case ISN_DROP:
5472 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01005473 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005474 case ISN_ENDTRY:
5475 case ISN_FOR:
5476 case ISN_FUNCREF:
5477 case ISN_INDEX:
5478 case ISN_JUMP:
5479 case ISN_LOAD:
5480 case ISN_LOADSCRIPT:
5481 case ISN_LOADREG:
5482 case ISN_LOADV:
5483 case ISN_NEGATENR:
5484 case ISN_NEWDICT:
5485 case ISN_NEWLIST:
5486 case ISN_OPNR:
5487 case ISN_OPFLOAT:
5488 case ISN_OPANY:
5489 case ISN_PCALL:
5490 case ISN_PUSHF:
5491 case ISN_PUSHNR:
5492 case ISN_PUSHBOOL:
5493 case ISN_PUSHSPEC:
5494 case ISN_RETURN:
5495 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005496 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005497 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005498 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005499 case ISN_STORESCRIPT:
5500 case ISN_THROW:
5501 case ISN_TRY:
5502 // nothing allocated
5503 break;
5504 }
5505}
5506
5507/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01005508 * Free all instructions for "dfunc".
5509 */
5510 static void
5511delete_def_function_contents(dfunc_T *dfunc)
5512{
5513 int idx;
5514
5515 ga_clear(&dfunc->df_def_args_isn);
5516
5517 if (dfunc->df_instr != NULL)
5518 {
5519 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
5520 delete_instr(dfunc->df_instr + idx);
5521 VIM_CLEAR(dfunc->df_instr);
5522 }
5523
5524 dfunc->df_deleted = TRUE;
5525}
5526
5527/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005528 * When a user function is deleted, delete any associated def function.
5529 */
5530 void
5531delete_def_function(ufunc_T *ufunc)
5532{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005533 if (ufunc->uf_dfunc_idx >= 0)
5534 {
5535 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5536 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005537
Bram Moolenaar20431c92020-03-20 18:39:46 +01005538 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005539 }
5540}
5541
5542#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01005543/*
5544 * Free all functions defined with ":def".
5545 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005546 void
5547free_def_functions(void)
5548{
Bram Moolenaar20431c92020-03-20 18:39:46 +01005549 int idx;
5550
5551 for (idx = 0; idx < def_functions.ga_len; ++idx)
5552 {
5553 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
5554
5555 delete_def_function_contents(dfunc);
5556 }
5557
5558 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005559}
5560#endif
5561
5562
5563#endif // FEAT_EVAL