blob: b64f8efd58ec47585c090193d68f9fb46ea67a14 [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 *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200227get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100228{
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.
Bram Moolenaard77a8522020-04-03 21:59:57 +0200244 if (ga_grow(type_gap, 1) == FAIL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100245 return &t_any;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200246 type = ((type_T *)type_gap->ga_data) + type_gap->ga_len;
247 ++type_gap->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100248 type->tt_type = VAR_LIST;
249 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200250 type->tt_argcount = 0;
251 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100252 return type;
253}
254
255 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200256get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100257{
258 type_T *type;
259
260 // recognize commonly used types
261 if (member_type->tt_type == VAR_UNKNOWN)
262 return &t_dict_any;
Bram Moolenaar436472f2020-02-20 22:54:43 +0100263 if (member_type->tt_type == VAR_VOID)
264 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100265 if (member_type->tt_type == VAR_BOOL)
266 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100267 if (member_type->tt_type == VAR_NUMBER)
268 return &t_dict_number;
269 if (member_type->tt_type == VAR_STRING)
270 return &t_dict_string;
271
272 // Not a common type, create a new entry.
Bram Moolenaard77a8522020-04-03 21:59:57 +0200273 if (ga_grow(type_gap, 1) == FAIL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100274 return &t_any;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200275 type = ((type_T *)type_gap->ga_data) + type_gap->ga_len;
276 ++type_gap->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100277 type->tt_type = VAR_DICT;
278 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200279 type->tt_argcount = 0;
280 type->tt_args = NULL;
281 return type;
282}
283
284/*
285 * Get a function type, based on the return type "ret_type".
286 * If "argcount" is -1 or 0 a predefined type can be used.
287 * If "argcount" > 0 always create a new type, so that arguments can be added.
288 */
289 static type_T *
290get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
291{
292 type_T *type;
293
294 // recognize commonly used types
295 if (argcount <= 0)
296 {
297 if (ret_type == &t_void)
298 {
299 if (argcount == 0)
300 return &t_func_0_void;
301 else
302 return &t_func_void;
303 }
304 if (ret_type == &t_any)
305 {
306 if (argcount == 0)
307 return &t_func_0_any;
308 else
309 return &t_func_any;
310 }
311 if (ret_type == &t_number)
312 {
313 if (argcount == 0)
314 return &t_func_0_number;
315 else
316 return &t_func_number;
317 }
318 if (ret_type == &t_string)
319 {
320 if (argcount == 0)
321 return &t_func_0_string;
322 else
323 return &t_func_string;
324 }
325 }
326
327 // Not a common type or has arguments, create a new entry.
328 if (ga_grow(type_gap, 1) == FAIL)
329 return &t_any;
330 type = ((type_T *)type_gap->ga_data) + type_gap->ga_len;
331 ++type_gap->ga_len;
332 type->tt_type = VAR_FUNC;
333 type->tt_member = ret_type;
334 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100335 return type;
336}
337
Bram Moolenaara8c17702020-04-01 21:17:24 +0200338/*
339 * Return the type_T for a typval. Only for primitive types.
340 */
341 static type_T *
342typval2type(typval_T *tv)
343{
344 if (tv->v_type == VAR_NUMBER)
345 return &t_number;
346 if (tv->v_type == VAR_BOOL)
347 return &t_bool;
348 if (tv->v_type == VAR_STRING)
349 return &t_string;
350 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
351 return &t_list_string;
352 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
353 return &t_dict_any;
354 return &t_any;
355}
356
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100357/////////////////////////////////////////////////////////////////////
358// Following generate_ functions expect the caller to call ga_grow().
359
Bram Moolenaar080457c2020-03-03 21:53:32 +0100360#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
361#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
362
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100363/*
364 * Generate an instruction without arguments.
365 * Returns a pointer to the new instruction, NULL if failed.
366 */
367 static isn_T *
368generate_instr(cctx_T *cctx, isntype_T isn_type)
369{
370 garray_T *instr = &cctx->ctx_instr;
371 isn_T *isn;
372
Bram Moolenaar080457c2020-03-03 21:53:32 +0100373 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100374 if (ga_grow(instr, 1) == FAIL)
375 return NULL;
376 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
377 isn->isn_type = isn_type;
378 isn->isn_lnum = cctx->ctx_lnum + 1;
379 ++instr->ga_len;
380
381 return isn;
382}
383
384/*
385 * Generate an instruction without arguments.
386 * "drop" will be removed from the stack.
387 * Returns a pointer to the new instruction, NULL if failed.
388 */
389 static isn_T *
390generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
391{
392 garray_T *stack = &cctx->ctx_type_stack;
393
Bram Moolenaar080457c2020-03-03 21:53:32 +0100394 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100395 stack->ga_len -= drop;
396 return generate_instr(cctx, isn_type);
397}
398
399/*
400 * Generate instruction "isn_type" and put "type" on the type stack.
401 */
402 static isn_T *
403generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
404{
405 isn_T *isn;
406 garray_T *stack = &cctx->ctx_type_stack;
407
408 if ((isn = generate_instr(cctx, isn_type)) == NULL)
409 return NULL;
410
411 if (ga_grow(stack, 1) == FAIL)
412 return NULL;
413 ((type_T **)stack->ga_data)[stack->ga_len] = type;
414 ++stack->ga_len;
415
416 return isn;
417}
418
419/*
420 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
421 */
422 static int
423may_generate_2STRING(int offset, cctx_T *cctx)
424{
425 isn_T *isn;
426 garray_T *stack = &cctx->ctx_type_stack;
427 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
428
429 if ((*type)->tt_type == VAR_STRING)
430 return OK;
431 *type = &t_string;
432
433 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
434 return FAIL;
435 isn->isn_arg.number = offset;
436
437 return OK;
438}
439
440 static int
441check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
442{
443 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_UNKNOWN)
444 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
445 || type2 == VAR_UNKNOWN)))
446 {
447 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100448 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100449 else
450 semsg(_("E1036: %c requires number or float arguments"), *op);
451 return FAIL;
452 }
453 return OK;
454}
455
456/*
457 * Generate an instruction with two arguments. The instruction depends on the
458 * type of the arguments.
459 */
460 static int
461generate_two_op(cctx_T *cctx, char_u *op)
462{
463 garray_T *stack = &cctx->ctx_type_stack;
464 type_T *type1;
465 type_T *type2;
466 vartype_T vartype;
467 isn_T *isn;
468
Bram Moolenaar080457c2020-03-03 21:53:32 +0100469 RETURN_OK_IF_SKIP(cctx);
470
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100471 // Get the known type of the two items on the stack. If they are matching
472 // use a type-specific instruction. Otherwise fall back to runtime type
473 // checking.
474 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
475 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
476 vartype = VAR_UNKNOWN;
477 if (type1->tt_type == type2->tt_type
478 && (type1->tt_type == VAR_NUMBER
479 || type1->tt_type == VAR_LIST
480#ifdef FEAT_FLOAT
481 || type1->tt_type == VAR_FLOAT
482#endif
483 || type1->tt_type == VAR_BLOB))
484 vartype = type1->tt_type;
485
486 switch (*op)
487 {
488 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar0062c2d2020-02-20 22:14:31 +0100489 && type1->tt_type != VAR_UNKNOWN
490 && type2->tt_type != VAR_UNKNOWN
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100491 && check_number_or_float(
492 type1->tt_type, type2->tt_type, op) == FAIL)
493 return FAIL;
494 isn = generate_instr_drop(cctx,
495 vartype == VAR_NUMBER ? ISN_OPNR
496 : vartype == VAR_LIST ? ISN_ADDLIST
497 : vartype == VAR_BLOB ? ISN_ADDBLOB
498#ifdef FEAT_FLOAT
499 : vartype == VAR_FLOAT ? ISN_OPFLOAT
500#endif
501 : ISN_OPANY, 1);
502 if (isn != NULL)
503 isn->isn_arg.op.op_type = EXPR_ADD;
504 break;
505
506 case '-':
507 case '*':
508 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
509 op) == FAIL)
510 return FAIL;
511 if (vartype == VAR_NUMBER)
512 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
513#ifdef FEAT_FLOAT
514 else if (vartype == VAR_FLOAT)
515 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
516#endif
517 else
518 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
519 if (isn != NULL)
520 isn->isn_arg.op.op_type = *op == '*'
521 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
522 break;
523
524 case '%': if ((type1->tt_type != VAR_UNKNOWN
525 && type1->tt_type != VAR_NUMBER)
526 || (type2->tt_type != VAR_UNKNOWN
527 && type2->tt_type != VAR_NUMBER))
528 {
529 emsg(_("E1035: % requires number arguments"));
530 return FAIL;
531 }
532 isn = generate_instr_drop(cctx,
533 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
534 if (isn != NULL)
535 isn->isn_arg.op.op_type = EXPR_REM;
536 break;
537 }
538
539 // correct type of result
540 if (vartype == VAR_UNKNOWN)
541 {
542 type_T *type = &t_any;
543
544#ifdef FEAT_FLOAT
545 // float+number and number+float results in float
546 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
547 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
548 type = &t_float;
549#endif
550 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
551 }
552
553 return OK;
554}
555
556/*
557 * Generate an ISN_COMPARE* instruction with a boolean result.
558 */
559 static int
560generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
561{
562 isntype_T isntype = ISN_DROP;
563 isn_T *isn;
564 garray_T *stack = &cctx->ctx_type_stack;
565 vartype_T type1;
566 vartype_T type2;
567
Bram Moolenaar080457c2020-03-03 21:53:32 +0100568 RETURN_OK_IF_SKIP(cctx);
569
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100570 // Get the known type of the two items on the stack. If they are matching
571 // use a type-specific instruction. Otherwise fall back to runtime type
572 // checking.
573 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
574 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
575 if (type1 == type2)
576 {
577 switch (type1)
578 {
579 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
580 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
581 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
582 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
583 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
584 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
585 case VAR_LIST: isntype = ISN_COMPARELIST; break;
586 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
587 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
588 case VAR_PARTIAL: isntype = ISN_COMPAREPARTIAL; break;
589 default: isntype = ISN_COMPAREANY; break;
590 }
591 }
592 else if (type1 == VAR_UNKNOWN || type2 == VAR_UNKNOWN
593 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
594 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
595 isntype = ISN_COMPAREANY;
596
597 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
598 && (isntype == ISN_COMPAREBOOL
599 || isntype == ISN_COMPARESPECIAL
600 || isntype == ISN_COMPARENR
601 || isntype == ISN_COMPAREFLOAT))
602 {
603 semsg(_("E1037: Cannot use \"%s\" with %s"),
604 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
605 return FAIL;
606 }
607 if (isntype == ISN_DROP
608 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
609 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
610 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
611 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
612 && exptype != EXPR_IS && exptype != EXPR_ISNOT
613 && (type1 == VAR_BLOB || type2 == VAR_BLOB
614 || type1 == VAR_LIST || type2 == VAR_LIST))))
615 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100616 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100617 vartype_name(type1), vartype_name(type2));
618 return FAIL;
619 }
620
621 if ((isn = generate_instr(cctx, isntype)) == NULL)
622 return FAIL;
623 isn->isn_arg.op.op_type = exptype;
624 isn->isn_arg.op.op_ic = ic;
625
626 // takes two arguments, puts one bool back
627 if (stack->ga_len >= 2)
628 {
629 --stack->ga_len;
630 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
631 }
632
633 return OK;
634}
635
636/*
637 * Generate an ISN_2BOOL instruction.
638 */
639 static int
640generate_2BOOL(cctx_T *cctx, int invert)
641{
642 isn_T *isn;
643 garray_T *stack = &cctx->ctx_type_stack;
644
Bram Moolenaar080457c2020-03-03 21:53:32 +0100645 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100646 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
647 return FAIL;
648 isn->isn_arg.number = invert;
649
650 // type becomes bool
651 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
652
653 return OK;
654}
655
656 static int
657generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
658{
659 isn_T *isn;
660 garray_T *stack = &cctx->ctx_type_stack;
661
Bram Moolenaar080457c2020-03-03 21:53:32 +0100662 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100663 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
664 return FAIL;
665 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
666 isn->isn_arg.type.ct_off = offset;
667
668 // type becomes vartype
669 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
670
671 return OK;
672}
673
674/*
675 * Generate an ISN_PUSHNR instruction.
676 */
677 static int
678generate_PUSHNR(cctx_T *cctx, varnumber_T number)
679{
680 isn_T *isn;
681
Bram Moolenaar080457c2020-03-03 21:53:32 +0100682 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100683 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
684 return FAIL;
685 isn->isn_arg.number = number;
686
687 return OK;
688}
689
690/*
691 * Generate an ISN_PUSHBOOL instruction.
692 */
693 static int
694generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
695{
696 isn_T *isn;
697
Bram Moolenaar080457c2020-03-03 21:53:32 +0100698 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100699 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
700 return FAIL;
701 isn->isn_arg.number = number;
702
703 return OK;
704}
705
706/*
707 * Generate an ISN_PUSHSPEC instruction.
708 */
709 static int
710generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
711{
712 isn_T *isn;
713
Bram Moolenaar080457c2020-03-03 21:53:32 +0100714 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100715 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
716 return FAIL;
717 isn->isn_arg.number = number;
718
719 return OK;
720}
721
722#ifdef FEAT_FLOAT
723/*
724 * Generate an ISN_PUSHF instruction.
725 */
726 static int
727generate_PUSHF(cctx_T *cctx, float_T fnumber)
728{
729 isn_T *isn;
730
Bram Moolenaar080457c2020-03-03 21:53:32 +0100731 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100732 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
733 return FAIL;
734 isn->isn_arg.fnumber = fnumber;
735
736 return OK;
737}
738#endif
739
740/*
741 * Generate an ISN_PUSHS instruction.
742 * Consumes "str".
743 */
744 static int
745generate_PUSHS(cctx_T *cctx, char_u *str)
746{
747 isn_T *isn;
748
Bram Moolenaar080457c2020-03-03 21:53:32 +0100749 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100750 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
751 return FAIL;
752 isn->isn_arg.string = str;
753
754 return OK;
755}
756
757/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100758 * Generate an ISN_PUSHCHANNEL instruction.
759 * Consumes "channel".
760 */
761 static int
762generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
763{
764 isn_T *isn;
765
Bram Moolenaar080457c2020-03-03 21:53:32 +0100766 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100767 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
768 return FAIL;
769 isn->isn_arg.channel = channel;
770
771 return OK;
772}
773
774/*
775 * Generate an ISN_PUSHJOB instruction.
776 * Consumes "job".
777 */
778 static int
779generate_PUSHJOB(cctx_T *cctx, job_T *job)
780{
781 isn_T *isn;
782
Bram Moolenaar080457c2020-03-03 21:53:32 +0100783 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100784 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100785 return FAIL;
786 isn->isn_arg.job = job;
787
788 return OK;
789}
790
791/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100792 * Generate an ISN_PUSHBLOB instruction.
793 * Consumes "blob".
794 */
795 static int
796generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
797{
798 isn_T *isn;
799
Bram Moolenaar080457c2020-03-03 21:53:32 +0100800 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100801 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
802 return FAIL;
803 isn->isn_arg.blob = blob;
804
805 return OK;
806}
807
808/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100809 * Generate an ISN_PUSHFUNC instruction with name "name".
810 * Consumes "name".
811 */
812 static int
813generate_PUSHFUNC(cctx_T *cctx, char_u *name)
814{
815 isn_T *isn;
816
Bram Moolenaar080457c2020-03-03 21:53:32 +0100817 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100818 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, &t_func_void)) == NULL)
819 return FAIL;
820 isn->isn_arg.string = name;
821
822 return OK;
823}
824
825/*
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100826 * Generate an ISN_PUSHPARTIAL instruction with partial "part".
Bram Moolenaare69f6d02020-04-01 22:11:01 +0200827 * Consumes "part".
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100828 */
829 static int
830generate_PUSHPARTIAL(cctx_T *cctx, partial_T *part)
831{
832 isn_T *isn;
833
Bram Moolenaar080457c2020-03-03 21:53:32 +0100834 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaard77a8522020-04-03 21:59:57 +0200835 if ((isn = generate_instr_type(cctx, ISN_PUSHPARTIAL, &t_func_any)) == NULL)
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100836 return FAIL;
837 isn->isn_arg.partial = part;
838
839 return OK;
840}
841
842/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100843 * Generate an ISN_STORE instruction.
844 */
845 static int
846generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
847{
848 isn_T *isn;
849
Bram Moolenaar080457c2020-03-03 21:53:32 +0100850 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100851 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
852 return FAIL;
853 if (name != NULL)
854 isn->isn_arg.string = vim_strsave(name);
855 else
856 isn->isn_arg.number = idx;
857
858 return OK;
859}
860
861/*
862 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
863 */
864 static int
865generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
866{
867 isn_T *isn;
868
Bram Moolenaar080457c2020-03-03 21:53:32 +0100869 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100870 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
871 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100872 isn->isn_arg.storenr.stnr_idx = idx;
873 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100874
875 return OK;
876}
877
878/*
879 * Generate an ISN_STOREOPT instruction
880 */
881 static int
882generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
883{
884 isn_T *isn;
885
Bram Moolenaar080457c2020-03-03 21:53:32 +0100886 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100887 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
888 return FAIL;
889 isn->isn_arg.storeopt.so_name = vim_strsave(name);
890 isn->isn_arg.storeopt.so_flags = opt_flags;
891
892 return OK;
893}
894
895/*
896 * Generate an ISN_LOAD or similar instruction.
897 */
898 static int
899generate_LOAD(
900 cctx_T *cctx,
901 isntype_T isn_type,
902 int idx,
903 char_u *name,
904 type_T *type)
905{
906 isn_T *isn;
907
Bram Moolenaar080457c2020-03-03 21:53:32 +0100908 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100909 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
910 return FAIL;
911 if (name != NULL)
912 isn->isn_arg.string = vim_strsave(name);
913 else
914 isn->isn_arg.number = idx;
915
916 return OK;
917}
918
919/*
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100920 * Generate an ISN_LOADV instruction.
921 */
922 static int
923generate_LOADV(
924 cctx_T *cctx,
925 char_u *name,
926 int error)
927{
928 // load v:var
929 int vidx = find_vim_var(name);
930
Bram Moolenaar080457c2020-03-03 21:53:32 +0100931 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100932 if (vidx < 0)
933 {
934 if (error)
935 semsg(_(e_var_notfound), name);
936 return FAIL;
937 }
938
939 // TODO: get actual type
940 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, &t_any);
941}
942
943/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100944 * Generate an ISN_LOADS instruction.
945 */
946 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100947generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100948 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100949 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100950 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100951 int sid,
952 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100953{
954 isn_T *isn;
955
Bram Moolenaar080457c2020-03-03 21:53:32 +0100956 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100957 if (isn_type == ISN_LOADS)
958 isn = generate_instr_type(cctx, isn_type, type);
959 else
960 isn = generate_instr_drop(cctx, isn_type, 1);
961 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100962 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100963 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
964 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100965
966 return OK;
967}
968
969/*
970 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
971 */
972 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100973generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100974 cctx_T *cctx,
975 isntype_T isn_type,
976 int sid,
977 int idx,
978 type_T *type)
979{
980 isn_T *isn;
981
Bram Moolenaar080457c2020-03-03 21:53:32 +0100982 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100983 if (isn_type == ISN_LOADSCRIPT)
984 isn = generate_instr_type(cctx, isn_type, type);
985 else
986 isn = generate_instr_drop(cctx, isn_type, 1);
987 if (isn == NULL)
988 return FAIL;
989 isn->isn_arg.script.script_sid = sid;
990 isn->isn_arg.script.script_idx = idx;
991 return OK;
992}
993
994/*
995 * Generate an ISN_NEWLIST instruction.
996 */
997 static int
998generate_NEWLIST(cctx_T *cctx, int count)
999{
1000 isn_T *isn;
1001 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001002 type_T *type;
1003 type_T *member;
1004
Bram Moolenaar080457c2020-03-03 21:53:32 +01001005 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001006 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1007 return FAIL;
1008 isn->isn_arg.number = count;
1009
1010 // drop the value types
1011 stack->ga_len -= count;
1012
Bram Moolenaar436472f2020-02-20 22:54:43 +01001013 // Use the first value type for the list member type. Use "void" for an
1014 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001015 if (count > 0)
1016 member = ((type_T **)stack->ga_data)[stack->ga_len];
1017 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001018 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001019 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001020
1021 // add the list type to the type stack
1022 if (ga_grow(stack, 1) == FAIL)
1023 return FAIL;
1024 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1025 ++stack->ga_len;
1026
1027 return OK;
1028}
1029
1030/*
1031 * Generate an ISN_NEWDICT instruction.
1032 */
1033 static int
1034generate_NEWDICT(cctx_T *cctx, int count)
1035{
1036 isn_T *isn;
1037 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001038 type_T *type;
1039 type_T *member;
1040
Bram Moolenaar080457c2020-03-03 21:53:32 +01001041 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001042 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1043 return FAIL;
1044 isn->isn_arg.number = count;
1045
1046 // drop the key and value types
1047 stack->ga_len -= 2 * count;
1048
Bram Moolenaar436472f2020-02-20 22:54:43 +01001049 // Use the first value type for the list member type. Use "void" for an
1050 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001051 if (count > 0)
1052 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1053 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001054 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001055 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001056
1057 // add the dict type to the type stack
1058 if (ga_grow(stack, 1) == FAIL)
1059 return FAIL;
1060 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1061 ++stack->ga_len;
1062
1063 return OK;
1064}
1065
1066/*
1067 * Generate an ISN_FUNCREF instruction.
1068 */
1069 static int
1070generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1071{
1072 isn_T *isn;
1073 garray_T *stack = &cctx->ctx_type_stack;
1074
Bram Moolenaar080457c2020-03-03 21:53:32 +01001075 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001076 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1077 return FAIL;
1078 isn->isn_arg.number = dfunc_idx;
1079
1080 if (ga_grow(stack, 1) == FAIL)
1081 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001082 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001083 // TODO: argument and return types
1084 ++stack->ga_len;
1085
1086 return OK;
1087}
1088
1089/*
1090 * Generate an ISN_JUMP instruction.
1091 */
1092 static int
1093generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1094{
1095 isn_T *isn;
1096 garray_T *stack = &cctx->ctx_type_stack;
1097
Bram Moolenaar080457c2020-03-03 21:53:32 +01001098 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001099 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1100 return FAIL;
1101 isn->isn_arg.jump.jump_when = when;
1102 isn->isn_arg.jump.jump_where = where;
1103
1104 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1105 --stack->ga_len;
1106
1107 return OK;
1108}
1109
1110 static int
1111generate_FOR(cctx_T *cctx, int loop_idx)
1112{
1113 isn_T *isn;
1114 garray_T *stack = &cctx->ctx_type_stack;
1115
Bram Moolenaar080457c2020-03-03 21:53:32 +01001116 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001117 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1118 return FAIL;
1119 isn->isn_arg.forloop.for_idx = loop_idx;
1120
1121 if (ga_grow(stack, 1) == FAIL)
1122 return FAIL;
1123 // type doesn't matter, will be stored next
1124 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1125 ++stack->ga_len;
1126
1127 return OK;
1128}
1129
1130/*
1131 * Generate an ISN_BCALL instruction.
1132 * Return FAIL if the number of arguments is wrong.
1133 */
1134 static int
1135generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1136{
1137 isn_T *isn;
1138 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001139 type_T *argtypes[MAX_FUNC_ARGS];
1140 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001141
Bram Moolenaar080457c2020-03-03 21:53:32 +01001142 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001143 if (check_internal_func(func_idx, argcount) == FAIL)
1144 return FAIL;
1145
1146 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1147 return FAIL;
1148 isn->isn_arg.bfunc.cbf_idx = func_idx;
1149 isn->isn_arg.bfunc.cbf_argcount = argcount;
1150
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001151 for (i = 0; i < argcount; ++i)
1152 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1153
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001154 stack->ga_len -= argcount; // drop the arguments
1155 if (ga_grow(stack, 1) == FAIL)
1156 return FAIL;
1157 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001158 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001159 ++stack->ga_len; // add return value
1160
1161 return OK;
1162}
1163
1164/*
1165 * Generate an ISN_DCALL or ISN_UCALL instruction.
1166 * Return FAIL if the number of arguments is wrong.
1167 */
1168 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001169generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001170{
1171 isn_T *isn;
1172 garray_T *stack = &cctx->ctx_type_stack;
1173 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001174 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001175
Bram Moolenaar080457c2020-03-03 21:53:32 +01001176 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001177 if (argcount > regular_args && !has_varargs(ufunc))
1178 {
1179 semsg(_(e_toomanyarg), ufunc->uf_name);
1180 return FAIL;
1181 }
1182 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1183 {
1184 semsg(_(e_toofewarg), ufunc->uf_name);
1185 return FAIL;
1186 }
1187
1188 // Turn varargs into a list.
1189 if (ufunc->uf_va_name != NULL)
1190 {
1191 int count = argcount - regular_args;
1192
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001193 // If count is negative an empty list will be added after evaluating
1194 // default values for missing optional arguments.
1195 if (count >= 0)
1196 {
1197 generate_NEWLIST(cctx, count);
1198 argcount = regular_args + 1;
1199 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001200 }
1201
1202 if ((isn = generate_instr(cctx,
1203 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1204 return FAIL;
1205 if (ufunc->uf_dfunc_idx >= 0)
1206 {
1207 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1208 isn->isn_arg.dfunc.cdf_argcount = argcount;
1209 }
1210 else
1211 {
1212 // A user function may be deleted and redefined later, can't use the
1213 // ufunc pointer, need to look it up again at runtime.
1214 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1215 isn->isn_arg.ufunc.cuf_argcount = argcount;
1216 }
1217
1218 stack->ga_len -= argcount; // drop the arguments
1219 if (ga_grow(stack, 1) == FAIL)
1220 return FAIL;
1221 // add return value
1222 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1223 ++stack->ga_len;
1224
1225 return OK;
1226}
1227
1228/*
1229 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1230 */
1231 static int
1232generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1233{
1234 isn_T *isn;
1235 garray_T *stack = &cctx->ctx_type_stack;
1236
Bram Moolenaar080457c2020-03-03 21:53:32 +01001237 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001238 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1239 return FAIL;
1240 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1241 isn->isn_arg.ufunc.cuf_argcount = argcount;
1242
1243 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001244 if (ga_grow(stack, 1) == FAIL)
1245 return FAIL;
1246 // add return value
1247 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1248 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001249
1250 return OK;
1251}
1252
1253/*
1254 * Generate an ISN_PCALL instruction.
1255 */
1256 static int
1257generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1258{
1259 isn_T *isn;
1260 garray_T *stack = &cctx->ctx_type_stack;
1261
Bram Moolenaar080457c2020-03-03 21:53:32 +01001262 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001263 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1264 return FAIL;
1265 isn->isn_arg.pfunc.cpf_top = at_top;
1266 isn->isn_arg.pfunc.cpf_argcount = argcount;
1267
1268 stack->ga_len -= argcount; // drop the arguments
1269
1270 // drop the funcref/partial, get back the return value
1271 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1272
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001273 // If partial is above the arguments it must be cleared and replaced with
1274 // the return value.
1275 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1276 return FAIL;
1277
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001278 return OK;
1279}
1280
1281/*
1282 * Generate an ISN_MEMBER instruction.
1283 */
1284 static int
1285generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1286{
1287 isn_T *isn;
1288 garray_T *stack = &cctx->ctx_type_stack;
1289 type_T *type;
1290
Bram Moolenaar080457c2020-03-03 21:53:32 +01001291 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001292 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1293 return FAIL;
1294 isn->isn_arg.string = vim_strnsave(name, (int)len);
1295
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001296 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001297 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001298 if (type->tt_type != VAR_DICT && type != &t_any)
1299 {
1300 emsg(_(e_dictreq));
1301 return FAIL;
1302 }
1303 // change dict type to dict member type
1304 if (type->tt_type == VAR_DICT)
1305 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001306
1307 return OK;
1308}
1309
1310/*
1311 * Generate an ISN_ECHO instruction.
1312 */
1313 static int
1314generate_ECHO(cctx_T *cctx, int with_white, int count)
1315{
1316 isn_T *isn;
1317
Bram Moolenaar080457c2020-03-03 21:53:32 +01001318 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001319 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1320 return FAIL;
1321 isn->isn_arg.echo.echo_with_white = with_white;
1322 isn->isn_arg.echo.echo_count = count;
1323
1324 return OK;
1325}
1326
Bram Moolenaarad39c092020-02-26 18:23:43 +01001327/*
1328 * Generate an ISN_EXECUTE instruction.
1329 */
1330 static int
1331generate_EXECUTE(cctx_T *cctx, int count)
1332{
1333 isn_T *isn;
1334
1335 if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL)
1336 return FAIL;
1337 isn->isn_arg.number = count;
1338
1339 return OK;
1340}
1341
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001342 static int
1343generate_EXEC(cctx_T *cctx, char_u *line)
1344{
1345 isn_T *isn;
1346
Bram Moolenaar080457c2020-03-03 21:53:32 +01001347 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001348 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1349 return FAIL;
1350 isn->isn_arg.string = vim_strsave(line);
1351 return OK;
1352}
1353
1354static char e_white_both[] =
1355 N_("E1004: white space required before and after '%s'");
Bram Moolenaard77a8522020-04-03 21:59:57 +02001356static char e_white_after[] = N_("E1069: white space required after '%s'");
1357static char e_no_white_before[] = N_("E1068: No white space allowed before '%s'");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001358
1359/*
1360 * Reserve space for a local variable.
1361 * Return the index or -1 if it failed.
1362 */
1363 static int
1364reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1365{
1366 int idx;
1367 lvar_T *lvar;
1368
1369 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1370 {
1371 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1372 return -1;
1373 }
1374
1375 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1376 return -1;
1377 idx = cctx->ctx_locals.ga_len;
1378 if (cctx->ctx_max_local < idx + 1)
1379 cctx->ctx_max_local = idx + 1;
1380 ++cctx->ctx_locals.ga_len;
1381
1382 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1383 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1384 lvar->lv_const = isConst;
1385 lvar->lv_type = type;
1386
1387 return idx;
1388}
1389
1390/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001391 * Remove local variables above "new_top".
1392 */
1393 static void
1394unwind_locals(cctx_T *cctx, int new_top)
1395{
1396 if (cctx->ctx_locals.ga_len > new_top)
1397 {
1398 int idx;
1399 lvar_T *lvar;
1400
1401 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1402 {
1403 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1404 vim_free(lvar->lv_name);
1405 }
1406 }
1407 cctx->ctx_locals.ga_len = new_top;
1408}
1409
1410/*
1411 * Free all local variables.
1412 */
1413 static void
1414free_local(cctx_T *cctx)
1415{
1416 unwind_locals(cctx, 0);
1417 ga_clear(&cctx->ctx_locals);
1418}
1419
1420/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001421 * Skip over a type definition and return a pointer to just after it.
1422 */
1423 char_u *
1424skip_type(char_u *start)
1425{
1426 char_u *p = start;
1427
1428 while (ASCII_ISALNUM(*p) || *p == '_')
1429 ++p;
1430
1431 // Skip over "<type>"; this is permissive about white space.
1432 if (*skipwhite(p) == '<')
1433 {
1434 p = skipwhite(p);
1435 p = skip_type(skipwhite(p + 1));
1436 p = skipwhite(p);
1437 if (*p == '>')
1438 ++p;
1439 }
1440 return p;
1441}
1442
1443/*
1444 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001445 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001446 * Returns NULL in case of failure.
1447 */
1448 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001449parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001450{
1451 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001452 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001453
1454 if (**arg != '<')
1455 {
1456 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001457 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001458 else
1459 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001460 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001461 }
1462 *arg = skipwhite(*arg + 1);
1463
Bram Moolenaard77a8522020-04-03 21:59:57 +02001464 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001465
1466 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001467 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001468 {
1469 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001470 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001471 }
1472 ++*arg;
1473
1474 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001475 return get_list_type(member_type, type_gap);
1476 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001477}
1478
1479/*
1480 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001481 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001482 */
1483 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001484parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001485{
1486 char_u *p = *arg;
1487 size_t len;
1488
1489 // skip over the first word
1490 while (ASCII_ISALNUM(*p) || *p == '_')
1491 ++p;
1492 len = p - *arg;
1493
1494 switch (**arg)
1495 {
1496 case 'a':
1497 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1498 {
1499 *arg += len;
1500 return &t_any;
1501 }
1502 break;
1503 case 'b':
1504 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1505 {
1506 *arg += len;
1507 return &t_bool;
1508 }
1509 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1510 {
1511 *arg += len;
1512 return &t_blob;
1513 }
1514 break;
1515 case 'c':
1516 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1517 {
1518 *arg += len;
1519 return &t_channel;
1520 }
1521 break;
1522 case 'd':
1523 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1524 {
1525 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001526 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001527 }
1528 break;
1529 case 'f':
1530 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1531 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001532#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001533 *arg += len;
1534 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001535#else
1536 emsg(_("E1055: This Vim is not compiled with float support"));
1537 return &t_any;
1538#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001539 }
1540 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1541 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001542 type_T *type;
1543 type_T *ret_type = &t_void;
1544 int argcount = -1;
1545 int flags = 0;
1546 type_T *arg_type[MAX_FUNC_ARGS + 1];
1547
1548 // func({type}, ...): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001549 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001550 if (**arg == '(')
1551 {
1552 p = ++*arg;
1553 argcount = 0;
1554 while (*p != NUL && *p != ')')
1555 {
1556 if (STRNCMP(p, "...", 3) == 0)
1557 {
1558 flags |= TTFLAG_VARARGS;
1559 break;
1560 }
1561 arg_type[argcount++] = parse_type(&p, type_gap);
1562
1563 if (*p != ',' && *skipwhite(p) == ',')
1564 {
1565 semsg(_(e_no_white_before), ",");
1566 return &t_any;
1567 }
1568 if (*p == ',')
1569 {
1570 ++p;
1571 if (!VIM_ISWHITE(*p))
1572 semsg(_(e_white_after), ",");
1573 }
1574 p = skipwhite(p);
1575 if (argcount == MAX_FUNC_ARGS)
1576 {
1577 emsg(_("E740: Too many argument types"));
1578 return &t_any;
1579 }
1580 }
1581
1582 p = skipwhite(p);
1583 if (*p != ')')
1584 {
1585 emsg(_(e_missing_close));
1586 return &t_any;
1587 }
1588 *arg = p + 1;
1589 }
1590 if (**arg == ':')
1591 {
1592 // parse return type
1593 ++*arg;
1594 if (!VIM_ISWHITE(*p))
1595 semsg(_(e_white_after), ":");
1596 *arg = skipwhite(*arg);
1597 ret_type = parse_type(arg, type_gap);
1598 }
1599 type = get_func_type(ret_type, flags == 0 ? argcount : 99,
1600 type_gap);
1601 if (flags != 0)
1602 type->tt_flags = flags;
1603 if (argcount > 0)
1604 {
1605 int type_ptr_cnt = (sizeof(type_T *) * argcount
1606 + sizeof(type_T) - 1) / sizeof(type_T);
1607
1608 type->tt_argcount = argcount;
1609 // Get space from "type_gap" to avoid having to keep track
1610 // of the pointer and freeing it.
1611 ga_grow(type_gap, type_ptr_cnt);
1612 if (ga_grow(type_gap, type_ptr_cnt) == FAIL)
1613 return &t_any;
1614 type->tt_args =
1615 ((type_T **)type_gap->ga_data) + type_gap->ga_len;
1616 type_gap->ga_len += type_ptr_cnt;
1617 mch_memmove(type->tt_args, arg_type,
1618 sizeof(type_T *) * argcount);
1619 }
1620 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001621 }
1622 break;
1623 case 'j':
1624 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1625 {
1626 *arg += len;
1627 return &t_job;
1628 }
1629 break;
1630 case 'l':
1631 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1632 {
1633 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001634 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001635 }
1636 break;
1637 case 'n':
1638 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1639 {
1640 *arg += len;
1641 return &t_number;
1642 }
1643 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001644 case 's':
1645 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1646 {
1647 *arg += len;
1648 return &t_string;
1649 }
1650 break;
1651 case 'v':
1652 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1653 {
1654 *arg += len;
1655 return &t_void;
1656 }
1657 break;
1658 }
1659
1660 semsg(_("E1010: Type not recognized: %s"), *arg);
1661 return &t_any;
1662}
1663
1664/*
1665 * Check if "type1" and "type2" are exactly the same.
1666 */
1667 static int
1668equal_type(type_T *type1, type_T *type2)
1669{
1670 if (type1->tt_type != type2->tt_type)
1671 return FALSE;
1672 switch (type1->tt_type)
1673 {
1674 case VAR_VOID:
1675 case VAR_UNKNOWN:
1676 case VAR_SPECIAL:
1677 case VAR_BOOL:
1678 case VAR_NUMBER:
1679 case VAR_FLOAT:
1680 case VAR_STRING:
1681 case VAR_BLOB:
1682 case VAR_JOB:
1683 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001684 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001685 case VAR_LIST:
1686 case VAR_DICT:
1687 return equal_type(type1->tt_member, type2->tt_member);
1688 case VAR_FUNC:
1689 case VAR_PARTIAL:
1690 // TODO; check argument types.
1691 return equal_type(type1->tt_member, type2->tt_member)
1692 && type1->tt_argcount == type2->tt_argcount;
1693 }
1694 return TRUE;
1695}
1696
1697/*
1698 * Find the common type of "type1" and "type2" and put it in "dest".
1699 * "type2" and "dest" may be the same.
1700 */
1701 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001702common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001703{
1704 if (equal_type(type1, type2))
1705 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001706 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001707 return;
1708 }
1709
1710 if (type1->tt_type == type2->tt_type)
1711 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001712 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1713 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001714 type_T *common;
1715
Bram Moolenaard77a8522020-04-03 21:59:57 +02001716 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001717 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001718 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001719 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001720 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001721 return;
1722 }
1723 // TODO: VAR_FUNC and VAR_PARTIAL
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001724 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001725 }
1726
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001727 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001728}
1729
1730 char *
1731vartype_name(vartype_T type)
1732{
1733 switch (type)
1734 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001735 case VAR_UNKNOWN: break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001736 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001737 case VAR_SPECIAL: return "special";
1738 case VAR_BOOL: return "bool";
1739 case VAR_NUMBER: return "number";
1740 case VAR_FLOAT: return "float";
1741 case VAR_STRING: return "string";
1742 case VAR_BLOB: return "blob";
1743 case VAR_JOB: return "job";
1744 case VAR_CHANNEL: return "channel";
1745 case VAR_LIST: return "list";
1746 case VAR_DICT: return "dict";
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001747 case VAR_FUNC: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001748 case VAR_PARTIAL: return "partial";
1749 }
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001750 return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001751}
1752
1753/*
1754 * Return the name of a type.
1755 * The result may be in allocated memory, in which case "tofree" is set.
1756 */
1757 char *
1758type_name(type_T *type, char **tofree)
1759{
1760 char *name = vartype_name(type->tt_type);
1761
1762 *tofree = NULL;
1763 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1764 {
1765 char *member_free;
1766 char *member_name = type_name(type->tt_member, &member_free);
1767 size_t len;
1768
1769 len = STRLEN(name) + STRLEN(member_name) + 3;
1770 *tofree = alloc(len);
1771 if (*tofree != NULL)
1772 {
1773 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1774 vim_free(member_free);
1775 return *tofree;
1776 }
1777 }
1778 // TODO: function and partial argument types
1779
1780 return name;
1781}
1782
1783/*
1784 * Find "name" in script-local items of script "sid".
1785 * Returns the index in "sn_var_vals" if found.
1786 * If found but not in "sn_var_vals" returns -1.
1787 * If not found returns -2.
1788 */
1789 int
1790get_script_item_idx(int sid, char_u *name, int check_writable)
1791{
1792 hashtab_T *ht;
1793 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001794 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001795 int idx;
1796
1797 // First look the name up in the hashtable.
1798 if (sid <= 0 || sid > script_items.ga_len)
1799 return -1;
1800 ht = &SCRIPT_VARS(sid);
1801 di = find_var_in_ht(ht, 0, name, TRUE);
1802 if (di == NULL)
1803 return -2;
1804
1805 // Now find the svar_T index in sn_var_vals.
1806 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
1807 {
1808 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1809
1810 if (sv->sv_tv == &di->di_tv)
1811 {
1812 if (check_writable && sv->sv_const)
1813 semsg(_(e_readonlyvar), name);
1814 return idx;
1815 }
1816 }
1817 return -1;
1818}
1819
1820/*
1821 * Find "name" in imported items of the current script/
1822 */
1823 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001824find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001825{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001826 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001827 int idx;
1828
1829 if (cctx != NULL)
1830 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1831 {
1832 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
1833 + idx;
1834
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001835 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1836 : STRLEN(import->imp_name) == len
1837 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001838 return import;
1839 }
1840
1841 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
1842 {
1843 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
1844
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001845 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1846 : STRLEN(import->imp_name) == len
1847 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001848 return import;
1849 }
1850 return NULL;
1851}
1852
1853/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001854 * Free all imported variables.
1855 */
1856 static void
1857free_imported(cctx_T *cctx)
1858{
1859 int idx;
1860
1861 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1862 {
1863 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
1864
1865 vim_free(import->imp_name);
1866 }
1867 ga_clear(&cctx->ctx_imports);
1868}
1869
1870/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001871 * Generate an instruction to load script-local variable "name".
1872 */
1873 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001874compile_load_scriptvar(
1875 cctx_T *cctx,
1876 char_u *name, // variable NUL terminated
1877 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001878 char_u **end, // end of variable
1879 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001880{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001881 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001882 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
1883 imported_T *import;
1884
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001885 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001886 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001887 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001888 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
1889 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001890 }
1891 if (idx >= 0)
1892 {
1893 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1894
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001895 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001896 current_sctx.sc_sid, idx, sv->sv_type);
1897 return OK;
1898 }
1899
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001900 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001901 if (import != NULL)
1902 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001903 if (import->imp_all)
1904 {
1905 char_u *p = skipwhite(*end);
1906 int name_len;
1907 ufunc_T *ufunc;
1908 type_T *type;
1909
1910 // Used "import * as Name", need to lookup the member.
1911 if (*p != '.')
1912 {
1913 semsg(_("E1060: expected dot after name: %s"), start);
1914 return FAIL;
1915 }
1916 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001917 if (VIM_ISWHITE(*p))
1918 {
1919 emsg(_("E1074: no white space allowed after dot"));
1920 return FAIL;
1921 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001922
1923 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
1924 // TODO: what if it is a function?
1925 if (idx < 0)
1926 return FAIL;
1927 *end = p;
1928
1929 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
1930 import->imp_sid,
1931 idx,
1932 type);
1933 }
1934 else
1935 {
1936 // TODO: check this is a variable, not a function
1937 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
1938 import->imp_sid,
1939 import->imp_var_vals_idx,
1940 import->imp_type);
1941 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001942 return OK;
1943 }
1944
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001945 if (error)
1946 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001947 return FAIL;
1948}
1949
1950/*
1951 * Compile a variable name into a load instruction.
1952 * "end" points to just after the name.
1953 * When "error" is FALSE do not give an error when not found.
1954 */
1955 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001956compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001957{
1958 type_T *type;
1959 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001960 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001961 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001962 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001963
1964 if (*(*arg + 1) == ':')
1965 {
1966 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01001967 if (end <= *arg + 2)
1968 name = vim_strsave((char_u *)"[empty]");
1969 else
1970 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001971 if (name == NULL)
1972 return FAIL;
1973
1974 if (**arg == 'v')
1975 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001976 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001977 }
1978 else if (**arg == 'g')
1979 {
1980 // Global variables can be defined later, thus we don't check if it
1981 // exists, give error at runtime.
1982 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
1983 }
1984 else if (**arg == 's')
1985 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001986 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001987 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01001988 else if (**arg == 'b')
1989 {
1990 semsg("Namespace b: not supported yet: %s", *arg);
1991 goto theend;
1992 }
1993 else if (**arg == 'w')
1994 {
1995 semsg("Namespace w: not supported yet: %s", *arg);
1996 goto theend;
1997 }
1998 else if (**arg == 't')
1999 {
2000 semsg("Namespace t: not supported yet: %s", *arg);
2001 goto theend;
2002 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002003 else
2004 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002005 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002006 goto theend;
2007 }
2008 }
2009 else
2010 {
2011 size_t len = end - *arg;
2012 int idx;
2013 int gen_load = FALSE;
2014
2015 name = vim_strnsave(*arg, end - *arg);
2016 if (name == NULL)
2017 return FAIL;
2018
2019 idx = lookup_arg(*arg, len, cctx);
2020 if (idx >= 0)
2021 {
2022 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2023 type = cctx->ctx_ufunc->uf_arg_types[idx];
2024 else
2025 type = &t_any;
2026
2027 // Arguments are located above the frame pointer.
2028 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2029 if (cctx->ctx_ufunc->uf_va_name != NULL)
2030 --idx;
2031 gen_load = TRUE;
2032 }
2033 else if (lookup_vararg(*arg, len, cctx))
2034 {
2035 // varargs is always the last argument
2036 idx = -STACK_FRAME_SIZE - 1;
2037 type = cctx->ctx_ufunc->uf_va_type;
2038 gen_load = TRUE;
2039 }
2040 else
2041 {
2042 idx = lookup_local(*arg, len, cctx);
2043 if (idx >= 0)
2044 {
2045 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2046 gen_load = TRUE;
2047 }
2048 else
2049 {
2050 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2051 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2052 res = generate_PUSHBOOL(cctx, **arg == 't'
2053 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002054 else if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2055 == SCRIPT_VERSION_VIM9)
2056 // in Vim9 script "var" can be script-local.
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002057 res = compile_load_scriptvar(cctx, name, *arg, &end, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002058 }
2059 }
2060 if (gen_load)
2061 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2062 }
2063
2064 *arg = end;
2065
2066theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002067 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002068 semsg(_(e_var_notfound), name);
2069 vim_free(name);
2070 return res;
2071}
2072
2073/*
2074 * Compile the argument expressions.
2075 * "arg" points to just after the "(" and is advanced to after the ")"
2076 */
2077 static int
2078compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2079{
2080 char_u *p = *arg;
2081
2082 while (*p != NUL && *p != ')')
2083 {
2084 if (compile_expr1(&p, cctx) == FAIL)
2085 return FAIL;
2086 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002087
2088 if (*p != ',' && *skipwhite(p) == ',')
2089 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002090 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002091 p = skipwhite(p);
2092 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002093 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002094 {
2095 ++p;
2096 if (!VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002097 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002098 }
2099 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002100 }
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002101 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002102 if (*p != ')')
2103 {
2104 emsg(_(e_missing_close));
2105 return FAIL;
2106 }
2107 *arg = p + 1;
2108 return OK;
2109}
2110
2111/*
2112 * Compile a function call: name(arg1, arg2)
2113 * "arg" points to "name", "arg + varlen" to the "(".
2114 * "argcount_init" is 1 for "value->method()"
2115 * Instructions:
2116 * EVAL arg1
2117 * EVAL arg2
2118 * BCALL / DCALL / UCALL
2119 */
2120 static int
2121compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2122{
2123 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002124 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002125 int argcount = argcount_init;
2126 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002127 char_u fname_buf[FLEN_FIXED + 1];
2128 char_u *tofree = NULL;
2129 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002130 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002131 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002132
2133 if (varlen >= sizeof(namebuf))
2134 {
2135 semsg(_("E1011: name too long: %s"), name);
2136 return FAIL;
2137 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002138 vim_strncpy(namebuf, *arg, varlen);
2139 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002140
2141 *arg = skipwhite(*arg + varlen + 1);
2142 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002143 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002144
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002145 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002146 {
2147 int idx;
2148
2149 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002150 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002151 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002152 {
2153 res = generate_BCALL(cctx, idx, argcount);
2154 goto theend;
2155 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002156 semsg(_(e_unknownfunc), namebuf);
2157 }
2158
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002159 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002160 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002161 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002162 {
2163 res = generate_CALL(cctx, ufunc, argcount);
2164 goto theend;
2165 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002166
2167 // If the name is a variable, load it and use PCALL.
2168 p = namebuf;
2169 if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002170 {
2171 res = generate_PCALL(cctx, argcount, FALSE);
2172 goto theend;
2173 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002174
2175 // The function may be defined only later. Need to figure out at runtime.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002176 res = generate_UCALL(cctx, name, argcount);
2177
2178theend:
2179 vim_free(tofree);
2180 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002181}
2182
2183// like NAMESPACE_CHAR but with 'a' and 'l'.
2184#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2185
2186/*
2187 * Find the end of a variable or function name. Unlike find_name_end() this
2188 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002189 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002190 * Return a pointer to just after the name. Equal to "arg" if there is no
2191 * valid name.
2192 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002193 static char_u *
2194to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002195{
2196 char_u *p;
2197
2198 // Quick check for valid starting character.
2199 if (!eval_isnamec1(*arg))
2200 return arg;
2201
2202 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2203 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2204 // and can be used in slice "[n:]".
2205 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002206 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002207 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2208 break;
2209 return p;
2210}
2211
2212/*
2213 * Like to_name_end() but also skip over a list or dict constant.
2214 */
2215 char_u *
2216to_name_const_end(char_u *arg)
2217{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002218 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002219 typval_T rettv;
2220
2221 if (p == arg && *arg == '[')
2222 {
2223
2224 // Can be "[1, 2, 3]->Func()".
2225 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2226 p = arg;
2227 }
2228 else if (p == arg && *arg == '#' && arg[1] == '{')
2229 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002230 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002231 ++p;
2232 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2233 p = arg;
2234 }
2235 else if (p == arg && *arg == '{')
2236 {
2237 int ret = get_lambda_tv(&p, &rettv, FALSE);
2238
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002239 // Can be "{x -> ret}()".
2240 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002241 if (ret == NOTDONE)
2242 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2243 if (ret != OK)
2244 p = arg;
2245 }
2246
2247 return p;
2248}
2249
2250 static void
2251type_mismatch(type_T *expected, type_T *actual)
2252{
2253 char *tofree1, *tofree2;
2254
2255 semsg(_("E1013: type mismatch, expected %s but got %s"),
2256 type_name(expected, &tofree1), type_name(actual, &tofree2));
2257 vim_free(tofree1);
2258 vim_free(tofree2);
2259}
2260
2261/*
2262 * Check if the expected and actual types match.
2263 */
2264 static int
2265check_type(type_T *expected, type_T *actual, int give_msg)
2266{
2267 if (expected->tt_type != VAR_UNKNOWN)
2268 {
2269 if (expected->tt_type != actual->tt_type)
2270 {
2271 if (give_msg)
2272 type_mismatch(expected, actual);
2273 return FAIL;
2274 }
2275 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2276 {
Bram Moolenaar436472f2020-02-20 22:54:43 +01002277 int ret;
2278
2279 // void is used for an empty list or dict
2280 if (actual->tt_member == &t_void)
2281 ret = OK;
2282 else
2283 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002284 if (ret == FAIL && give_msg)
2285 type_mismatch(expected, actual);
2286 return ret;
2287 }
2288 }
2289 return OK;
2290}
2291
2292/*
2293 * Check that
2294 * - "actual" is "expected" type or
2295 * - "actual" is a type that can be "expected" type: add a runtime check; or
2296 * - return FAIL.
2297 */
2298 static int
2299need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2300{
Bram Moolenaar436472f2020-02-20 22:54:43 +01002301 if (check_type(expected, actual, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002302 return OK;
2303 if (actual->tt_type != VAR_UNKNOWN)
2304 {
2305 type_mismatch(expected, actual);
2306 return FAIL;
2307 }
2308 generate_TYPECHECK(cctx, expected, offset);
2309 return OK;
2310}
2311
2312/*
2313 * parse a list: [expr, expr]
2314 * "*arg" points to the '['.
2315 */
2316 static int
2317compile_list(char_u **arg, cctx_T *cctx)
2318{
2319 char_u *p = skipwhite(*arg + 1);
2320 int count = 0;
2321
2322 while (*p != ']')
2323 {
2324 if (*p == NUL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01002325 {
2326 semsg(_(e_list_end), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002327 return FAIL;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002328 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002329 if (compile_expr1(&p, cctx) == FAIL)
2330 break;
2331 ++count;
2332 if (*p == ',')
2333 ++p;
2334 p = skipwhite(p);
2335 }
2336 *arg = p + 1;
2337
2338 generate_NEWLIST(cctx, count);
2339 return OK;
2340}
2341
2342/*
2343 * parse a lambda: {arg, arg -> expr}
2344 * "*arg" points to the '{'.
2345 */
2346 static int
2347compile_lambda(char_u **arg, cctx_T *cctx)
2348{
2349 garray_T *instr = &cctx->ctx_instr;
2350 typval_T rettv;
2351 ufunc_T *ufunc;
2352
2353 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002354 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002355 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002356
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002357 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002358 ++ufunc->uf_refcount;
2359 clear_tv(&rettv);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002360
2361 // The function will have one line: "return {expr}".
2362 // Compile it into instructions.
2363 compile_def_function(ufunc, TRUE);
2364
2365 if (ufunc->uf_dfunc_idx >= 0)
2366 {
2367 if (ga_grow(instr, 1) == FAIL)
2368 return FAIL;
2369 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2370 return OK;
2371 }
2372 return FAIL;
2373}
2374
2375/*
2376 * Compile a lamda call: expr->{lambda}(args)
2377 * "arg" points to the "{".
2378 */
2379 static int
2380compile_lambda_call(char_u **arg, cctx_T *cctx)
2381{
2382 ufunc_T *ufunc;
2383 typval_T rettv;
2384 int argcount = 1;
2385 int ret = FAIL;
2386
2387 // Get the funcref in "rettv".
2388 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2389 return FAIL;
2390
2391 if (**arg != '(')
2392 {
2393 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002394 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395 else
2396 semsg(_(e_missing_paren), "lambda");
2397 clear_tv(&rettv);
2398 return FAIL;
2399 }
2400
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002401 ufunc = rettv.vval.v_partial->pt_func;
2402 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002403 clear_tv(&rettv);
2404
2405 // The function will have one line: "return {expr}".
2406 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002407 compile_def_function(ufunc, TRUE);
2408
2409 // compile the arguments
2410 *arg = skipwhite(*arg + 1);
2411 if (compile_arguments(arg, cctx, &argcount) == OK)
2412 // call the compiled function
2413 ret = generate_CALL(cctx, ufunc, argcount);
2414
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002415 return ret;
2416}
2417
2418/*
2419 * parse a dict: {'key': val} or #{key: val}
2420 * "*arg" points to the '{'.
2421 */
2422 static int
2423compile_dict(char_u **arg, cctx_T *cctx, int literal)
2424{
2425 garray_T *instr = &cctx->ctx_instr;
2426 int count = 0;
2427 dict_T *d = dict_alloc();
2428 dictitem_T *item;
2429
2430 if (d == NULL)
2431 return FAIL;
2432 *arg = skipwhite(*arg + 1);
2433 while (**arg != '}' && **arg != NUL)
2434 {
2435 char_u *key = NULL;
2436
2437 if (literal)
2438 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002439 char_u *p = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002440
2441 if (p == *arg)
2442 {
2443 semsg(_("E1014: Invalid key: %s"), *arg);
2444 return FAIL;
2445 }
2446 key = vim_strnsave(*arg, p - *arg);
2447 if (generate_PUSHS(cctx, key) == FAIL)
2448 return FAIL;
2449 *arg = p;
2450 }
2451 else
2452 {
2453 isn_T *isn;
2454
2455 if (compile_expr1(arg, cctx) == FAIL)
2456 return FAIL;
2457 // TODO: check type is string
2458 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2459 if (isn->isn_type == ISN_PUSHS)
2460 key = isn->isn_arg.string;
2461 }
2462
2463 // Check for duplicate keys, if using string keys.
2464 if (key != NULL)
2465 {
2466 item = dict_find(d, key, -1);
2467 if (item != NULL)
2468 {
2469 semsg(_(e_duplicate_key), key);
2470 goto failret;
2471 }
2472 item = dictitem_alloc(key);
2473 if (item != NULL)
2474 {
2475 item->di_tv.v_type = VAR_UNKNOWN;
2476 item->di_tv.v_lock = 0;
2477 if (dict_add(d, item) == FAIL)
2478 dictitem_free(item);
2479 }
2480 }
2481
2482 *arg = skipwhite(*arg);
2483 if (**arg != ':')
2484 {
2485 semsg(_(e_missing_dict_colon), *arg);
2486 return FAIL;
2487 }
2488
2489 *arg = skipwhite(*arg + 1);
2490 if (compile_expr1(arg, cctx) == FAIL)
2491 return FAIL;
2492 ++count;
2493
2494 if (**arg == '}')
2495 break;
2496 if (**arg != ',')
2497 {
2498 semsg(_(e_missing_dict_comma), *arg);
2499 goto failret;
2500 }
2501 *arg = skipwhite(*arg + 1);
2502 }
2503
2504 if (**arg != '}')
2505 {
2506 semsg(_(e_missing_dict_end), *arg);
2507 goto failret;
2508 }
2509 *arg = *arg + 1;
2510
2511 dict_unref(d);
2512 return generate_NEWDICT(cctx, count);
2513
2514failret:
2515 dict_unref(d);
2516 return FAIL;
2517}
2518
2519/*
2520 * Compile "&option".
2521 */
2522 static int
2523compile_get_option(char_u **arg, cctx_T *cctx)
2524{
2525 typval_T rettv;
2526 char_u *start = *arg;
2527 int ret;
2528
2529 // parse the option and get the current value to get the type.
2530 rettv.v_type = VAR_UNKNOWN;
2531 ret = get_option_tv(arg, &rettv, TRUE);
2532 if (ret == OK)
2533 {
2534 // include the '&' in the name, get_option_tv() expects it.
2535 char_u *name = vim_strnsave(start, *arg - start);
2536 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2537
2538 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2539 vim_free(name);
2540 }
2541 clear_tv(&rettv);
2542
2543 return ret;
2544}
2545
2546/*
2547 * Compile "$VAR".
2548 */
2549 static int
2550compile_get_env(char_u **arg, cctx_T *cctx)
2551{
2552 char_u *start = *arg;
2553 int len;
2554 int ret;
2555 char_u *name;
2556
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002557 ++*arg;
2558 len = get_env_len(arg);
2559 if (len == 0)
2560 {
2561 semsg(_(e_syntax_at), start - 1);
2562 return FAIL;
2563 }
2564
2565 // include the '$' in the name, get_env_tv() expects it.
2566 name = vim_strnsave(start, len + 1);
2567 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2568 vim_free(name);
2569 return ret;
2570}
2571
2572/*
2573 * Compile "@r".
2574 */
2575 static int
2576compile_get_register(char_u **arg, cctx_T *cctx)
2577{
2578 int ret;
2579
2580 ++*arg;
2581 if (**arg == NUL)
2582 {
2583 semsg(_(e_syntax_at), *arg - 1);
2584 return FAIL;
2585 }
2586 if (!valid_yank_reg(**arg, TRUE))
2587 {
2588 emsg_invreg(**arg);
2589 return FAIL;
2590 }
2591 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2592 ++*arg;
2593 return ret;
2594}
2595
2596/*
2597 * Apply leading '!', '-' and '+' to constant "rettv".
2598 */
2599 static int
2600apply_leader(typval_T *rettv, char_u *start, char_u *end)
2601{
2602 char_u *p = end;
2603
2604 // this works from end to start
2605 while (p > start)
2606 {
2607 --p;
2608 if (*p == '-' || *p == '+')
2609 {
2610 // only '-' has an effect, for '+' we only check the type
2611#ifdef FEAT_FLOAT
2612 if (rettv->v_type == VAR_FLOAT)
2613 {
2614 if (*p == '-')
2615 rettv->vval.v_float = -rettv->vval.v_float;
2616 }
2617 else
2618#endif
2619 {
2620 varnumber_T val;
2621 int error = FALSE;
2622
2623 // tv_get_number_chk() accepts a string, but we don't want that
2624 // here
2625 if (check_not_string(rettv) == FAIL)
2626 return FAIL;
2627 val = tv_get_number_chk(rettv, &error);
2628 clear_tv(rettv);
2629 if (error)
2630 return FAIL;
2631 if (*p == '-')
2632 val = -val;
2633 rettv->v_type = VAR_NUMBER;
2634 rettv->vval.v_number = val;
2635 }
2636 }
2637 else
2638 {
2639 int v = tv2bool(rettv);
2640
2641 // '!' is permissive in the type.
2642 clear_tv(rettv);
2643 rettv->v_type = VAR_BOOL;
2644 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
2645 }
2646 }
2647 return OK;
2648}
2649
2650/*
2651 * Recognize v: variables that are constants and set "rettv".
2652 */
2653 static void
2654get_vim_constant(char_u **arg, typval_T *rettv)
2655{
2656 if (STRNCMP(*arg, "v:true", 6) == 0)
2657 {
2658 rettv->v_type = VAR_BOOL;
2659 rettv->vval.v_number = VVAL_TRUE;
2660 *arg += 6;
2661 }
2662 else if (STRNCMP(*arg, "v:false", 7) == 0)
2663 {
2664 rettv->v_type = VAR_BOOL;
2665 rettv->vval.v_number = VVAL_FALSE;
2666 *arg += 7;
2667 }
2668 else if (STRNCMP(*arg, "v:null", 6) == 0)
2669 {
2670 rettv->v_type = VAR_SPECIAL;
2671 rettv->vval.v_number = VVAL_NULL;
2672 *arg += 6;
2673 }
2674 else if (STRNCMP(*arg, "v:none", 6) == 0)
2675 {
2676 rettv->v_type = VAR_SPECIAL;
2677 rettv->vval.v_number = VVAL_NONE;
2678 *arg += 6;
2679 }
2680}
2681
2682/*
2683 * Compile code to apply '-', '+' and '!'.
2684 */
2685 static int
2686compile_leader(cctx_T *cctx, char_u *start, char_u *end)
2687{
2688 char_u *p = end;
2689
2690 // this works from end to start
2691 while (p > start)
2692 {
2693 --p;
2694 if (*p == '-' || *p == '+')
2695 {
2696 int negate = *p == '-';
2697 isn_T *isn;
2698
2699 // TODO: check type
2700 while (p > start && (p[-1] == '-' || p[-1] == '+'))
2701 {
2702 --p;
2703 if (*p == '-')
2704 negate = !negate;
2705 }
2706 // only '-' has an effect, for '+' we only check the type
2707 if (negate)
2708 isn = generate_instr(cctx, ISN_NEGATENR);
2709 else
2710 isn = generate_instr(cctx, ISN_CHECKNR);
2711 if (isn == NULL)
2712 return FAIL;
2713 }
2714 else
2715 {
2716 int invert = TRUE;
2717
2718 while (p > start && p[-1] == '!')
2719 {
2720 --p;
2721 invert = !invert;
2722 }
2723 if (generate_2BOOL(cctx, invert) == FAIL)
2724 return FAIL;
2725 }
2726 }
2727 return OK;
2728}
2729
2730/*
2731 * Compile whatever comes after "name" or "name()".
2732 */
2733 static int
2734compile_subscript(
2735 char_u **arg,
2736 cctx_T *cctx,
2737 char_u **start_leader,
2738 char_u *end_leader)
2739{
2740 for (;;)
2741 {
2742 if (**arg == '(')
2743 {
2744 int argcount = 0;
2745
2746 // funcref(arg)
2747 *arg = skipwhite(*arg + 1);
2748 if (compile_arguments(arg, cctx, &argcount) == FAIL)
2749 return FAIL;
2750 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
2751 return FAIL;
2752 }
2753 else if (**arg == '-' && (*arg)[1] == '>')
2754 {
2755 char_u *p;
2756
2757 // something->method()
2758 // Apply the '!', '-' and '+' first:
2759 // -1.0->func() works like (-1.0)->func()
2760 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
2761 return FAIL;
2762 *start_leader = end_leader; // don't apply again later
2763
2764 *arg = skipwhite(*arg + 2);
2765 if (**arg == '{')
2766 {
2767 // lambda call: list->{lambda}
2768 if (compile_lambda_call(arg, cctx) == FAIL)
2769 return FAIL;
2770 }
2771 else
2772 {
2773 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02002774 p = *arg;
2775 if (ASCII_ISALPHA(*p) && p[1] == ':')
2776 p += 2;
2777 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002778 ;
2779 if (*p != '(')
2780 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02002781 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002782 return FAIL;
2783 }
2784 // TODO: base value may not be the first argument
2785 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
2786 return FAIL;
2787 }
2788 }
2789 else if (**arg == '[')
2790 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01002791 garray_T *stack;
2792 type_T **typep;
2793
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002794 // list index: list[123]
2795 // TODO: more arguments
2796 // TODO: dict member dict['name']
2797 *arg = skipwhite(*arg + 1);
2798 if (compile_expr1(arg, cctx) == FAIL)
2799 return FAIL;
2800
2801 if (**arg != ']')
2802 {
2803 emsg(_(e_missbrac));
2804 return FAIL;
2805 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01002806 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002807
2808 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
2809 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01002810 stack = &cctx->ctx_type_stack;
2811 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
2812 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
2813 {
2814 emsg(_(e_listreq));
2815 return FAIL;
2816 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01002817 if ((*typep)->tt_type == VAR_LIST)
2818 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002819 }
2820 else if (**arg == '.' && (*arg)[1] != '.')
2821 {
2822 char_u *p;
2823
2824 ++*arg;
2825 p = *arg;
2826 // dictionary member: dict.name
2827 if (eval_isnamec1(*p))
2828 while (eval_isnamec(*p))
2829 MB_PTR_ADV(p);
2830 if (p == *arg)
2831 {
2832 semsg(_(e_syntax_at), *arg);
2833 return FAIL;
2834 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002835 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
2836 return FAIL;
2837 *arg = p;
2838 }
2839 else
2840 break;
2841 }
2842
2843 // TODO - see handle_subscript():
2844 // Turn "dict.Func" into a partial for "Func" bound to "dict".
2845 // Don't do this when "Func" is already a partial that was bound
2846 // explicitly (pt_auto is FALSE).
2847
2848 return OK;
2849}
2850
2851/*
2852 * Compile an expression at "*p" and add instructions to "instr".
2853 * "p" is advanced until after the expression, skipping white space.
2854 *
2855 * This is the equivalent of eval1(), eval2(), etc.
2856 */
2857
2858/*
2859 * number number constant
2860 * 0zFFFFFFFF Blob constant
2861 * "string" string constant
2862 * 'string' literal string constant
2863 * &option-name option value
2864 * @r register contents
2865 * identifier variable value
2866 * function() function call
2867 * $VAR environment variable
2868 * (expression) nested expression
2869 * [expr, expr] List
2870 * {key: val, key: val} Dictionary
2871 * #{key: val, key: val} Dictionary with literal keys
2872 *
2873 * Also handle:
2874 * ! in front logical NOT
2875 * - in front unary minus
2876 * + in front unary plus (ignored)
2877 * trailing (arg) funcref/partial call
2878 * trailing [] subscript in String or List
2879 * trailing .name entry in Dictionary
2880 * trailing ->name() method call
2881 */
2882 static int
2883compile_expr7(char_u **arg, cctx_T *cctx)
2884{
2885 typval_T rettv;
2886 char_u *start_leader, *end_leader;
2887 int ret = OK;
2888
2889 /*
2890 * Skip '!', '-' and '+' characters. They are handled later.
2891 */
2892 start_leader = *arg;
2893 while (**arg == '!' || **arg == '-' || **arg == '+')
2894 *arg = skipwhite(*arg + 1);
2895 end_leader = *arg;
2896
2897 rettv.v_type = VAR_UNKNOWN;
2898 switch (**arg)
2899 {
2900 /*
2901 * Number constant.
2902 */
2903 case '0': // also for blob starting with 0z
2904 case '1':
2905 case '2':
2906 case '3':
2907 case '4':
2908 case '5':
2909 case '6':
2910 case '7':
2911 case '8':
2912 case '9':
2913 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
2914 return FAIL;
2915 break;
2916
2917 /*
2918 * String constant: "string".
2919 */
2920 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
2921 return FAIL;
2922 break;
2923
2924 /*
2925 * Literal string constant: 'str''ing'.
2926 */
2927 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
2928 return FAIL;
2929 break;
2930
2931 /*
2932 * Constant Vim variable.
2933 */
2934 case 'v': get_vim_constant(arg, &rettv);
2935 ret = NOTDONE;
2936 break;
2937
2938 /*
2939 * List: [expr, expr]
2940 */
2941 case '[': ret = compile_list(arg, cctx);
2942 break;
2943
2944 /*
2945 * Dictionary: #{key: val, key: val}
2946 */
2947 case '#': if ((*arg)[1] == '{')
2948 {
2949 ++*arg;
2950 ret = compile_dict(arg, cctx, TRUE);
2951 }
2952 else
2953 ret = NOTDONE;
2954 break;
2955
2956 /*
2957 * Lambda: {arg, arg -> expr}
2958 * Dictionary: {'key': val, 'key': val}
2959 */
2960 case '{': {
2961 char_u *start = skipwhite(*arg + 1);
2962
2963 // Find out what comes after the arguments.
2964 ret = get_function_args(&start, '-', NULL,
2965 NULL, NULL, NULL, TRUE);
2966 if (ret != FAIL && *start == '>')
2967 ret = compile_lambda(arg, cctx);
2968 else
2969 ret = compile_dict(arg, cctx, FALSE);
2970 }
2971 break;
2972
2973 /*
2974 * Option value: &name
2975 */
2976 case '&': ret = compile_get_option(arg, cctx);
2977 break;
2978
2979 /*
2980 * Environment variable: $VAR.
2981 */
2982 case '$': ret = compile_get_env(arg, cctx);
2983 break;
2984
2985 /*
2986 * Register contents: @r.
2987 */
2988 case '@': ret = compile_get_register(arg, cctx);
2989 break;
2990 /*
2991 * nested expression: (expression).
2992 */
2993 case '(': *arg = skipwhite(*arg + 1);
2994 ret = compile_expr1(arg, cctx); // recursive!
2995 *arg = skipwhite(*arg);
2996 if (**arg == ')')
2997 ++*arg;
2998 else if (ret == OK)
2999 {
3000 emsg(_(e_missing_close));
3001 ret = FAIL;
3002 }
3003 break;
3004
3005 default: ret = NOTDONE;
3006 break;
3007 }
3008 if (ret == FAIL)
3009 return FAIL;
3010
3011 if (rettv.v_type != VAR_UNKNOWN)
3012 {
3013 // apply the '!', '-' and '+' before the constant
3014 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3015 {
3016 clear_tv(&rettv);
3017 return FAIL;
3018 }
3019 start_leader = end_leader; // don't apply again below
3020
3021 // push constant
3022 switch (rettv.v_type)
3023 {
3024 case VAR_BOOL:
3025 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3026 break;
3027 case VAR_SPECIAL:
3028 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3029 break;
3030 case VAR_NUMBER:
3031 generate_PUSHNR(cctx, rettv.vval.v_number);
3032 break;
3033#ifdef FEAT_FLOAT
3034 case VAR_FLOAT:
3035 generate_PUSHF(cctx, rettv.vval.v_float);
3036 break;
3037#endif
3038 case VAR_BLOB:
3039 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3040 rettv.vval.v_blob = NULL;
3041 break;
3042 case VAR_STRING:
3043 generate_PUSHS(cctx, rettv.vval.v_string);
3044 rettv.vval.v_string = NULL;
3045 break;
3046 default:
3047 iemsg("constant type missing");
3048 return FAIL;
3049 }
3050 }
3051 else if (ret == NOTDONE)
3052 {
3053 char_u *p;
3054 int r;
3055
3056 if (!eval_isnamec1(**arg))
3057 {
3058 semsg(_("E1015: Name expected: %s"), *arg);
3059 return FAIL;
3060 }
3061
3062 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003063 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003064 if (*p == '(')
3065 r = compile_call(arg, p - *arg, cctx, 0);
3066 else
3067 r = compile_load(arg, p, cctx, TRUE);
3068 if (r == FAIL)
3069 return FAIL;
3070 }
3071
3072 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3073 return FAIL;
3074
3075 // Now deal with prefixed '-', '+' and '!', if not done already.
3076 return compile_leader(cctx, start_leader, end_leader);
3077}
3078
3079/*
3080 * * number multiplication
3081 * / number division
3082 * % number modulo
3083 */
3084 static int
3085compile_expr6(char_u **arg, cctx_T *cctx)
3086{
3087 char_u *op;
3088
3089 // get the first variable
3090 if (compile_expr7(arg, cctx) == FAIL)
3091 return FAIL;
3092
3093 /*
3094 * Repeat computing, until no "*", "/" or "%" is following.
3095 */
3096 for (;;)
3097 {
3098 op = skipwhite(*arg);
3099 if (*op != '*' && *op != '/' && *op != '%')
3100 break;
3101 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[1]))
3102 {
3103 char_u buf[3];
3104
3105 vim_strncpy(buf, op, 1);
3106 semsg(_(e_white_both), buf);
3107 }
3108 *arg = skipwhite(op + 1);
3109
3110 // get the second variable
3111 if (compile_expr7(arg, cctx) == FAIL)
3112 return FAIL;
3113
3114 generate_two_op(cctx, op);
3115 }
3116
3117 return OK;
3118}
3119
3120/*
3121 * + number addition
3122 * - number subtraction
3123 * .. string concatenation
3124 */
3125 static int
3126compile_expr5(char_u **arg, cctx_T *cctx)
3127{
3128 char_u *op;
3129 int oplen;
3130
3131 // get the first variable
3132 if (compile_expr6(arg, cctx) == FAIL)
3133 return FAIL;
3134
3135 /*
3136 * Repeat computing, until no "+", "-" or ".." is following.
3137 */
3138 for (;;)
3139 {
3140 op = skipwhite(*arg);
3141 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3142 break;
3143 oplen = (*op == '.' ? 2 : 1);
3144
3145 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[oplen]))
3146 {
3147 char_u buf[3];
3148
3149 vim_strncpy(buf, op, oplen);
3150 semsg(_(e_white_both), buf);
3151 }
3152
3153 *arg = skipwhite(op + oplen);
3154
3155 // get the second variable
3156 if (compile_expr6(arg, cctx) == FAIL)
3157 return FAIL;
3158
3159 if (*op == '.')
3160 {
3161 if (may_generate_2STRING(-2, cctx) == FAIL
3162 || may_generate_2STRING(-1, cctx) == FAIL)
3163 return FAIL;
3164 generate_instr_drop(cctx, ISN_CONCAT, 1);
3165 }
3166 else
3167 generate_two_op(cctx, op);
3168 }
3169
3170 return OK;
3171}
3172
Bram Moolenaar080457c2020-03-03 21:53:32 +01003173 static exptype_T
3174get_compare_type(char_u *p, int *len, int *type_is)
3175{
3176 exptype_T type = EXPR_UNKNOWN;
3177 int i;
3178
3179 switch (p[0])
3180 {
3181 case '=': if (p[1] == '=')
3182 type = EXPR_EQUAL;
3183 else if (p[1] == '~')
3184 type = EXPR_MATCH;
3185 break;
3186 case '!': if (p[1] == '=')
3187 type = EXPR_NEQUAL;
3188 else if (p[1] == '~')
3189 type = EXPR_NOMATCH;
3190 break;
3191 case '>': if (p[1] != '=')
3192 {
3193 type = EXPR_GREATER;
3194 *len = 1;
3195 }
3196 else
3197 type = EXPR_GEQUAL;
3198 break;
3199 case '<': if (p[1] != '=')
3200 {
3201 type = EXPR_SMALLER;
3202 *len = 1;
3203 }
3204 else
3205 type = EXPR_SEQUAL;
3206 break;
3207 case 'i': if (p[1] == 's')
3208 {
3209 // "is" and "isnot"; but not a prefix of a name
3210 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3211 *len = 5;
3212 i = p[*len];
3213 if (!isalnum(i) && i != '_')
3214 {
3215 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3216 *type_is = TRUE;
3217 }
3218 }
3219 break;
3220 }
3221 return type;
3222}
3223
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003224/*
3225 * expr5a == expr5b
3226 * expr5a =~ expr5b
3227 * expr5a != expr5b
3228 * expr5a !~ expr5b
3229 * expr5a > expr5b
3230 * expr5a >= expr5b
3231 * expr5a < expr5b
3232 * expr5a <= expr5b
3233 * expr5a is expr5b
3234 * expr5a isnot expr5b
3235 *
3236 * Produces instructions:
3237 * EVAL expr5a Push result of "expr5a"
3238 * EVAL expr5b Push result of "expr5b"
3239 * COMPARE one of the compare instructions
3240 */
3241 static int
3242compile_expr4(char_u **arg, cctx_T *cctx)
3243{
3244 exptype_T type = EXPR_UNKNOWN;
3245 char_u *p;
3246 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003247 int type_is = FALSE;
3248
3249 // get the first variable
3250 if (compile_expr5(arg, cctx) == FAIL)
3251 return FAIL;
3252
3253 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003254 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003255
3256 /*
3257 * If there is a comparative operator, use it.
3258 */
3259 if (type != EXPR_UNKNOWN)
3260 {
3261 int ic = FALSE; // Default: do not ignore case
3262
3263 if (type_is && (p[len] == '?' || p[len] == '#'))
3264 {
3265 semsg(_(e_invexpr2), *arg);
3266 return FAIL;
3267 }
3268 // extra question mark appended: ignore case
3269 if (p[len] == '?')
3270 {
3271 ic = TRUE;
3272 ++len;
3273 }
3274 // extra '#' appended: match case (ignored)
3275 else if (p[len] == '#')
3276 ++len;
3277 // nothing appended: match case
3278
3279 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[len]))
3280 {
3281 char_u buf[7];
3282
3283 vim_strncpy(buf, p, len);
3284 semsg(_(e_white_both), buf);
3285 }
3286
3287 // get the second variable
3288 *arg = skipwhite(p + len);
3289 if (compile_expr5(arg, cctx) == FAIL)
3290 return FAIL;
3291
3292 generate_COMPARE(cctx, type, ic);
3293 }
3294
3295 return OK;
3296}
3297
3298/*
3299 * Compile || or &&.
3300 */
3301 static int
3302compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3303{
3304 char_u *p = skipwhite(*arg);
3305 int opchar = *op;
3306
3307 if (p[0] == opchar && p[1] == opchar)
3308 {
3309 garray_T *instr = &cctx->ctx_instr;
3310 garray_T end_ga;
3311
3312 /*
3313 * Repeat until there is no following "||" or "&&"
3314 */
3315 ga_init2(&end_ga, sizeof(int), 10);
3316 while (p[0] == opchar && p[1] == opchar)
3317 {
3318 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
3319 semsg(_(e_white_both), op);
3320
3321 if (ga_grow(&end_ga, 1) == FAIL)
3322 {
3323 ga_clear(&end_ga);
3324 return FAIL;
3325 }
3326 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3327 ++end_ga.ga_len;
3328 generate_JUMP(cctx, opchar == '|'
3329 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3330
3331 // eval the next expression
3332 *arg = skipwhite(p + 2);
3333 if ((opchar == '|' ? compile_expr3(arg, cctx)
3334 : compile_expr4(arg, cctx)) == FAIL)
3335 {
3336 ga_clear(&end_ga);
3337 return FAIL;
3338 }
3339 p = skipwhite(*arg);
3340 }
3341
3342 // Fill in the end label in all jumps.
3343 while (end_ga.ga_len > 0)
3344 {
3345 isn_T *isn;
3346
3347 --end_ga.ga_len;
3348 isn = ((isn_T *)instr->ga_data)
3349 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3350 isn->isn_arg.jump.jump_where = instr->ga_len;
3351 }
3352 ga_clear(&end_ga);
3353 }
3354
3355 return OK;
3356}
3357
3358/*
3359 * expr4a && expr4a && expr4a logical AND
3360 *
3361 * Produces instructions:
3362 * EVAL expr4a Push result of "expr4a"
3363 * JUMP_AND_KEEP_IF_FALSE end
3364 * EVAL expr4b Push result of "expr4b"
3365 * JUMP_AND_KEEP_IF_FALSE end
3366 * EVAL expr4c Push result of "expr4c"
3367 * end:
3368 */
3369 static int
3370compile_expr3(char_u **arg, cctx_T *cctx)
3371{
3372 // get the first variable
3373 if (compile_expr4(arg, cctx) == FAIL)
3374 return FAIL;
3375
3376 // || and && work almost the same
3377 return compile_and_or(arg, cctx, "&&");
3378}
3379
3380/*
3381 * expr3a || expr3b || expr3c logical OR
3382 *
3383 * Produces instructions:
3384 * EVAL expr3a Push result of "expr3a"
3385 * JUMP_AND_KEEP_IF_TRUE end
3386 * EVAL expr3b Push result of "expr3b"
3387 * JUMP_AND_KEEP_IF_TRUE end
3388 * EVAL expr3c Push result of "expr3c"
3389 * end:
3390 */
3391 static int
3392compile_expr2(char_u **arg, cctx_T *cctx)
3393{
3394 // eval the first expression
3395 if (compile_expr3(arg, cctx) == FAIL)
3396 return FAIL;
3397
3398 // || and && work almost the same
3399 return compile_and_or(arg, cctx, "||");
3400}
3401
3402/*
3403 * Toplevel expression: expr2 ? expr1a : expr1b
3404 *
3405 * Produces instructions:
3406 * EVAL expr2 Push result of "expr"
3407 * JUMP_IF_FALSE alt jump if false
3408 * EVAL expr1a
3409 * JUMP_ALWAYS end
3410 * alt: EVAL expr1b
3411 * end:
3412 */
3413 static int
3414compile_expr1(char_u **arg, cctx_T *cctx)
3415{
3416 char_u *p;
3417
3418 // evaluate the first expression
3419 if (compile_expr2(arg, cctx) == FAIL)
3420 return FAIL;
3421
3422 p = skipwhite(*arg);
3423 if (*p == '?')
3424 {
3425 garray_T *instr = &cctx->ctx_instr;
3426 garray_T *stack = &cctx->ctx_type_stack;
3427 int alt_idx = instr->ga_len;
3428 int end_idx;
3429 isn_T *isn;
3430 type_T *type1;
3431 type_T *type2;
3432
3433 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3434 semsg(_(e_white_both), "?");
3435
3436 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3437
3438 // evaluate the second expression; any type is accepted
3439 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003440 if (compile_expr1(arg, cctx) == FAIL)
3441 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003442
3443 // remember the type and drop it
3444 --stack->ga_len;
3445 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3446
3447 end_idx = instr->ga_len;
3448 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3449
3450 // jump here from JUMP_IF_FALSE
3451 isn = ((isn_T *)instr->ga_data) + alt_idx;
3452 isn->isn_arg.jump.jump_where = instr->ga_len;
3453
3454 // Check for the ":".
3455 p = skipwhite(*arg);
3456 if (*p != ':')
3457 {
3458 emsg(_(e_missing_colon));
3459 return FAIL;
3460 }
3461 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3462 semsg(_(e_white_both), ":");
3463
3464 // evaluate the third expression
3465 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003466 if (compile_expr1(arg, cctx) == FAIL)
3467 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003468
3469 // If the types differ, the result has a more generic type.
3470 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003471 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003472
3473 // jump here from JUMP_ALWAYS
3474 isn = ((isn_T *)instr->ga_data) + end_idx;
3475 isn->isn_arg.jump.jump_where = instr->ga_len;
3476 }
3477 return OK;
3478}
3479
3480/*
3481 * compile "return [expr]"
3482 */
3483 static char_u *
3484compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3485{
3486 char_u *p = arg;
3487 garray_T *stack = &cctx->ctx_type_stack;
3488 type_T *stack_type;
3489
3490 if (*p != NUL && *p != '|' && *p != '\n')
3491 {
3492 // compile return argument into instructions
3493 if (compile_expr1(&p, cctx) == FAIL)
3494 return NULL;
3495
3496 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3497 if (set_return_type)
3498 cctx->ctx_ufunc->uf_ret_type = stack_type;
3499 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3500 == FAIL)
3501 return NULL;
3502 }
3503 else
3504 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003505 // "set_return_type" cannot be TRUE, only used for a lambda which
3506 // always has an argument.
3507 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003508 {
3509 emsg(_("E1003: Missing return value"));
3510 return NULL;
3511 }
3512
3513 // No argument, return zero.
3514 generate_PUSHNR(cctx, 0);
3515 }
3516
3517 if (generate_instr(cctx, ISN_RETURN) == NULL)
3518 return NULL;
3519
3520 // "return val | endif" is possible
3521 return skipwhite(p);
3522}
3523
3524/*
3525 * Return the length of an assignment operator, or zero if there isn't one.
3526 */
3527 int
3528assignment_len(char_u *p, int *heredoc)
3529{
3530 if (*p == '=')
3531 {
3532 if (p[1] == '<' && p[2] == '<')
3533 {
3534 *heredoc = TRUE;
3535 return 3;
3536 }
3537 return 1;
3538 }
3539 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3540 return 2;
3541 if (STRNCMP(p, "..=", 3) == 0)
3542 return 3;
3543 return 0;
3544}
3545
3546// words that cannot be used as a variable
3547static char *reserved[] = {
3548 "true",
3549 "false",
3550 NULL
3551};
3552
3553/*
3554 * Get a line for "=<<".
3555 * Return a pointer to the line in allocated memory.
3556 * Return NULL for end-of-file or some error.
3557 */
3558 static char_u *
3559heredoc_getline(
3560 int c UNUSED,
3561 void *cookie,
3562 int indent UNUSED,
3563 int do_concat UNUSED)
3564{
3565 cctx_T *cctx = (cctx_T *)cookie;
3566
3567 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003568 {
3569 iemsg("Heredoc got to end");
3570 return NULL;
3571 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003572 ++cctx->ctx_lnum;
3573 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3574 [cctx->ctx_lnum]);
3575}
3576
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003577typedef enum {
3578 dest_local,
3579 dest_option,
3580 dest_env,
3581 dest_global,
3582 dest_vimvar,
3583 dest_script,
3584 dest_reg,
3585} assign_dest_T;
3586
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003587/*
3588 * compile "let var [= expr]", "const var = expr" and "var = expr"
3589 * "arg" points to "var".
3590 */
3591 static char_u *
3592compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3593{
3594 char_u *p;
3595 char_u *ret = NULL;
3596 int var_count = 0;
3597 int semicolon = 0;
3598 size_t varlen;
3599 garray_T *instr = &cctx->ctx_instr;
3600 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02003601 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003602 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003603 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003604 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003605 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003606 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003607 int oplen = 0;
3608 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003609 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003610 lvar_T *lvar;
3611 char_u *name;
3612 char_u *sp;
3613 int has_type = FALSE;
3614 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
3615 int instr_count = -1;
3616
3617 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
3618 if (p == NULL)
3619 return NULL;
3620 if (var_count > 0)
3621 {
3622 // TODO: let [var, var] = list
3623 emsg("Cannot handle a list yet");
3624 return NULL;
3625 }
3626
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003627 // "a: type" is declaring variable "a" with a type, not "a:".
3628 if (is_decl && p == arg + 2 && p[-1] == ':')
3629 --p;
3630
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003631 varlen = p - arg;
3632 name = vim_strnsave(arg, (int)varlen);
3633 if (name == NULL)
3634 return NULL;
3635
Bram Moolenaar080457c2020-03-03 21:53:32 +01003636 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003637 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003638 if (*arg == '&')
3639 {
3640 int cc;
3641 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003642
Bram Moolenaar080457c2020-03-03 21:53:32 +01003643 dest = dest_option;
3644 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003645 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003646 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003647 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003648 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003649 if (is_decl)
3650 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003651 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003652 goto theend;
3653 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01003654 p = arg;
3655 p = find_option_end(&p, &opt_flags);
3656 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003657 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003658 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01003659 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003660 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003661 }
3662 cc = *p;
3663 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003664 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003665 *p = cc;
3666 if (opt_type == -3)
3667 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003668 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003669 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003670 }
3671 if (opt_type == -2 || opt_type == 0)
3672 type = &t_string;
3673 else
3674 type = &t_number; // both number and boolean option
3675 }
3676 else if (*arg == '$')
3677 {
3678 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003679 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003680 if (is_decl)
3681 {
3682 semsg(_("E1065: Cannot declare an environment variable: %s"), name);
3683 goto theend;
3684 }
3685 }
3686 else if (*arg == '@')
3687 {
3688 if (!valid_yank_reg(arg[1], TRUE))
3689 {
3690 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003691 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003692 }
3693 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003694 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003695 if (is_decl)
3696 {
3697 semsg(_("E1066: Cannot declare a register: %s"), name);
3698 goto theend;
3699 }
3700 }
3701 else if (STRNCMP(arg, "g:", 2) == 0)
3702 {
3703 dest = dest_global;
3704 if (is_decl)
3705 {
3706 semsg(_("E1016: Cannot declare a global variable: %s"), name);
3707 goto theend;
3708 }
3709 }
3710 else if (STRNCMP(arg, "v:", 2) == 0)
3711 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02003712 typval_T *vtv;
3713
Bram Moolenaar080457c2020-03-03 21:53:32 +01003714 vimvaridx = find_vim_var(name + 2);
3715 if (vimvaridx < 0)
3716 {
3717 semsg(_(e_var_notfound), arg);
3718 goto theend;
3719 }
3720 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003721 vtv = get_vim_var_tv(vimvaridx);
3722 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003723 if (is_decl)
3724 {
3725 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
3726 goto theend;
3727 }
3728 }
3729 else
3730 {
3731 for (idx = 0; reserved[idx] != NULL; ++idx)
3732 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003733 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003734 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003735 goto theend;
3736 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01003737
3738 idx = lookup_local(arg, varlen, cctx);
3739 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003740 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003741 if (is_decl)
3742 {
3743 semsg(_("E1017: Variable already declared: %s"), name);
3744 goto theend;
3745 }
3746 else
3747 {
3748 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3749 if (lvar->lv_const)
3750 {
3751 semsg(_("E1018: Cannot assign to a constant: %s"), name);
3752 goto theend;
3753 }
3754 }
3755 }
3756 else if (STRNCMP(arg, "s:", 2) == 0
3757 || lookup_script(arg, varlen) == OK
3758 || find_imported(arg, varlen, cctx) != NULL)
3759 {
3760 dest = dest_script;
3761 if (is_decl)
3762 {
3763 semsg(_("E1054: Variable already declared in the script: %s"),
3764 name);
3765 goto theend;
3766 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003767 }
3768 }
3769 }
3770
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003771 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003772 {
3773 if (is_decl && *p == ':')
3774 {
3775 // parse optional type: "let var: type = expr"
3776 p = skipwhite(p + 1);
3777 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003778 has_type = TRUE;
3779 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02003780 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003781 {
3782 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3783 type = lvar->lv_type;
3784 }
3785 }
3786
3787 sp = p;
3788 p = skipwhite(p);
3789 op = p;
3790 oplen = assignment_len(p, &heredoc);
3791 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
3792 {
3793 char_u buf[4];
3794
3795 vim_strncpy(buf, op, oplen);
3796 semsg(_(e_white_both), buf);
3797 }
3798
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003799 if (oplen == 3 && !heredoc && dest != dest_global
3800 && type->tt_type != VAR_STRING && type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003801 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01003802 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003803 goto theend;
3804 }
3805
3806 // +=, /=, etc. require an existing variable
Bram Moolenaar080457c2020-03-03 21:53:32 +01003807 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003808 {
3809 if (oplen > 1 && !heredoc)
3810 {
3811 semsg(_("E1020: cannot use an operator on a new variable: %s"),
3812 name);
3813 goto theend;
3814 }
3815
3816 // new local variable
3817 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
3818 if (idx < 0)
3819 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02003820 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003821 }
3822
3823 if (heredoc)
3824 {
3825 list_T *l;
3826 listitem_T *li;
3827
3828 // [let] varname =<< [trim] {end}
3829 eap->getline = heredoc_getline;
3830 eap->cookie = cctx;
3831 l = heredoc_get(eap, op + 3);
3832
3833 // Push each line and the create the list.
3834 for (li = l->lv_first; li != NULL; li = li->li_next)
3835 {
3836 generate_PUSHS(cctx, li->li_tv.vval.v_string);
3837 li->li_tv.vval.v_string = NULL;
3838 }
3839 generate_NEWLIST(cctx, l->lv_len);
3840 type = &t_list_string;
3841 list_free(l);
3842 p += STRLEN(p);
3843 }
3844 else if (oplen > 0)
3845 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02003846 int r;
3847 type_T *stacktype;
3848 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02003849
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003850 // for "+=", "*=", "..=" etc. first load the current value
3851 if (*op != '=')
3852 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003853 switch (dest)
3854 {
3855 case dest_option:
3856 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02003857 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003858 break;
3859 case dest_global:
3860 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
3861 break;
3862 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01003863 compile_load_scriptvar(cctx,
3864 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003865 break;
3866 case dest_env:
3867 // Include $ in the name here
3868 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
3869 break;
3870 case dest_reg:
3871 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
3872 break;
3873 case dest_vimvar:
3874 generate_LOADV(cctx, name + 2, TRUE);
3875 break;
3876 case dest_local:
3877 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
3878 break;
3879 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003880 }
3881
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02003882 // Compile the expression. Temporarily hide the new local variable
3883 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02003884 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02003885 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003886 instr_count = instr->ga_len;
3887 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02003888 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02003889 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02003890 ++cctx->ctx_locals.ga_len;
3891 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003892 goto theend;
3893
Bram Moolenaara8c17702020-04-01 21:17:24 +02003894 stack = &cctx->ctx_type_stack;
Bram Moolenaarea94fbe2020-04-01 22:36:49 +02003895 stacktype = stack->ga_len == 0 ? &t_void
3896 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003897 if (idx >= 0 && (is_decl || !has_type))
3898 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003899 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3900 if (!has_type)
3901 {
3902 if (stacktype->tt_type == VAR_VOID)
3903 {
3904 emsg(_("E1031: Cannot use void value"));
3905 goto theend;
3906 }
3907 else
3908 lvar->lv_type = stacktype;
3909 }
3910 else
3911 if (check_type(lvar->lv_type, stacktype, TRUE) == FAIL)
3912 goto theend;
3913 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02003914 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
3915 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003916 }
3917 else if (cmdidx == CMD_const)
3918 {
3919 emsg(_("E1021: const requires a value"));
3920 goto theend;
3921 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003922 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003923 {
3924 emsg(_("E1022: type or initialization required"));
3925 goto theend;
3926 }
3927 else
3928 {
3929 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003930 if (ga_grow(instr, 1) == FAIL)
3931 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01003932 switch (type->tt_type)
3933 {
3934 case VAR_BOOL:
3935 generate_PUSHBOOL(cctx, VVAL_FALSE);
3936 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01003937 case VAR_FLOAT:
3938#ifdef FEAT_FLOAT
3939 generate_PUSHF(cctx, 0.0);
3940#endif
3941 break;
3942 case VAR_STRING:
3943 generate_PUSHS(cctx, NULL);
3944 break;
3945 case VAR_BLOB:
3946 generate_PUSHBLOB(cctx, NULL);
3947 break;
3948 case VAR_FUNC:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003949 generate_PUSHFUNC(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01003950 break;
3951 case VAR_PARTIAL:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01003952 generate_PUSHPARTIAL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01003953 break;
3954 case VAR_LIST:
3955 generate_NEWLIST(cctx, 0);
3956 break;
3957 case VAR_DICT:
3958 generate_NEWDICT(cctx, 0);
3959 break;
3960 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003961 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01003962 break;
3963 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01003964 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01003965 break;
3966 case VAR_NUMBER:
3967 case VAR_UNKNOWN:
3968 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02003969 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01003970 generate_PUSHNR(cctx, 0);
3971 break;
3972 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003973 }
3974
3975 if (oplen > 0 && *op != '=')
3976 {
3977 type_T *expected = &t_number;
3978 garray_T *stack = &cctx->ctx_type_stack;
3979 type_T *stacktype;
3980
3981 // TODO: if type is known use float or any operation
3982
3983 if (*op == '.')
3984 expected = &t_string;
3985 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3986 if (need_type(stacktype, expected, -1, cctx) == FAIL)
3987 goto theend;
3988
3989 if (*op == '.')
3990 generate_instr_drop(cctx, ISN_CONCAT, 1);
3991 else
3992 {
3993 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
3994
3995 if (isn == NULL)
3996 goto theend;
3997 switch (*op)
3998 {
3999 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4000 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4001 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4002 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4003 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4004 }
4005 }
4006 }
4007
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004008 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004009 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004010 case dest_option:
4011 generate_STOREOPT(cctx, name + 1, opt_flags);
4012 break;
4013 case dest_global:
4014 // include g: with the name, easier to execute that way
4015 generate_STORE(cctx, ISN_STOREG, 0, name);
4016 break;
4017 case dest_env:
4018 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4019 break;
4020 case dest_reg:
4021 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4022 break;
4023 case dest_vimvar:
4024 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4025 break;
4026 case dest_script:
4027 {
4028 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4029 imported_T *import = NULL;
4030 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004031
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004032 if (name[1] != ':')
4033 {
4034 import = find_imported(name, 0, cctx);
4035 if (import != NULL)
4036 sid = import->imp_sid;
4037 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004038
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004039 idx = get_script_item_idx(sid, rawname, TRUE);
4040 // TODO: specific type
4041 if (idx < 0)
Bram Moolenaar0bbf7222020-02-19 22:31:48 +01004042 generate_OLDSCRIPT(cctx, ISN_STORES, name, sid, &t_any);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004043 else
4044 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4045 sid, idx, &t_any);
4046 }
4047 break;
4048 case dest_local:
4049 {
4050 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004051
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004052 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4053 // into ISN_STORENR
4054 if (instr->ga_len == instr_count + 1
4055 && isn->isn_type == ISN_PUSHNR)
4056 {
4057 varnumber_T val = isn->isn_arg.number;
4058 garray_T *stack = &cctx->ctx_type_stack;
4059
4060 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004061 isn->isn_arg.storenr.stnr_idx = idx;
4062 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004063 if (stack->ga_len > 0)
4064 --stack->ga_len;
4065 }
4066 else
4067 generate_STORE(cctx, ISN_STORE, idx, NULL);
4068 }
4069 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004070 }
4071 ret = p;
4072
4073theend:
4074 vim_free(name);
4075 return ret;
4076}
4077
4078/*
4079 * Compile an :import command.
4080 */
4081 static char_u *
4082compile_import(char_u *arg, cctx_T *cctx)
4083{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004084 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004085}
4086
4087/*
4088 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4089 */
4090 static int
4091compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4092{
4093 garray_T *instr = &cctx->ctx_instr;
4094 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4095
4096 if (endlabel == NULL)
4097 return FAIL;
4098 endlabel->el_next = *el;
4099 *el = endlabel;
4100 endlabel->el_end_label = instr->ga_len;
4101
4102 generate_JUMP(cctx, when, 0);
4103 return OK;
4104}
4105
4106 static void
4107compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4108{
4109 garray_T *instr = &cctx->ctx_instr;
4110
4111 while (*el != NULL)
4112 {
4113 endlabel_T *cur = (*el);
4114 isn_T *isn;
4115
4116 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4117 isn->isn_arg.jump.jump_where = instr->ga_len;
4118 *el = cur->el_next;
4119 vim_free(cur);
4120 }
4121}
4122
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004123 static void
4124compile_free_jump_to_end(endlabel_T **el)
4125{
4126 while (*el != NULL)
4127 {
4128 endlabel_T *cur = (*el);
4129
4130 *el = cur->el_next;
4131 vim_free(cur);
4132 }
4133}
4134
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004135/*
4136 * Create a new scope and set up the generic items.
4137 */
4138 static scope_T *
4139new_scope(cctx_T *cctx, scopetype_T type)
4140{
4141 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4142
4143 if (scope == NULL)
4144 return NULL;
4145 scope->se_outer = cctx->ctx_scope;
4146 cctx->ctx_scope = scope;
4147 scope->se_type = type;
4148 scope->se_local_count = cctx->ctx_locals.ga_len;
4149 return scope;
4150}
4151
4152/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004153 * Free the current scope and go back to the outer scope.
4154 */
4155 static void
4156drop_scope(cctx_T *cctx)
4157{
4158 scope_T *scope = cctx->ctx_scope;
4159
4160 if (scope == NULL)
4161 {
4162 iemsg("calling drop_scope() without a scope");
4163 return;
4164 }
4165 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004166 switch (scope->se_type)
4167 {
4168 case IF_SCOPE:
4169 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4170 case FOR_SCOPE:
4171 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4172 case WHILE_SCOPE:
4173 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4174 case TRY_SCOPE:
4175 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4176 case NO_SCOPE:
4177 case BLOCK_SCOPE:
4178 break;
4179 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004180 vim_free(scope);
4181}
4182
4183/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004184 * Evaluate an expression that is a constant:
4185 * has(arg)
4186 *
4187 * Also handle:
4188 * ! in front logical NOT
4189 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004190 * Return FAIL if the expression is not a constant.
4191 */
4192 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004193evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004194{
4195 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004196 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004197 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004198
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004199 /*
4200 * Skip '!' characters. They are handled later.
4201 */
4202 start_leader = *arg;
4203 while (**arg == '!')
4204 *arg = skipwhite(*arg + 1);
4205 end_leader = *arg;
4206
4207 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004208 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004209 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004210 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4211 {
4212 tv->v_type = VAR_SPECIAL;
4213 tv->vval.v_number = VVAL_TRUE;
4214 *arg += 4;
4215 return OK;
4216 }
4217 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4218 {
4219 tv->v_type = VAR_SPECIAL;
4220 tv->vval.v_number = VVAL_FALSE;
4221 *arg += 5;
4222 return OK;
4223 }
4224
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004225 if (STRNCMP("has(", *arg, 4) == 0)
4226 {
4227 has_call = TRUE;
4228 *arg = skipwhite(*arg + 4);
4229 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004230
4231 if (**arg == '"')
4232 {
4233 if (get_string_tv(arg, tv, TRUE) == FAIL)
4234 return FAIL;
4235 }
4236 else if (**arg == '\'')
4237 {
4238 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4239 return FAIL;
4240 }
4241 else
4242 return FAIL;
4243
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004244 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004245 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004246 *arg = skipwhite(*arg);
4247 if (**arg != ')')
4248 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004249 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004250
4251 argvars[0] = *tv;
4252 argvars[1].v_type = VAR_UNKNOWN;
4253 tv->v_type = VAR_NUMBER;
4254 tv->vval.v_number = 0;
4255 f_has(argvars, tv);
4256 clear_tv(&argvars[0]);
4257
4258 while (start_leader < end_leader)
4259 {
4260 if (*start_leader == '!')
4261 tv->vval.v_number = !tv->vval.v_number;
4262 ++start_leader;
4263 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004264 }
4265
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004266 return OK;
4267}
4268
Bram Moolenaar080457c2020-03-03 21:53:32 +01004269 static int
4270evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4271{
4272 exptype_T type = EXPR_UNKNOWN;
4273 char_u *p;
4274 int len = 2;
4275 int type_is = FALSE;
4276
4277 // get the first variable
4278 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4279 return FAIL;
4280
4281 p = skipwhite(*arg);
4282 type = get_compare_type(p, &len, &type_is);
4283
4284 /*
4285 * If there is a comparative operator, use it.
4286 */
4287 if (type != EXPR_UNKNOWN)
4288 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004289 typval_T tv2;
4290 char_u *s1, *s2;
4291 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4292 int n;
4293
4294 // TODO: Only string == string is supported now
4295 if (tv->v_type != VAR_STRING)
4296 return FAIL;
4297 if (type != EXPR_EQUAL)
4298 return FAIL;
4299
4300 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004301 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004302 *arg = skipwhite(p + len);
4303 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4304 || tv2.v_type != VAR_STRING)
4305 {
4306 clear_tv(&tv2);
4307 return FAIL;
4308 }
4309 s1 = tv_get_string_buf(tv, buf1);
4310 s2 = tv_get_string_buf(&tv2, buf2);
4311 n = STRCMP(s1, s2);
4312 clear_tv(tv);
4313 clear_tv(&tv2);
4314 tv->v_type = VAR_BOOL;
4315 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004316 }
4317
4318 return OK;
4319}
4320
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004321static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4322
4323/*
4324 * Compile constant || or &&.
4325 */
4326 static int
4327evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4328{
4329 char_u *p = skipwhite(*arg);
4330 int opchar = *op;
4331
4332 if (p[0] == opchar && p[1] == opchar)
4333 {
4334 int val = tv2bool(tv);
4335
4336 /*
4337 * Repeat until there is no following "||" or "&&"
4338 */
4339 while (p[0] == opchar && p[1] == opchar)
4340 {
4341 typval_T tv2;
4342
4343 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4344 return FAIL;
4345
4346 // eval the next expression
4347 *arg = skipwhite(p + 2);
4348 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004349 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004350 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004351 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004352 {
4353 clear_tv(&tv2);
4354 return FAIL;
4355 }
4356 if ((opchar == '&') == val)
4357 {
4358 // false || tv2 or true && tv2: use tv2
4359 clear_tv(tv);
4360 *tv = tv2;
4361 val = tv2bool(tv);
4362 }
4363 else
4364 clear_tv(&tv2);
4365 p = skipwhite(*arg);
4366 }
4367 }
4368
4369 return OK;
4370}
4371
4372/*
4373 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4374 * Return FAIL if the expression is not a constant.
4375 */
4376 static int
4377evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4378{
4379 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004380 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004381 return FAIL;
4382
4383 // || and && work almost the same
4384 return evaluate_const_and_or(arg, cctx, "&&", tv);
4385}
4386
4387/*
4388 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4389 * Return FAIL if the expression is not a constant.
4390 */
4391 static int
4392evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4393{
4394 // evaluate the first expression
4395 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4396 return FAIL;
4397
4398 // || and && work almost the same
4399 return evaluate_const_and_or(arg, cctx, "||", tv);
4400}
4401
4402/*
4403 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4404 * E.g. for "has('feature')".
4405 * This does not produce error messages. "tv" should be cleared afterwards.
4406 * Return FAIL if the expression is not a constant.
4407 */
4408 static int
4409evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4410{
4411 char_u *p;
4412
4413 // evaluate the first expression
4414 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4415 return FAIL;
4416
4417 p = skipwhite(*arg);
4418 if (*p == '?')
4419 {
4420 int val = tv2bool(tv);
4421 typval_T tv2;
4422
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004423 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004424 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4425 return FAIL;
4426
4427 // evaluate the second expression; any type is accepted
4428 clear_tv(tv);
4429 *arg = skipwhite(p + 1);
4430 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
4431 return FAIL;
4432
4433 // Check for the ":".
4434 p = skipwhite(*arg);
4435 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4436 return FAIL;
4437
4438 // evaluate the third expression
4439 *arg = skipwhite(p + 1);
4440 tv2.v_type = VAR_UNKNOWN;
4441 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
4442 {
4443 clear_tv(&tv2);
4444 return FAIL;
4445 }
4446 if (val)
4447 {
4448 // use the expr after "?"
4449 clear_tv(&tv2);
4450 }
4451 else
4452 {
4453 // use the expr after ":"
4454 clear_tv(tv);
4455 *tv = tv2;
4456 }
4457 }
4458 return OK;
4459}
4460
4461/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004462 * compile "if expr"
4463 *
4464 * "if expr" Produces instructions:
4465 * EVAL expr Push result of "expr"
4466 * JUMP_IF_FALSE end
4467 * ... body ...
4468 * end:
4469 *
4470 * "if expr | else" Produces instructions:
4471 * EVAL expr Push result of "expr"
4472 * JUMP_IF_FALSE else
4473 * ... body ...
4474 * JUMP_ALWAYS end
4475 * else:
4476 * ... body ...
4477 * end:
4478 *
4479 * "if expr1 | elseif expr2 | else" Produces instructions:
4480 * EVAL expr Push result of "expr"
4481 * JUMP_IF_FALSE elseif
4482 * ... body ...
4483 * JUMP_ALWAYS end
4484 * elseif:
4485 * EVAL expr Push result of "expr"
4486 * JUMP_IF_FALSE else
4487 * ... body ...
4488 * JUMP_ALWAYS end
4489 * else:
4490 * ... body ...
4491 * end:
4492 */
4493 static char_u *
4494compile_if(char_u *arg, cctx_T *cctx)
4495{
4496 char_u *p = arg;
4497 garray_T *instr = &cctx->ctx_instr;
4498 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004499 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004500
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004501 // compile "expr"; if we know it evaluates to FALSE skip the block
4502 tv.v_type = VAR_UNKNOWN;
4503 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4504 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4505 else
4506 cctx->ctx_skip = MAYBE;
4507 clear_tv(&tv);
4508 if (cctx->ctx_skip == MAYBE)
4509 {
4510 p = arg;
4511 if (compile_expr1(&p, cctx) == FAIL)
4512 return NULL;
4513 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004514
4515 scope = new_scope(cctx, IF_SCOPE);
4516 if (scope == NULL)
4517 return NULL;
4518
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004519 if (cctx->ctx_skip == MAYBE)
4520 {
4521 // "where" is set when ":elseif", "else" or ":endif" is found
4522 scope->se_u.se_if.is_if_label = instr->ga_len;
4523 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4524 }
4525 else
4526 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004527
4528 return p;
4529}
4530
4531 static char_u *
4532compile_elseif(char_u *arg, cctx_T *cctx)
4533{
4534 char_u *p = arg;
4535 garray_T *instr = &cctx->ctx_instr;
4536 isn_T *isn;
4537 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004538 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004539
4540 if (scope == NULL || scope->se_type != IF_SCOPE)
4541 {
4542 emsg(_(e_elseif_without_if));
4543 return NULL;
4544 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004545 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004546
Bram Moolenaar158906c2020-02-06 20:39:45 +01004547 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004548 {
4549 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004550 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004551 return NULL;
4552 // previous "if" or "elseif" jumps here
4553 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4554 isn->isn_arg.jump.jump_where = instr->ga_len;
4555 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004556
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004557 // compile "expr"; if we know it evaluates to FALSE skip the block
4558 tv.v_type = VAR_UNKNOWN;
4559 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4560 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4561 else
4562 cctx->ctx_skip = MAYBE;
4563 clear_tv(&tv);
4564 if (cctx->ctx_skip == MAYBE)
4565 {
4566 p = arg;
4567 if (compile_expr1(&p, cctx) == FAIL)
4568 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004569
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004570 // "where" is set when ":elseif", "else" or ":endif" is found
4571 scope->se_u.se_if.is_if_label = instr->ga_len;
4572 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4573 }
4574 else
4575 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004576
4577 return p;
4578}
4579
4580 static char_u *
4581compile_else(char_u *arg, cctx_T *cctx)
4582{
4583 char_u *p = arg;
4584 garray_T *instr = &cctx->ctx_instr;
4585 isn_T *isn;
4586 scope_T *scope = cctx->ctx_scope;
4587
4588 if (scope == NULL || scope->se_type != IF_SCOPE)
4589 {
4590 emsg(_(e_else_without_if));
4591 return NULL;
4592 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004593 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004594
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004595 // jump from previous block to the end, unless the else block is empty
4596 if (cctx->ctx_skip == MAYBE)
4597 {
4598 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004599 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004600 return NULL;
4601 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004602
Bram Moolenaar158906c2020-02-06 20:39:45 +01004603 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004604 {
4605 if (scope->se_u.se_if.is_if_label >= 0)
4606 {
4607 // previous "if" or "elseif" jumps here
4608 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4609 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01004610 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004611 }
4612 }
4613
4614 if (cctx->ctx_skip != MAYBE)
4615 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004616
4617 return p;
4618}
4619
4620 static char_u *
4621compile_endif(char_u *arg, cctx_T *cctx)
4622{
4623 scope_T *scope = cctx->ctx_scope;
4624 ifscope_T *ifscope;
4625 garray_T *instr = &cctx->ctx_instr;
4626 isn_T *isn;
4627
4628 if (scope == NULL || scope->se_type != IF_SCOPE)
4629 {
4630 emsg(_(e_endif_without_if));
4631 return NULL;
4632 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004633 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004634 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004635
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004636 if (scope->se_u.se_if.is_if_label >= 0)
4637 {
4638 // previous "if" or "elseif" jumps here
4639 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4640 isn->isn_arg.jump.jump_where = instr->ga_len;
4641 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004642 // Fill in the "end" label in jumps at the end of the blocks.
4643 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004644 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004645
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004646 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004647 return arg;
4648}
4649
4650/*
4651 * compile "for var in expr"
4652 *
4653 * Produces instructions:
4654 * PUSHNR -1
4655 * STORE loop-idx Set index to -1
4656 * EVAL expr Push result of "expr"
4657 * top: FOR loop-idx, end Increment index, use list on bottom of stack
4658 * - if beyond end, jump to "end"
4659 * - otherwise get item from list and push it
4660 * STORE var Store item in "var"
4661 * ... body ...
4662 * JUMP top Jump back to repeat
4663 * end: DROP Drop the result of "expr"
4664 *
4665 */
4666 static char_u *
4667compile_for(char_u *arg, cctx_T *cctx)
4668{
4669 char_u *p;
4670 size_t varlen;
4671 garray_T *instr = &cctx->ctx_instr;
4672 garray_T *stack = &cctx->ctx_type_stack;
4673 scope_T *scope;
4674 int loop_idx; // index of loop iteration variable
4675 int var_idx; // index of "var"
4676 type_T *vartype;
4677
4678 // TODO: list of variables: "for [key, value] in dict"
4679 // parse "var"
4680 for (p = arg; eval_isnamec1(*p); ++p)
4681 ;
4682 varlen = p - arg;
4683 var_idx = lookup_local(arg, varlen, cctx);
4684 if (var_idx >= 0)
4685 {
4686 semsg(_("E1023: variable already defined: %s"), arg);
4687 return NULL;
4688 }
4689
4690 // consume "in"
4691 p = skipwhite(p);
4692 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
4693 {
4694 emsg(_(e_missing_in));
4695 return NULL;
4696 }
4697 p = skipwhite(p + 2);
4698
4699
4700 scope = new_scope(cctx, FOR_SCOPE);
4701 if (scope == NULL)
4702 return NULL;
4703
4704 // Reserve a variable to store the loop iteration counter.
4705 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
4706 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004707 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004708 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004709 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004710 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004711 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004712
4713 // Reserve a variable to store "var"
4714 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
4715 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004716 {
4717 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004718 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004719 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004720
4721 generate_STORENR(cctx, loop_idx, -1);
4722
4723 // compile "expr", it remains on the stack until "endfor"
4724 arg = p;
4725 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004726 {
4727 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004728 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004729 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004730
4731 // now we know the type of "var"
4732 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4733 if (vartype->tt_type != VAR_LIST)
4734 {
4735 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004736 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004737 return NULL;
4738 }
4739 if (vartype->tt_member->tt_type != VAR_UNKNOWN)
4740 {
4741 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
4742
4743 lvar->lv_type = vartype->tt_member;
4744 }
4745
4746 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004747 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004748
4749 generate_FOR(cctx, loop_idx);
4750 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
4751
4752 return arg;
4753}
4754
4755/*
4756 * compile "endfor"
4757 */
4758 static char_u *
4759compile_endfor(char_u *arg, cctx_T *cctx)
4760{
4761 garray_T *instr = &cctx->ctx_instr;
4762 scope_T *scope = cctx->ctx_scope;
4763 forscope_T *forscope;
4764 isn_T *isn;
4765
4766 if (scope == NULL || scope->se_type != FOR_SCOPE)
4767 {
4768 emsg(_(e_for));
4769 return NULL;
4770 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004771 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004772 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004773 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004774
4775 // At end of ":for" scope jump back to the FOR instruction.
4776 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
4777
4778 // Fill in the "end" label in the FOR statement so it can jump here
4779 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
4780 isn->isn_arg.forloop.for_end = instr->ga_len;
4781
4782 // Fill in the "end" label any BREAK statements
4783 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
4784
4785 // Below the ":for" scope drop the "expr" list from the stack.
4786 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
4787 return NULL;
4788
4789 vim_free(scope);
4790
4791 return arg;
4792}
4793
4794/*
4795 * compile "while expr"
4796 *
4797 * Produces instructions:
4798 * top: EVAL expr Push result of "expr"
4799 * JUMP_IF_FALSE end jump if false
4800 * ... body ...
4801 * JUMP top Jump back to repeat
4802 * end:
4803 *
4804 */
4805 static char_u *
4806compile_while(char_u *arg, cctx_T *cctx)
4807{
4808 char_u *p = arg;
4809 garray_T *instr = &cctx->ctx_instr;
4810 scope_T *scope;
4811
4812 scope = new_scope(cctx, WHILE_SCOPE);
4813 if (scope == NULL)
4814 return NULL;
4815
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004816 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004817
4818 // compile "expr"
4819 if (compile_expr1(&p, cctx) == FAIL)
4820 return NULL;
4821
4822 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004823 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004824 JUMP_IF_FALSE, cctx) == FAIL)
4825 return FAIL;
4826
4827 return p;
4828}
4829
4830/*
4831 * compile "endwhile"
4832 */
4833 static char_u *
4834compile_endwhile(char_u *arg, cctx_T *cctx)
4835{
4836 scope_T *scope = cctx->ctx_scope;
4837
4838 if (scope == NULL || scope->se_type != WHILE_SCOPE)
4839 {
4840 emsg(_(e_while));
4841 return NULL;
4842 }
4843 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004844 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004845
4846 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004847 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004848
4849 // Fill in the "end" label in the WHILE statement so it can jump here.
4850 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004851 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004852
4853 vim_free(scope);
4854
4855 return arg;
4856}
4857
4858/*
4859 * compile "continue"
4860 */
4861 static char_u *
4862compile_continue(char_u *arg, cctx_T *cctx)
4863{
4864 scope_T *scope = cctx->ctx_scope;
4865
4866 for (;;)
4867 {
4868 if (scope == NULL)
4869 {
4870 emsg(_(e_continue));
4871 return NULL;
4872 }
4873 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
4874 break;
4875 scope = scope->se_outer;
4876 }
4877
4878 // Jump back to the FOR or WHILE instruction.
4879 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004880 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
4881 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004882 return arg;
4883}
4884
4885/*
4886 * compile "break"
4887 */
4888 static char_u *
4889compile_break(char_u *arg, cctx_T *cctx)
4890{
4891 scope_T *scope = cctx->ctx_scope;
4892 endlabel_T **el;
4893
4894 for (;;)
4895 {
4896 if (scope == NULL)
4897 {
4898 emsg(_(e_break));
4899 return NULL;
4900 }
4901 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
4902 break;
4903 scope = scope->se_outer;
4904 }
4905
4906 // Jump to the end of the FOR or WHILE loop.
4907 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004908 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004909 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004910 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004911 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
4912 return FAIL;
4913
4914 return arg;
4915}
4916
4917/*
4918 * compile "{" start of block
4919 */
4920 static char_u *
4921compile_block(char_u *arg, cctx_T *cctx)
4922{
4923 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
4924 return NULL;
4925 return skipwhite(arg + 1);
4926}
4927
4928/*
4929 * compile end of block: drop one scope
4930 */
4931 static void
4932compile_endblock(cctx_T *cctx)
4933{
4934 scope_T *scope = cctx->ctx_scope;
4935
4936 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004937 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004938 vim_free(scope);
4939}
4940
4941/*
4942 * compile "try"
4943 * Creates a new scope for the try-endtry, pointing to the first catch and
4944 * finally.
4945 * Creates another scope for the "try" block itself.
4946 * TRY instruction sets up exception handling at runtime.
4947 *
4948 * "try"
4949 * TRY -> catch1, -> finally push trystack entry
4950 * ... try block
4951 * "throw {exception}"
4952 * EVAL {exception}
4953 * THROW create exception
4954 * ... try block
4955 * " catch {expr}"
4956 * JUMP -> finally
4957 * catch1: PUSH exeception
4958 * EVAL {expr}
4959 * MATCH
4960 * JUMP nomatch -> catch2
4961 * CATCH remove exception
4962 * ... catch block
4963 * " catch"
4964 * JUMP -> finally
4965 * catch2: CATCH remove exception
4966 * ... catch block
4967 * " finally"
4968 * finally:
4969 * ... finally block
4970 * " endtry"
4971 * ENDTRY pop trystack entry, may rethrow
4972 */
4973 static char_u *
4974compile_try(char_u *arg, cctx_T *cctx)
4975{
4976 garray_T *instr = &cctx->ctx_instr;
4977 scope_T *try_scope;
4978 scope_T *scope;
4979
4980 // scope that holds the jumps that go to catch/finally/endtry
4981 try_scope = new_scope(cctx, TRY_SCOPE);
4982 if (try_scope == NULL)
4983 return NULL;
4984
4985 // "catch" is set when the first ":catch" is found.
4986 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004987 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004988 if (generate_instr(cctx, ISN_TRY) == NULL)
4989 return NULL;
4990
4991 // scope for the try block itself
4992 scope = new_scope(cctx, BLOCK_SCOPE);
4993 if (scope == NULL)
4994 return NULL;
4995
4996 return arg;
4997}
4998
4999/*
5000 * compile "catch {expr}"
5001 */
5002 static char_u *
5003compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5004{
5005 scope_T *scope = cctx->ctx_scope;
5006 garray_T *instr = &cctx->ctx_instr;
5007 char_u *p;
5008 isn_T *isn;
5009
5010 // end block scope from :try or :catch
5011 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5012 compile_endblock(cctx);
5013 scope = cctx->ctx_scope;
5014
5015 // Error if not in a :try scope
5016 if (scope == NULL || scope->se_type != TRY_SCOPE)
5017 {
5018 emsg(_(e_catch));
5019 return NULL;
5020 }
5021
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005022 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005023 {
5024 emsg(_("E1033: catch unreachable after catch-all"));
5025 return NULL;
5026 }
5027
5028 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005029 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005030 JUMP_ALWAYS, cctx) == FAIL)
5031 return NULL;
5032
5033 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005034 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005035 if (isn->isn_arg.try.try_catch == 0)
5036 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005037 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005038 {
5039 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005040 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005041 isn->isn_arg.jump.jump_where = instr->ga_len;
5042 }
5043
5044 p = skipwhite(arg);
5045 if (ends_excmd(*p))
5046 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005047 scope->se_u.se_try.ts_caught_all = TRUE;
5048 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005049 }
5050 else
5051 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005052 char_u *end;
5053 char_u *pat;
5054 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005055 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005056 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005057
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005058 // Push v:exception, push {expr} and MATCH
5059 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5060
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005061 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005062 if (*end != *p)
5063 {
5064 semsg(_("E1067: Separator mismatch: %s"), p);
5065 vim_free(tofree);
5066 return FAIL;
5067 }
5068 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005069 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005070 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005071 len = (int)(end - tofree);
5072 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005073 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005074 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005075 if (pat == NULL)
5076 return FAIL;
5077 if (generate_PUSHS(cctx, pat) == FAIL)
5078 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005079
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005080 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5081 return NULL;
5082
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005083 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005084 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5085 return NULL;
5086 }
5087
5088 if (generate_instr(cctx, ISN_CATCH) == NULL)
5089 return NULL;
5090
5091 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5092 return NULL;
5093 return p;
5094}
5095
5096 static char_u *
5097compile_finally(char_u *arg, cctx_T *cctx)
5098{
5099 scope_T *scope = cctx->ctx_scope;
5100 garray_T *instr = &cctx->ctx_instr;
5101 isn_T *isn;
5102
5103 // end block scope from :try or :catch
5104 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5105 compile_endblock(cctx);
5106 scope = cctx->ctx_scope;
5107
5108 // Error if not in a :try scope
5109 if (scope == NULL || scope->se_type != TRY_SCOPE)
5110 {
5111 emsg(_(e_finally));
5112 return NULL;
5113 }
5114
5115 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005116 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005117 if (isn->isn_arg.try.try_finally != 0)
5118 {
5119 emsg(_(e_finally_dup));
5120 return NULL;
5121 }
5122
5123 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005124 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005125
Bram Moolenaar585fea72020-04-02 22:33:21 +02005126 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005127 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005128 {
5129 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005130 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005131 isn->isn_arg.jump.jump_where = instr->ga_len;
5132 }
5133
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005134 // TODO: set index in ts_finally_label jumps
5135
5136 return arg;
5137}
5138
5139 static char_u *
5140compile_endtry(char_u *arg, cctx_T *cctx)
5141{
5142 scope_T *scope = cctx->ctx_scope;
5143 garray_T *instr = &cctx->ctx_instr;
5144 isn_T *isn;
5145
5146 // end block scope from :catch or :finally
5147 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5148 compile_endblock(cctx);
5149 scope = cctx->ctx_scope;
5150
5151 // Error if not in a :try scope
5152 if (scope == NULL || scope->se_type != TRY_SCOPE)
5153 {
5154 if (scope == NULL)
5155 emsg(_(e_no_endtry));
5156 else if (scope->se_type == WHILE_SCOPE)
5157 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005158 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005159 emsg(_(e_endfor));
5160 else
5161 emsg(_(e_endif));
5162 return NULL;
5163 }
5164
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005165 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005166 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5167 {
5168 emsg(_("E1032: missing :catch or :finally"));
5169 return NULL;
5170 }
5171
5172 // Fill in the "end" label in jumps at the end of the blocks, if not done
5173 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005174 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005175
5176 // End :catch or :finally scope: set value in ISN_TRY instruction
5177 if (isn->isn_arg.try.try_finally == 0)
5178 isn->isn_arg.try.try_finally = instr->ga_len;
5179 compile_endblock(cctx);
5180
5181 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5182 return NULL;
5183 return arg;
5184}
5185
5186/*
5187 * compile "throw {expr}"
5188 */
5189 static char_u *
5190compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5191{
5192 char_u *p = skipwhite(arg);
5193
5194 if (ends_excmd(*p))
5195 {
5196 emsg(_(e_argreq));
5197 return NULL;
5198 }
5199 if (compile_expr1(&p, cctx) == FAIL)
5200 return NULL;
5201 if (may_generate_2STRING(-1, cctx) == FAIL)
5202 return NULL;
5203 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5204 return NULL;
5205
5206 return p;
5207}
5208
5209/*
5210 * compile "echo expr"
5211 */
5212 static char_u *
5213compile_echo(char_u *arg, int with_white, cctx_T *cctx)
5214{
5215 char_u *p = arg;
5216 int count = 0;
5217
Bram Moolenaarad39c092020-02-26 18:23:43 +01005218 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005219 {
5220 if (compile_expr1(&p, cctx) == FAIL)
5221 return NULL;
5222 ++count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005223 p = skipwhite(p);
5224 if (ends_excmd(*p))
5225 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005226 }
5227
5228 generate_ECHO(cctx, with_white, count);
Bram Moolenaarad39c092020-02-26 18:23:43 +01005229 return p;
5230}
5231
5232/*
5233 * compile "execute expr"
5234 */
5235 static char_u *
5236compile_execute(char_u *arg, cctx_T *cctx)
5237{
5238 char_u *p = arg;
5239 int count = 0;
5240
5241 for (;;)
5242 {
5243 if (compile_expr1(&p, cctx) == FAIL)
5244 return NULL;
5245 ++count;
5246 p = skipwhite(p);
5247 if (ends_excmd(*p))
5248 break;
5249 }
5250
5251 generate_EXECUTE(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005252
5253 return p;
5254}
5255
5256/*
5257 * After ex_function() has collected all the function lines: parse and compile
5258 * the lines into instructions.
5259 * Adds the function to "def_functions".
5260 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5261 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005262 * This can be used recursively through compile_lambda(), which may reallocate
5263 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005264 */
5265 void
5266compile_def_function(ufunc_T *ufunc, int set_return_type)
5267{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005268 char_u *line = NULL;
5269 char_u *p;
5270 exarg_T ea;
5271 char *errormsg = NULL; // error message
5272 int had_return = FALSE;
5273 cctx_T cctx;
5274 garray_T *instr;
5275 int called_emsg_before = called_emsg;
5276 int ret = FAIL;
5277 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005278 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005279
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005280 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005281 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005282
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005283 if (ufunc->uf_dfunc_idx >= 0)
5284 {
5285 // Redefining a function that was compiled before.
5286 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5287
5288 // Free old instructions.
5289 delete_def_function_contents(dfunc);
5290 }
5291 else
5292 {
5293 // Add the function to "def_functions".
5294 if (ga_grow(&def_functions, 1) == FAIL)
5295 return;
5296 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
5297 vim_memset(dfunc, 0, sizeof(dfunc_T));
5298 dfunc->df_idx = def_functions.ga_len;
5299 ufunc->uf_dfunc_idx = dfunc->df_idx;
5300 dfunc->df_ufunc = ufunc;
5301 ++def_functions.ga_len;
5302 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005303 }
5304
5305 vim_memset(&cctx, 0, sizeof(cctx));
5306 cctx.ctx_ufunc = ufunc;
5307 cctx.ctx_lnum = -1;
5308 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5309 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5310 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5311 cctx.ctx_type_list = &ufunc->uf_type_list;
5312 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5313 instr = &cctx.ctx_instr;
5314
5315 // Most modern script version.
5316 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5317
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005318 if (ufunc->uf_def_args.ga_len > 0)
5319 {
5320 int count = ufunc->uf_def_args.ga_len;
5321 int i;
5322 char_u *arg;
5323 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5324
5325 // Produce instructions for the default values of optional arguments.
5326 // Store the instruction index in uf_def_arg_idx[] so that we know
5327 // where to start when the function is called, depending on the number
5328 // of arguments.
5329 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5330 if (ufunc->uf_def_arg_idx == NULL)
5331 goto erret;
5332 for (i = 0; i < count; ++i)
5333 {
5334 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5335 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
5336 if (compile_expr1(&arg, &cctx) == FAIL
5337 || generate_STORE(&cctx, ISN_STORE,
5338 i - count - off, NULL) == FAIL)
5339 goto erret;
5340 }
5341
5342 // If a varargs is following, push an empty list.
5343 if (ufunc->uf_va_name != NULL)
5344 {
5345 if (generate_NEWLIST(&cctx, 0) == FAIL
5346 || generate_STORE(&cctx, ISN_STORE, -off, NULL) == FAIL)
5347 goto erret;
5348 }
5349
5350 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5351 }
5352
5353 /*
5354 * Loop over all the lines of the function and generate instructions.
5355 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005356 for (;;)
5357 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005358 int is_ex_command;
5359
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005360 if (line != NULL && *line == '|')
5361 // the line continues after a '|'
5362 ++line;
5363 else if (line != NULL && *line != NUL)
5364 {
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005365 if (emsg_before == called_emsg)
5366 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005367 goto erret;
5368 }
5369 else
5370 {
5371 do
5372 {
5373 ++cctx.ctx_lnum;
5374 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
5375 break;
5376 line = ((char_u **)ufunc->uf_lines.ga_data)[cctx.ctx_lnum];
5377 } while (line == NULL);
5378 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
5379 break;
5380 SOURCING_LNUM = ufunc->uf_script_ctx.sc_lnum + cctx.ctx_lnum + 1;
5381 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005382 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005383
5384 had_return = FALSE;
5385 vim_memset(&ea, 0, sizeof(ea));
5386 ea.cmdlinep = &line;
5387 ea.cmd = skipwhite(line);
5388
5389 // "}" ends a block scope
5390 if (*ea.cmd == '}')
5391 {
5392 scopetype_T stype = cctx.ctx_scope == NULL
5393 ? NO_SCOPE : cctx.ctx_scope->se_type;
5394
5395 if (stype == BLOCK_SCOPE)
5396 {
5397 compile_endblock(&cctx);
5398 line = ea.cmd;
5399 }
5400 else
5401 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005402 emsg(_("E1025: using } outside of a block scope"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005403 goto erret;
5404 }
5405 if (line != NULL)
5406 line = skipwhite(ea.cmd + 1);
5407 continue;
5408 }
5409
5410 // "{" starts a block scope
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01005411 // "{'a': 1}->func() is something else
5412 if (*ea.cmd == '{' && ends_excmd(*skipwhite(ea.cmd + 1)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005413 {
5414 line = compile_block(ea.cmd, &cctx);
5415 continue;
5416 }
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005417 is_ex_command = *ea.cmd == ':';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005418
5419 /*
5420 * COMMAND MODIFIERS
5421 */
5422 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
5423 {
5424 if (errormsg != NULL)
5425 goto erret;
5426 // empty line or comment
5427 line = (char_u *)"";
5428 continue;
5429 }
5430
5431 // Skip ":call" to get to the function name.
5432 if (checkforcmd(&ea.cmd, "call", 3))
5433 ea.cmd = skipwhite(ea.cmd);
5434
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005435 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005436 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005437 // Assuming the command starts with a variable or function name,
5438 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
5439 // val".
5440 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
5441 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005442 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02005443 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005444 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005445 int oplen;
5446 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005447
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005448 oplen = assignment_len(skipwhite(p), &heredoc);
5449 if (oplen > 0)
5450 {
5451 // Recognize an assignment if we recognize the variable
5452 // name:
5453 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005454 // "local = expr" where "local" is a local var.
5455 // "script = expr" where "script" is a script-local var.
5456 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005457 // "&opt = expr"
5458 // "$ENV = expr"
5459 // "@r = expr"
5460 if (*ea.cmd == '&'
5461 || *ea.cmd == '$'
5462 || *ea.cmd == '@'
5463 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
5464 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
5465 || lookup_script(ea.cmd, p - ea.cmd) == OK
5466 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
5467 {
5468 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
5469 if (line == NULL)
5470 goto erret;
5471 continue;
5472 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005473 }
5474 }
5475 }
5476
5477 /*
5478 * COMMAND after range
5479 */
5480 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005481 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
5482 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005483
5484 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
5485 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005486 if (cctx.ctx_skip == TRUE)
5487 {
5488 line += STRLEN(line);
5489 continue;
5490 }
5491
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005492 // Expression or function call.
5493 if (ea.cmdidx == CMD_eval)
5494 {
5495 p = ea.cmd;
5496 if (compile_expr1(&p, &cctx) == FAIL)
5497 goto erret;
5498
5499 // drop the return value
5500 generate_instr_drop(&cctx, ISN_DROP, 1);
5501 line = p;
5502 continue;
5503 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02005504 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005505 iemsg("Command from find_ex_command() not handled");
5506 goto erret;
5507 }
5508
5509 p = skipwhite(p);
5510
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005511 if (cctx.ctx_skip == TRUE
5512 && ea.cmdidx != CMD_elseif
5513 && ea.cmdidx != CMD_else
5514 && ea.cmdidx != CMD_endif)
5515 {
5516 line += STRLEN(line);
5517 continue;
5518 }
5519
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005520 switch (ea.cmdidx)
5521 {
5522 case CMD_def:
5523 case CMD_function:
5524 // TODO: Nested function
5525 emsg("Nested function not implemented yet");
5526 goto erret;
5527
5528 case CMD_return:
5529 line = compile_return(p, set_return_type, &cctx);
5530 had_return = TRUE;
5531 break;
5532
5533 case CMD_let:
5534 case CMD_const:
5535 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
5536 break;
5537
5538 case CMD_import:
5539 line = compile_import(p, &cctx);
5540 break;
5541
5542 case CMD_if:
5543 line = compile_if(p, &cctx);
5544 break;
5545 case CMD_elseif:
5546 line = compile_elseif(p, &cctx);
5547 break;
5548 case CMD_else:
5549 line = compile_else(p, &cctx);
5550 break;
5551 case CMD_endif:
5552 line = compile_endif(p, &cctx);
5553 break;
5554
5555 case CMD_while:
5556 line = compile_while(p, &cctx);
5557 break;
5558 case CMD_endwhile:
5559 line = compile_endwhile(p, &cctx);
5560 break;
5561
5562 case CMD_for:
5563 line = compile_for(p, &cctx);
5564 break;
5565 case CMD_endfor:
5566 line = compile_endfor(p, &cctx);
5567 break;
5568 case CMD_continue:
5569 line = compile_continue(p, &cctx);
5570 break;
5571 case CMD_break:
5572 line = compile_break(p, &cctx);
5573 break;
5574
5575 case CMD_try:
5576 line = compile_try(p, &cctx);
5577 break;
5578 case CMD_catch:
5579 line = compile_catch(p, &cctx);
5580 break;
5581 case CMD_finally:
5582 line = compile_finally(p, &cctx);
5583 break;
5584 case CMD_endtry:
5585 line = compile_endtry(p, &cctx);
5586 break;
5587 case CMD_throw:
5588 line = compile_throw(p, &cctx);
5589 break;
5590
5591 case CMD_echo:
5592 line = compile_echo(p, TRUE, &cctx);
5593 break;
5594 case CMD_echon:
5595 line = compile_echo(p, FALSE, &cctx);
5596 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005597 case CMD_execute:
5598 line = compile_execute(p, &cctx);
5599 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005600
5601 default:
5602 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01005603 // TODO:
5604 // CMD_echomsg
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01005605 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005606 generate_EXEC(&cctx, line);
5607 line = (char_u *)"";
5608 break;
5609 }
5610 if (line == NULL)
5611 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02005612 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005613
5614 if (cctx.ctx_type_stack.ga_len < 0)
5615 {
5616 iemsg("Type stack underflow");
5617 goto erret;
5618 }
5619 }
5620
5621 if (cctx.ctx_scope != NULL)
5622 {
5623 if (cctx.ctx_scope->se_type == IF_SCOPE)
5624 emsg(_(e_endif));
5625 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
5626 emsg(_(e_endwhile));
5627 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
5628 emsg(_(e_endfor));
5629 else
5630 emsg(_("E1026: Missing }"));
5631 goto erret;
5632 }
5633
5634 if (!had_return)
5635 {
5636 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
5637 {
5638 emsg(_("E1027: Missing return statement"));
5639 goto erret;
5640 }
5641
5642 // Return zero if there is no return at the end.
5643 generate_PUSHNR(&cctx, 0);
5644 generate_instr(&cctx, ISN_RETURN);
5645 }
5646
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005647 {
5648 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5649 + ufunc->uf_dfunc_idx;
5650 dfunc->df_deleted = FALSE;
5651 dfunc->df_instr = instr->ga_data;
5652 dfunc->df_instr_count = instr->ga_len;
5653 dfunc->df_varcount = cctx.ctx_max_local;
5654 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005655
5656 ret = OK;
5657
5658erret:
5659 if (ret == FAIL)
5660 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01005661 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005662 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5663 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005664
5665 for (idx = 0; idx < instr->ga_len; ++idx)
5666 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005667 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01005668
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005669 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005670 if (!dfunc->df_deleted)
5671 --def_functions.ga_len;
5672
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005673 while (cctx.ctx_scope != NULL)
5674 drop_scope(&cctx);
5675
Bram Moolenaar20431c92020-03-20 18:39:46 +01005676 // Don't execute this function body.
5677 ga_clear_strings(&ufunc->uf_lines);
5678
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005679 if (errormsg != NULL)
5680 emsg(errormsg);
5681 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005682 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005683 }
5684
5685 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005686 free_imported(&cctx);
5687 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005688 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005689}
5690
5691/*
5692 * Delete an instruction, free what it contains.
5693 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01005694 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005695delete_instr(isn_T *isn)
5696{
5697 switch (isn->isn_type)
5698 {
5699 case ISN_EXEC:
5700 case ISN_LOADENV:
5701 case ISN_LOADG:
5702 case ISN_LOADOPT:
5703 case ISN_MEMBER:
5704 case ISN_PUSHEXC:
5705 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005706 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005707 case ISN_STOREG:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005708 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005709 vim_free(isn->isn_arg.string);
5710 break;
5711
5712 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005713 case ISN_STORES:
5714 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005715 break;
5716
5717 case ISN_STOREOPT:
5718 vim_free(isn->isn_arg.storeopt.so_name);
5719 break;
5720
5721 case ISN_PUSHBLOB: // push blob isn_arg.blob
5722 blob_unref(isn->isn_arg.blob);
5723 break;
5724
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005725 case ISN_PUSHPARTIAL:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01005726 partial_unref(isn->isn_arg.partial);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005727 break;
5728
5729 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005730#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005731 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005732#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005733 break;
5734
5735 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005736#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005737 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005738#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005739 break;
5740
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005741 case ISN_UCALL:
5742 vim_free(isn->isn_arg.ufunc.cuf_name);
5743 break;
5744
5745 case ISN_2BOOL:
5746 case ISN_2STRING:
5747 case ISN_ADDBLOB:
5748 case ISN_ADDLIST:
5749 case ISN_BCALL:
5750 case ISN_CATCH:
5751 case ISN_CHECKNR:
5752 case ISN_CHECKTYPE:
5753 case ISN_COMPAREANY:
5754 case ISN_COMPAREBLOB:
5755 case ISN_COMPAREBOOL:
5756 case ISN_COMPAREDICT:
5757 case ISN_COMPAREFLOAT:
5758 case ISN_COMPAREFUNC:
5759 case ISN_COMPARELIST:
5760 case ISN_COMPARENR:
5761 case ISN_COMPAREPARTIAL:
5762 case ISN_COMPARESPECIAL:
5763 case ISN_COMPARESTRING:
5764 case ISN_CONCAT:
5765 case ISN_DCALL:
5766 case ISN_DROP:
5767 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01005768 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005769 case ISN_ENDTRY:
5770 case ISN_FOR:
5771 case ISN_FUNCREF:
5772 case ISN_INDEX:
5773 case ISN_JUMP:
5774 case ISN_LOAD:
5775 case ISN_LOADSCRIPT:
5776 case ISN_LOADREG:
5777 case ISN_LOADV:
5778 case ISN_NEGATENR:
5779 case ISN_NEWDICT:
5780 case ISN_NEWLIST:
5781 case ISN_OPNR:
5782 case ISN_OPFLOAT:
5783 case ISN_OPANY:
5784 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02005785 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005786 case ISN_PUSHF:
5787 case ISN_PUSHNR:
5788 case ISN_PUSHBOOL:
5789 case ISN_PUSHSPEC:
5790 case ISN_RETURN:
5791 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005792 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005793 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005794 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005795 case ISN_STORESCRIPT:
5796 case ISN_THROW:
5797 case ISN_TRY:
5798 // nothing allocated
5799 break;
5800 }
5801}
5802
5803/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01005804 * Free all instructions for "dfunc".
5805 */
5806 static void
5807delete_def_function_contents(dfunc_T *dfunc)
5808{
5809 int idx;
5810
5811 ga_clear(&dfunc->df_def_args_isn);
5812
5813 if (dfunc->df_instr != NULL)
5814 {
5815 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
5816 delete_instr(dfunc->df_instr + idx);
5817 VIM_CLEAR(dfunc->df_instr);
5818 }
5819
5820 dfunc->df_deleted = TRUE;
5821}
5822
5823/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005824 * When a user function is deleted, delete any associated def function.
5825 */
5826 void
5827delete_def_function(ufunc_T *ufunc)
5828{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005829 if (ufunc->uf_dfunc_idx >= 0)
5830 {
5831 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5832 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005833
Bram Moolenaar20431c92020-03-20 18:39:46 +01005834 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005835 }
5836}
5837
5838#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01005839/*
5840 * Free all functions defined with ":def".
5841 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005842 void
5843free_def_functions(void)
5844{
Bram Moolenaar20431c92020-03-20 18:39:46 +01005845 int idx;
5846
5847 for (idx = 0; idx < def_functions.ga_len; ++idx)
5848 {
5849 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
5850
5851 delete_def_function_contents(dfunc);
5852 }
5853
5854 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005855}
5856#endif
5857
5858
5859#endif // FEAT_EVAL