blob: b040fd141a2e870374fcedd9e36d20ad1d723ed4 [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
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200123 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100124};
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 Moolenaar5deeb3f2020-04-05 17:08:17 +0200226/*
227 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
228 * be freed later.
229 */
230 static type_T *
231alloc_type(garray_T *type_gap)
232{
233 type_T *type;
234
235 if (ga_grow(type_gap, 1) == FAIL)
236 return NULL;
237 type = ALLOC_CLEAR_ONE(type_T);
238 if (type != NULL)
239 {
240 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
241 ++type_gap->ga_len;
242 }
243 return type;
244}
245
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100246 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200247get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100248{
249 type_T *type;
250
251 // recognize commonly used types
252 if (member_type->tt_type == VAR_UNKNOWN)
253 return &t_list_any;
Bram Moolenaar436472f2020-02-20 22:54:43 +0100254 if (member_type->tt_type == VAR_VOID)
255 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100256 if (member_type->tt_type == VAR_BOOL)
257 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100258 if (member_type->tt_type == VAR_NUMBER)
259 return &t_list_number;
260 if (member_type->tt_type == VAR_STRING)
261 return &t_list_string;
262
263 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200264 type = alloc_type(type_gap);
265 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100266 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100267 type->tt_type = VAR_LIST;
268 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200269 type->tt_argcount = 0;
270 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 return type;
272}
273
274 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200275get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100276{
277 type_T *type;
278
279 // recognize commonly used types
280 if (member_type->tt_type == VAR_UNKNOWN)
281 return &t_dict_any;
Bram Moolenaar436472f2020-02-20 22:54:43 +0100282 if (member_type->tt_type == VAR_VOID)
283 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100284 if (member_type->tt_type == VAR_BOOL)
285 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100286 if (member_type->tt_type == VAR_NUMBER)
287 return &t_dict_number;
288 if (member_type->tt_type == VAR_STRING)
289 return &t_dict_string;
290
291 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200292 type = alloc_type(type_gap);
293 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100294 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100295 type->tt_type = VAR_DICT;
296 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200297 type->tt_argcount = 0;
298 type->tt_args = NULL;
299 return type;
300}
301
302/*
303 * Get a function type, based on the return type "ret_type".
304 * If "argcount" is -1 or 0 a predefined type can be used.
305 * If "argcount" > 0 always create a new type, so that arguments can be added.
306 */
307 static type_T *
308get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
309{
310 type_T *type;
311
312 // recognize commonly used types
313 if (argcount <= 0)
314 {
315 if (ret_type == &t_void)
316 {
317 if (argcount == 0)
318 return &t_func_0_void;
319 else
320 return &t_func_void;
321 }
322 if (ret_type == &t_any)
323 {
324 if (argcount == 0)
325 return &t_func_0_any;
326 else
327 return &t_func_any;
328 }
329 if (ret_type == &t_number)
330 {
331 if (argcount == 0)
332 return &t_func_0_number;
333 else
334 return &t_func_number;
335 }
336 if (ret_type == &t_string)
337 {
338 if (argcount == 0)
339 return &t_func_0_string;
340 else
341 return &t_func_string;
342 }
343 }
344
345 // Not a common type or has arguments, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200346 type = alloc_type(type_gap);
347 if (type == NULL)
Bram Moolenaard77a8522020-04-03 21:59:57 +0200348 return &t_any;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200349 type->tt_type = VAR_FUNC;
350 type->tt_member = ret_type;
351 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100352 return type;
353}
354
Bram Moolenaara8c17702020-04-01 21:17:24 +0200355/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200356 * For a function type, reserve space for "argcount" argument types.
357 */
358 static int
359func_type_add_arg_types(
360 type_T *functype,
361 int argcount,
362 int min_argcount,
363 garray_T *type_gap)
364{
365 if (ga_grow(type_gap, 1) == FAIL)
366 return FAIL;
367 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
368 if (functype->tt_args == NULL)
369 return FAIL;
370 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = (void *)functype->tt_args;
371 ++type_gap->ga_len;
372
373 functype->tt_argcount = argcount;
374 functype->tt_min_argcount = min_argcount;
375 return OK;
376}
377
378/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200379 * Return the type_T for a typval. Only for primitive types.
380 */
381 static type_T *
382typval2type(typval_T *tv)
383{
384 if (tv->v_type == VAR_NUMBER)
385 return &t_number;
386 if (tv->v_type == VAR_BOOL)
387 return &t_bool;
388 if (tv->v_type == VAR_STRING)
389 return &t_string;
390 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
391 return &t_list_string;
392 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
393 return &t_dict_any;
394 return &t_any;
395}
396
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100397/////////////////////////////////////////////////////////////////////
398// Following generate_ functions expect the caller to call ga_grow().
399
Bram Moolenaar080457c2020-03-03 21:53:32 +0100400#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
401#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
402
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100403/*
404 * Generate an instruction without arguments.
405 * Returns a pointer to the new instruction, NULL if failed.
406 */
407 static isn_T *
408generate_instr(cctx_T *cctx, isntype_T isn_type)
409{
410 garray_T *instr = &cctx->ctx_instr;
411 isn_T *isn;
412
Bram Moolenaar080457c2020-03-03 21:53:32 +0100413 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100414 if (ga_grow(instr, 1) == FAIL)
415 return NULL;
416 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
417 isn->isn_type = isn_type;
418 isn->isn_lnum = cctx->ctx_lnum + 1;
419 ++instr->ga_len;
420
421 return isn;
422}
423
424/*
425 * Generate an instruction without arguments.
426 * "drop" will be removed from the stack.
427 * Returns a pointer to the new instruction, NULL if failed.
428 */
429 static isn_T *
430generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
431{
432 garray_T *stack = &cctx->ctx_type_stack;
433
Bram Moolenaar080457c2020-03-03 21:53:32 +0100434 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100435 stack->ga_len -= drop;
436 return generate_instr(cctx, isn_type);
437}
438
439/*
440 * Generate instruction "isn_type" and put "type" on the type stack.
441 */
442 static isn_T *
443generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
444{
445 isn_T *isn;
446 garray_T *stack = &cctx->ctx_type_stack;
447
448 if ((isn = generate_instr(cctx, isn_type)) == NULL)
449 return NULL;
450
451 if (ga_grow(stack, 1) == FAIL)
452 return NULL;
453 ((type_T **)stack->ga_data)[stack->ga_len] = type;
454 ++stack->ga_len;
455
456 return isn;
457}
458
459/*
460 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
461 */
462 static int
463may_generate_2STRING(int offset, cctx_T *cctx)
464{
465 isn_T *isn;
466 garray_T *stack = &cctx->ctx_type_stack;
467 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
468
469 if ((*type)->tt_type == VAR_STRING)
470 return OK;
471 *type = &t_string;
472
473 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
474 return FAIL;
475 isn->isn_arg.number = offset;
476
477 return OK;
478}
479
480 static int
481check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
482{
483 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_UNKNOWN)
484 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
485 || type2 == VAR_UNKNOWN)))
486 {
487 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100488 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100489 else
490 semsg(_("E1036: %c requires number or float arguments"), *op);
491 return FAIL;
492 }
493 return OK;
494}
495
496/*
497 * Generate an instruction with two arguments. The instruction depends on the
498 * type of the arguments.
499 */
500 static int
501generate_two_op(cctx_T *cctx, char_u *op)
502{
503 garray_T *stack = &cctx->ctx_type_stack;
504 type_T *type1;
505 type_T *type2;
506 vartype_T vartype;
507 isn_T *isn;
508
Bram Moolenaar080457c2020-03-03 21:53:32 +0100509 RETURN_OK_IF_SKIP(cctx);
510
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100511 // Get the known type of the two items on the stack. If they are matching
512 // use a type-specific instruction. Otherwise fall back to runtime type
513 // checking.
514 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
515 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
516 vartype = VAR_UNKNOWN;
517 if (type1->tt_type == type2->tt_type
518 && (type1->tt_type == VAR_NUMBER
519 || type1->tt_type == VAR_LIST
520#ifdef FEAT_FLOAT
521 || type1->tt_type == VAR_FLOAT
522#endif
523 || type1->tt_type == VAR_BLOB))
524 vartype = type1->tt_type;
525
526 switch (*op)
527 {
528 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar0062c2d2020-02-20 22:14:31 +0100529 && type1->tt_type != VAR_UNKNOWN
530 && type2->tt_type != VAR_UNKNOWN
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100531 && check_number_or_float(
532 type1->tt_type, type2->tt_type, op) == FAIL)
533 return FAIL;
534 isn = generate_instr_drop(cctx,
535 vartype == VAR_NUMBER ? ISN_OPNR
536 : vartype == VAR_LIST ? ISN_ADDLIST
537 : vartype == VAR_BLOB ? ISN_ADDBLOB
538#ifdef FEAT_FLOAT
539 : vartype == VAR_FLOAT ? ISN_OPFLOAT
540#endif
541 : ISN_OPANY, 1);
542 if (isn != NULL)
543 isn->isn_arg.op.op_type = EXPR_ADD;
544 break;
545
546 case '-':
547 case '*':
548 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
549 op) == FAIL)
550 return FAIL;
551 if (vartype == VAR_NUMBER)
552 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
553#ifdef FEAT_FLOAT
554 else if (vartype == VAR_FLOAT)
555 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
556#endif
557 else
558 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
559 if (isn != NULL)
560 isn->isn_arg.op.op_type = *op == '*'
561 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
562 break;
563
564 case '%': if ((type1->tt_type != VAR_UNKNOWN
565 && type1->tt_type != VAR_NUMBER)
566 || (type2->tt_type != VAR_UNKNOWN
567 && type2->tt_type != VAR_NUMBER))
568 {
569 emsg(_("E1035: % requires number arguments"));
570 return FAIL;
571 }
572 isn = generate_instr_drop(cctx,
573 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
574 if (isn != NULL)
575 isn->isn_arg.op.op_type = EXPR_REM;
576 break;
577 }
578
579 // correct type of result
580 if (vartype == VAR_UNKNOWN)
581 {
582 type_T *type = &t_any;
583
584#ifdef FEAT_FLOAT
585 // float+number and number+float results in float
586 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
587 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
588 type = &t_float;
589#endif
590 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
591 }
592
593 return OK;
594}
595
596/*
597 * Generate an ISN_COMPARE* instruction with a boolean result.
598 */
599 static int
600generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
601{
602 isntype_T isntype = ISN_DROP;
603 isn_T *isn;
604 garray_T *stack = &cctx->ctx_type_stack;
605 vartype_T type1;
606 vartype_T type2;
607
Bram Moolenaar080457c2020-03-03 21:53:32 +0100608 RETURN_OK_IF_SKIP(cctx);
609
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100610 // Get the known type of the two items on the stack. If they are matching
611 // use a type-specific instruction. Otherwise fall back to runtime type
612 // checking.
613 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
614 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
615 if (type1 == type2)
616 {
617 switch (type1)
618 {
619 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
620 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
621 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
622 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
623 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
624 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
625 case VAR_LIST: isntype = ISN_COMPARELIST; break;
626 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
627 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
628 case VAR_PARTIAL: isntype = ISN_COMPAREPARTIAL; break;
629 default: isntype = ISN_COMPAREANY; break;
630 }
631 }
632 else if (type1 == VAR_UNKNOWN || type2 == VAR_UNKNOWN
633 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
634 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
635 isntype = ISN_COMPAREANY;
636
637 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
638 && (isntype == ISN_COMPAREBOOL
639 || isntype == ISN_COMPARESPECIAL
640 || isntype == ISN_COMPARENR
641 || isntype == ISN_COMPAREFLOAT))
642 {
643 semsg(_("E1037: Cannot use \"%s\" with %s"),
644 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
645 return FAIL;
646 }
647 if (isntype == ISN_DROP
648 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
649 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
650 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
651 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
652 && exptype != EXPR_IS && exptype != EXPR_ISNOT
653 && (type1 == VAR_BLOB || type2 == VAR_BLOB
654 || type1 == VAR_LIST || type2 == VAR_LIST))))
655 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100656 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100657 vartype_name(type1), vartype_name(type2));
658 return FAIL;
659 }
660
661 if ((isn = generate_instr(cctx, isntype)) == NULL)
662 return FAIL;
663 isn->isn_arg.op.op_type = exptype;
664 isn->isn_arg.op.op_ic = ic;
665
666 // takes two arguments, puts one bool back
667 if (stack->ga_len >= 2)
668 {
669 --stack->ga_len;
670 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
671 }
672
673 return OK;
674}
675
676/*
677 * Generate an ISN_2BOOL instruction.
678 */
679 static int
680generate_2BOOL(cctx_T *cctx, int invert)
681{
682 isn_T *isn;
683 garray_T *stack = &cctx->ctx_type_stack;
684
Bram Moolenaar080457c2020-03-03 21:53:32 +0100685 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100686 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
687 return FAIL;
688 isn->isn_arg.number = invert;
689
690 // type becomes bool
691 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
692
693 return OK;
694}
695
696 static int
697generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
698{
699 isn_T *isn;
700 garray_T *stack = &cctx->ctx_type_stack;
701
Bram Moolenaar080457c2020-03-03 21:53:32 +0100702 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100703 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
704 return FAIL;
705 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
706 isn->isn_arg.type.ct_off = offset;
707
708 // type becomes vartype
709 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
710
711 return OK;
712}
713
714/*
715 * Generate an ISN_PUSHNR instruction.
716 */
717 static int
718generate_PUSHNR(cctx_T *cctx, varnumber_T number)
719{
720 isn_T *isn;
721
Bram Moolenaar080457c2020-03-03 21:53:32 +0100722 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100723 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
724 return FAIL;
725 isn->isn_arg.number = number;
726
727 return OK;
728}
729
730/*
731 * Generate an ISN_PUSHBOOL instruction.
732 */
733 static int
734generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
735{
736 isn_T *isn;
737
Bram Moolenaar080457c2020-03-03 21:53:32 +0100738 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100739 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
740 return FAIL;
741 isn->isn_arg.number = number;
742
743 return OK;
744}
745
746/*
747 * Generate an ISN_PUSHSPEC instruction.
748 */
749 static int
750generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
751{
752 isn_T *isn;
753
Bram Moolenaar080457c2020-03-03 21:53:32 +0100754 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100755 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
756 return FAIL;
757 isn->isn_arg.number = number;
758
759 return OK;
760}
761
762#ifdef FEAT_FLOAT
763/*
764 * Generate an ISN_PUSHF instruction.
765 */
766 static int
767generate_PUSHF(cctx_T *cctx, float_T fnumber)
768{
769 isn_T *isn;
770
Bram Moolenaar080457c2020-03-03 21:53:32 +0100771 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100772 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
773 return FAIL;
774 isn->isn_arg.fnumber = fnumber;
775
776 return OK;
777}
778#endif
779
780/*
781 * Generate an ISN_PUSHS instruction.
782 * Consumes "str".
783 */
784 static int
785generate_PUSHS(cctx_T *cctx, char_u *str)
786{
787 isn_T *isn;
788
Bram Moolenaar080457c2020-03-03 21:53:32 +0100789 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100790 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
791 return FAIL;
792 isn->isn_arg.string = str;
793
794 return OK;
795}
796
797/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100798 * Generate an ISN_PUSHCHANNEL instruction.
799 * Consumes "channel".
800 */
801 static int
802generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
803{
804 isn_T *isn;
805
Bram Moolenaar080457c2020-03-03 21:53:32 +0100806 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100807 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
808 return FAIL;
809 isn->isn_arg.channel = channel;
810
811 return OK;
812}
813
814/*
815 * Generate an ISN_PUSHJOB instruction.
816 * Consumes "job".
817 */
818 static int
819generate_PUSHJOB(cctx_T *cctx, job_T *job)
820{
821 isn_T *isn;
822
Bram Moolenaar080457c2020-03-03 21:53:32 +0100823 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100824 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100825 return FAIL;
826 isn->isn_arg.job = job;
827
828 return OK;
829}
830
831/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100832 * Generate an ISN_PUSHBLOB instruction.
833 * Consumes "blob".
834 */
835 static int
836generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
837{
838 isn_T *isn;
839
Bram Moolenaar080457c2020-03-03 21:53:32 +0100840 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100841 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
842 return FAIL;
843 isn->isn_arg.blob = blob;
844
845 return OK;
846}
847
848/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100849 * Generate an ISN_PUSHFUNC instruction with name "name".
850 * Consumes "name".
851 */
852 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200853generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100854{
855 isn_T *isn;
856
Bram Moolenaar080457c2020-03-03 21:53:32 +0100857 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200858 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100859 return FAIL;
860 isn->isn_arg.string = name;
861
862 return OK;
863}
864
865/*
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100866 * Generate an ISN_PUSHPARTIAL instruction with partial "part".
Bram Moolenaare69f6d02020-04-01 22:11:01 +0200867 * Consumes "part".
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100868 */
869 static int
870generate_PUSHPARTIAL(cctx_T *cctx, partial_T *part)
871{
872 isn_T *isn;
873
Bram Moolenaar080457c2020-03-03 21:53:32 +0100874 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaard77a8522020-04-03 21:59:57 +0200875 if ((isn = generate_instr_type(cctx, ISN_PUSHPARTIAL, &t_func_any)) == NULL)
Bram Moolenaar087d2e12020-03-01 15:36:42 +0100876 return FAIL;
877 isn->isn_arg.partial = part;
878
879 return OK;
880}
881
882/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100883 * Generate an ISN_STORE instruction.
884 */
885 static int
886generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
887{
888 isn_T *isn;
889
Bram Moolenaar080457c2020-03-03 21:53:32 +0100890 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100891 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
892 return FAIL;
893 if (name != NULL)
894 isn->isn_arg.string = vim_strsave(name);
895 else
896 isn->isn_arg.number = idx;
897
898 return OK;
899}
900
901/*
902 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
903 */
904 static int
905generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
906{
907 isn_T *isn;
908
Bram Moolenaar080457c2020-03-03 21:53:32 +0100909 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100910 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
911 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100912 isn->isn_arg.storenr.stnr_idx = idx;
913 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100914
915 return OK;
916}
917
918/*
919 * Generate an ISN_STOREOPT instruction
920 */
921 static int
922generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
923{
924 isn_T *isn;
925
Bram Moolenaar080457c2020-03-03 21:53:32 +0100926 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100927 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
928 return FAIL;
929 isn->isn_arg.storeopt.so_name = vim_strsave(name);
930 isn->isn_arg.storeopt.so_flags = opt_flags;
931
932 return OK;
933}
934
935/*
936 * Generate an ISN_LOAD or similar instruction.
937 */
938 static int
939generate_LOAD(
940 cctx_T *cctx,
941 isntype_T isn_type,
942 int idx,
943 char_u *name,
944 type_T *type)
945{
946 isn_T *isn;
947
Bram Moolenaar080457c2020-03-03 21:53:32 +0100948 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100949 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
950 return FAIL;
951 if (name != NULL)
952 isn->isn_arg.string = vim_strsave(name);
953 else
954 isn->isn_arg.number = idx;
955
956 return OK;
957}
958
959/*
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100960 * Generate an ISN_LOADV instruction.
961 */
962 static int
963generate_LOADV(
964 cctx_T *cctx,
965 char_u *name,
966 int error)
967{
968 // load v:var
969 int vidx = find_vim_var(name);
970
Bram Moolenaar080457c2020-03-03 21:53:32 +0100971 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100972 if (vidx < 0)
973 {
974 if (error)
975 semsg(_(e_var_notfound), name);
976 return FAIL;
977 }
978
979 // TODO: get actual type
980 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, &t_any);
981}
982
983/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100984 * Generate an ISN_LOADS instruction.
985 */
986 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100987generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100988 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100989 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100990 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100991 int sid,
992 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100993{
994 isn_T *isn;
995
Bram Moolenaar080457c2020-03-03 21:53:32 +0100996 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100997 if (isn_type == ISN_LOADS)
998 isn = generate_instr_type(cctx, isn_type, type);
999 else
1000 isn = generate_instr_drop(cctx, isn_type, 1);
1001 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001002 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001003 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1004 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001005
1006 return OK;
1007}
1008
1009/*
1010 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1011 */
1012 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001013generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001014 cctx_T *cctx,
1015 isntype_T isn_type,
1016 int sid,
1017 int idx,
1018 type_T *type)
1019{
1020 isn_T *isn;
1021
Bram Moolenaar080457c2020-03-03 21:53:32 +01001022 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001023 if (isn_type == ISN_LOADSCRIPT)
1024 isn = generate_instr_type(cctx, isn_type, type);
1025 else
1026 isn = generate_instr_drop(cctx, isn_type, 1);
1027 if (isn == NULL)
1028 return FAIL;
1029 isn->isn_arg.script.script_sid = sid;
1030 isn->isn_arg.script.script_idx = idx;
1031 return OK;
1032}
1033
1034/*
1035 * Generate an ISN_NEWLIST instruction.
1036 */
1037 static int
1038generate_NEWLIST(cctx_T *cctx, int count)
1039{
1040 isn_T *isn;
1041 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001042 type_T *type;
1043 type_T *member;
1044
Bram Moolenaar080457c2020-03-03 21:53:32 +01001045 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001046 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1047 return FAIL;
1048 isn->isn_arg.number = count;
1049
1050 // drop the value types
1051 stack->ga_len -= count;
1052
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001053 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001054 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001055 if (count > 0)
1056 member = ((type_T **)stack->ga_data)[stack->ga_len];
1057 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001058 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001059 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001060
1061 // add the list type to the type stack
1062 if (ga_grow(stack, 1) == FAIL)
1063 return FAIL;
1064 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1065 ++stack->ga_len;
1066
1067 return OK;
1068}
1069
1070/*
1071 * Generate an ISN_NEWDICT instruction.
1072 */
1073 static int
1074generate_NEWDICT(cctx_T *cctx, int count)
1075{
1076 isn_T *isn;
1077 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001078 type_T *type;
1079 type_T *member;
1080
Bram Moolenaar080457c2020-03-03 21:53:32 +01001081 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001082 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1083 return FAIL;
1084 isn->isn_arg.number = count;
1085
1086 // drop the key and value types
1087 stack->ga_len -= 2 * count;
1088
Bram Moolenaar436472f2020-02-20 22:54:43 +01001089 // Use the first value type for the list member type. Use "void" for an
1090 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001091 if (count > 0)
1092 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1093 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001094 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001095 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001096
1097 // add the dict type to the type stack
1098 if (ga_grow(stack, 1) == FAIL)
1099 return FAIL;
1100 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1101 ++stack->ga_len;
1102
1103 return OK;
1104}
1105
1106/*
1107 * Generate an ISN_FUNCREF instruction.
1108 */
1109 static int
1110generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1111{
1112 isn_T *isn;
1113 garray_T *stack = &cctx->ctx_type_stack;
1114
Bram Moolenaar080457c2020-03-03 21:53:32 +01001115 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001116 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1117 return FAIL;
1118 isn->isn_arg.number = dfunc_idx;
1119
1120 if (ga_grow(stack, 1) == FAIL)
1121 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001122 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001123 // TODO: argument and return types
1124 ++stack->ga_len;
1125
1126 return OK;
1127}
1128
1129/*
1130 * Generate an ISN_JUMP instruction.
1131 */
1132 static int
1133generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1134{
1135 isn_T *isn;
1136 garray_T *stack = &cctx->ctx_type_stack;
1137
Bram Moolenaar080457c2020-03-03 21:53:32 +01001138 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001139 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1140 return FAIL;
1141 isn->isn_arg.jump.jump_when = when;
1142 isn->isn_arg.jump.jump_where = where;
1143
1144 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1145 --stack->ga_len;
1146
1147 return OK;
1148}
1149
1150 static int
1151generate_FOR(cctx_T *cctx, int loop_idx)
1152{
1153 isn_T *isn;
1154 garray_T *stack = &cctx->ctx_type_stack;
1155
Bram Moolenaar080457c2020-03-03 21:53:32 +01001156 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001157 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1158 return FAIL;
1159 isn->isn_arg.forloop.for_idx = loop_idx;
1160
1161 if (ga_grow(stack, 1) == FAIL)
1162 return FAIL;
1163 // type doesn't matter, will be stored next
1164 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1165 ++stack->ga_len;
1166
1167 return OK;
1168}
1169
1170/*
1171 * Generate an ISN_BCALL instruction.
1172 * Return FAIL if the number of arguments is wrong.
1173 */
1174 static int
1175generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1176{
1177 isn_T *isn;
1178 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001179 type_T *argtypes[MAX_FUNC_ARGS];
1180 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001181
Bram Moolenaar080457c2020-03-03 21:53:32 +01001182 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001183 if (check_internal_func(func_idx, argcount) == FAIL)
1184 return FAIL;
1185
1186 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1187 return FAIL;
1188 isn->isn_arg.bfunc.cbf_idx = func_idx;
1189 isn->isn_arg.bfunc.cbf_argcount = argcount;
1190
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001191 for (i = 0; i < argcount; ++i)
1192 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1193
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001194 stack->ga_len -= argcount; // drop the arguments
1195 if (ga_grow(stack, 1) == FAIL)
1196 return FAIL;
1197 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001198 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001199 ++stack->ga_len; // add return value
1200
1201 return OK;
1202}
1203
1204/*
1205 * Generate an ISN_DCALL or ISN_UCALL instruction.
1206 * Return FAIL if the number of arguments is wrong.
1207 */
1208 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001209generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001210{
1211 isn_T *isn;
1212 garray_T *stack = &cctx->ctx_type_stack;
1213 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001214 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001215
Bram Moolenaar080457c2020-03-03 21:53:32 +01001216 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001217 if (argcount > regular_args && !has_varargs(ufunc))
1218 {
1219 semsg(_(e_toomanyarg), ufunc->uf_name);
1220 return FAIL;
1221 }
1222 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1223 {
1224 semsg(_(e_toofewarg), ufunc->uf_name);
1225 return FAIL;
1226 }
1227
1228 // Turn varargs into a list.
1229 if (ufunc->uf_va_name != NULL)
1230 {
1231 int count = argcount - regular_args;
1232
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001233 // If count is negative an empty list will be added after evaluating
1234 // default values for missing optional arguments.
1235 if (count >= 0)
1236 {
1237 generate_NEWLIST(cctx, count);
1238 argcount = regular_args + 1;
1239 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001240 }
1241
1242 if ((isn = generate_instr(cctx,
1243 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1244 return FAIL;
1245 if (ufunc->uf_dfunc_idx >= 0)
1246 {
1247 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1248 isn->isn_arg.dfunc.cdf_argcount = argcount;
1249 }
1250 else
1251 {
1252 // A user function may be deleted and redefined later, can't use the
1253 // ufunc pointer, need to look it up again at runtime.
1254 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1255 isn->isn_arg.ufunc.cuf_argcount = argcount;
1256 }
1257
1258 stack->ga_len -= argcount; // drop the arguments
1259 if (ga_grow(stack, 1) == FAIL)
1260 return FAIL;
1261 // add return value
1262 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1263 ++stack->ga_len;
1264
1265 return OK;
1266}
1267
1268/*
1269 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1270 */
1271 static int
1272generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1273{
1274 isn_T *isn;
1275 garray_T *stack = &cctx->ctx_type_stack;
1276
Bram Moolenaar080457c2020-03-03 21:53:32 +01001277 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001278 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1279 return FAIL;
1280 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1281 isn->isn_arg.ufunc.cuf_argcount = argcount;
1282
1283 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001284 if (ga_grow(stack, 1) == FAIL)
1285 return FAIL;
1286 // add return value
1287 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1288 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001289
1290 return OK;
1291}
1292
1293/*
1294 * Generate an ISN_PCALL instruction.
1295 */
1296 static int
1297generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1298{
1299 isn_T *isn;
1300 garray_T *stack = &cctx->ctx_type_stack;
1301
Bram Moolenaar080457c2020-03-03 21:53:32 +01001302 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001303 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1304 return FAIL;
1305 isn->isn_arg.pfunc.cpf_top = at_top;
1306 isn->isn_arg.pfunc.cpf_argcount = argcount;
1307
1308 stack->ga_len -= argcount; // drop the arguments
1309
1310 // drop the funcref/partial, get back the return value
1311 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1312
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001313 // If partial is above the arguments it must be cleared and replaced with
1314 // the return value.
1315 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1316 return FAIL;
1317
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001318 return OK;
1319}
1320
1321/*
1322 * Generate an ISN_MEMBER instruction.
1323 */
1324 static int
1325generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1326{
1327 isn_T *isn;
1328 garray_T *stack = &cctx->ctx_type_stack;
1329 type_T *type;
1330
Bram Moolenaar080457c2020-03-03 21:53:32 +01001331 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001332 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1333 return FAIL;
1334 isn->isn_arg.string = vim_strnsave(name, (int)len);
1335
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001336 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001337 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001338 if (type->tt_type != VAR_DICT && type != &t_any)
1339 {
1340 emsg(_(e_dictreq));
1341 return FAIL;
1342 }
1343 // change dict type to dict member type
1344 if (type->tt_type == VAR_DICT)
1345 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001346
1347 return OK;
1348}
1349
1350/*
1351 * Generate an ISN_ECHO instruction.
1352 */
1353 static int
1354generate_ECHO(cctx_T *cctx, int with_white, int count)
1355{
1356 isn_T *isn;
1357
Bram Moolenaar080457c2020-03-03 21:53:32 +01001358 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001359 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1360 return FAIL;
1361 isn->isn_arg.echo.echo_with_white = with_white;
1362 isn->isn_arg.echo.echo_count = count;
1363
1364 return OK;
1365}
1366
Bram Moolenaarad39c092020-02-26 18:23:43 +01001367/*
1368 * Generate an ISN_EXECUTE instruction.
1369 */
1370 static int
1371generate_EXECUTE(cctx_T *cctx, int count)
1372{
1373 isn_T *isn;
1374
1375 if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL)
1376 return FAIL;
1377 isn->isn_arg.number = count;
1378
1379 return OK;
1380}
1381
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001382 static int
1383generate_EXEC(cctx_T *cctx, char_u *line)
1384{
1385 isn_T *isn;
1386
Bram Moolenaar080457c2020-03-03 21:53:32 +01001387 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001388 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1389 return FAIL;
1390 isn->isn_arg.string = vim_strsave(line);
1391 return OK;
1392}
1393
1394static char e_white_both[] =
1395 N_("E1004: white space required before and after '%s'");
Bram Moolenaard77a8522020-04-03 21:59:57 +02001396static char e_white_after[] = N_("E1069: white space required after '%s'");
1397static char e_no_white_before[] = N_("E1068: No white space allowed before '%s'");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001398
1399/*
1400 * Reserve space for a local variable.
1401 * Return the index or -1 if it failed.
1402 */
1403 static int
1404reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1405{
1406 int idx;
1407 lvar_T *lvar;
1408
1409 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1410 {
1411 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1412 return -1;
1413 }
1414
1415 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1416 return -1;
1417 idx = cctx->ctx_locals.ga_len;
1418 if (cctx->ctx_max_local < idx + 1)
1419 cctx->ctx_max_local = idx + 1;
1420 ++cctx->ctx_locals.ga_len;
1421
1422 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1423 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1424 lvar->lv_const = isConst;
1425 lvar->lv_type = type;
1426
1427 return idx;
1428}
1429
1430/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001431 * Remove local variables above "new_top".
1432 */
1433 static void
1434unwind_locals(cctx_T *cctx, int new_top)
1435{
1436 if (cctx->ctx_locals.ga_len > new_top)
1437 {
1438 int idx;
1439 lvar_T *lvar;
1440
1441 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1442 {
1443 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1444 vim_free(lvar->lv_name);
1445 }
1446 }
1447 cctx->ctx_locals.ga_len = new_top;
1448}
1449
1450/*
1451 * Free all local variables.
1452 */
1453 static void
1454free_local(cctx_T *cctx)
1455{
1456 unwind_locals(cctx, 0);
1457 ga_clear(&cctx->ctx_locals);
1458}
1459
1460/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001461 * Skip over a type definition and return a pointer to just after it.
1462 */
1463 char_u *
1464skip_type(char_u *start)
1465{
1466 char_u *p = start;
1467
1468 while (ASCII_ISALNUM(*p) || *p == '_')
1469 ++p;
1470
1471 // Skip over "<type>"; this is permissive about white space.
1472 if (*skipwhite(p) == '<')
1473 {
1474 p = skipwhite(p);
1475 p = skip_type(skipwhite(p + 1));
1476 p = skipwhite(p);
1477 if (*p == '>')
1478 ++p;
1479 }
1480 return p;
1481}
1482
1483/*
1484 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001485 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001486 * Returns NULL in case of failure.
1487 */
1488 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001489parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001490{
1491 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001492 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001493
1494 if (**arg != '<')
1495 {
1496 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001497 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001498 else
1499 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001500 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001501 }
1502 *arg = skipwhite(*arg + 1);
1503
Bram Moolenaard77a8522020-04-03 21:59:57 +02001504 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001505
1506 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001507 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001508 {
1509 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001510 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001511 }
1512 ++*arg;
1513
1514 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001515 return get_list_type(member_type, type_gap);
1516 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001517}
1518
1519/*
1520 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001521 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001522 */
1523 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001524parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001525{
1526 char_u *p = *arg;
1527 size_t len;
1528
1529 // skip over the first word
1530 while (ASCII_ISALNUM(*p) || *p == '_')
1531 ++p;
1532 len = p - *arg;
1533
1534 switch (**arg)
1535 {
1536 case 'a':
1537 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1538 {
1539 *arg += len;
1540 return &t_any;
1541 }
1542 break;
1543 case 'b':
1544 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1545 {
1546 *arg += len;
1547 return &t_bool;
1548 }
1549 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1550 {
1551 *arg += len;
1552 return &t_blob;
1553 }
1554 break;
1555 case 'c':
1556 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1557 {
1558 *arg += len;
1559 return &t_channel;
1560 }
1561 break;
1562 case 'd':
1563 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1564 {
1565 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001566 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001567 }
1568 break;
1569 case 'f':
1570 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1571 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001572#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001573 *arg += len;
1574 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001575#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001576 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001577 return &t_any;
1578#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001579 }
1580 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1581 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001582 type_T *type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001583 type_T *ret_type = &t_any;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001584 int argcount = -1;
1585 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001586 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001587 type_T *arg_type[MAX_FUNC_ARGS + 1];
1588
1589 // func({type}, ...): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001590 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001591 if (**arg == '(')
1592 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001593 // "func" may or may not return a value, "func()" does
1594 // not return a value.
1595 ret_type = &t_void;
1596
Bram Moolenaard77a8522020-04-03 21:59:57 +02001597 p = ++*arg;
1598 argcount = 0;
1599 while (*p != NUL && *p != ')')
1600 {
1601 if (STRNCMP(p, "...", 3) == 0)
1602 {
1603 flags |= TTFLAG_VARARGS;
1604 break;
1605 }
1606 arg_type[argcount++] = parse_type(&p, type_gap);
1607
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001608 if (*p == '?')
1609 {
1610 if (first_optional == -1)
1611 first_optional = argcount;
1612 ++p;
1613 }
1614 else if (first_optional != -1)
1615 {
1616 emsg(_("E1007: mandatory argument after optional argument"));
1617 return &t_any;
1618 }
1619
Bram Moolenaard77a8522020-04-03 21:59:57 +02001620 if (*p != ',' && *skipwhite(p) == ',')
1621 {
1622 semsg(_(e_no_white_before), ",");
1623 return &t_any;
1624 }
1625 if (*p == ',')
1626 {
1627 ++p;
1628 if (!VIM_ISWHITE(*p))
1629 semsg(_(e_white_after), ",");
1630 }
1631 p = skipwhite(p);
1632 if (argcount == MAX_FUNC_ARGS)
1633 {
1634 emsg(_("E740: Too many argument types"));
1635 return &t_any;
1636 }
1637 }
1638
1639 p = skipwhite(p);
1640 if (*p != ')')
1641 {
1642 emsg(_(e_missing_close));
1643 return &t_any;
1644 }
1645 *arg = p + 1;
1646 }
1647 if (**arg == ':')
1648 {
1649 // parse return type
1650 ++*arg;
1651 if (!VIM_ISWHITE(*p))
1652 semsg(_(e_white_after), ":");
1653 *arg = skipwhite(*arg);
1654 ret_type = parse_type(arg, type_gap);
1655 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001656 type = get_func_type(ret_type,
1657 flags == 0 && first_optional == -1 ? argcount : 99,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001658 type_gap);
1659 if (flags != 0)
1660 type->tt_flags = flags;
1661 if (argcount > 0)
1662 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001663 if (func_type_add_arg_types(type, argcount,
1664 first_optional == -1 ? argcount : first_optional,
1665 type_gap) == FAIL)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001666 return &t_any;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001667 mch_memmove(type->tt_args, arg_type,
1668 sizeof(type_T *) * argcount);
1669 }
1670 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001671 }
1672 break;
1673 case 'j':
1674 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1675 {
1676 *arg += len;
1677 return &t_job;
1678 }
1679 break;
1680 case 'l':
1681 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1682 {
1683 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001684 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001685 }
1686 break;
1687 case 'n':
1688 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1689 {
1690 *arg += len;
1691 return &t_number;
1692 }
1693 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001694 case 's':
1695 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1696 {
1697 *arg += len;
1698 return &t_string;
1699 }
1700 break;
1701 case 'v':
1702 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1703 {
1704 *arg += len;
1705 return &t_void;
1706 }
1707 break;
1708 }
1709
1710 semsg(_("E1010: Type not recognized: %s"), *arg);
1711 return &t_any;
1712}
1713
1714/*
1715 * Check if "type1" and "type2" are exactly the same.
1716 */
1717 static int
1718equal_type(type_T *type1, type_T *type2)
1719{
1720 if (type1->tt_type != type2->tt_type)
1721 return FALSE;
1722 switch (type1->tt_type)
1723 {
1724 case VAR_VOID:
1725 case VAR_UNKNOWN:
1726 case VAR_SPECIAL:
1727 case VAR_BOOL:
1728 case VAR_NUMBER:
1729 case VAR_FLOAT:
1730 case VAR_STRING:
1731 case VAR_BLOB:
1732 case VAR_JOB:
1733 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001734 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001735 case VAR_LIST:
1736 case VAR_DICT:
1737 return equal_type(type1->tt_member, type2->tt_member);
1738 case VAR_FUNC:
1739 case VAR_PARTIAL:
1740 // TODO; check argument types.
1741 return equal_type(type1->tt_member, type2->tt_member)
1742 && type1->tt_argcount == type2->tt_argcount;
1743 }
1744 return TRUE;
1745}
1746
1747/*
1748 * Find the common type of "type1" and "type2" and put it in "dest".
1749 * "type2" and "dest" may be the same.
1750 */
1751 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001752common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001753{
1754 if (equal_type(type1, type2))
1755 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001756 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001757 return;
1758 }
1759
1760 if (type1->tt_type == type2->tt_type)
1761 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001762 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1763 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001764 type_T *common;
1765
Bram Moolenaard77a8522020-04-03 21:59:57 +02001766 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001767 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001768 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001769 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001770 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001771 return;
1772 }
1773 // TODO: VAR_FUNC and VAR_PARTIAL
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001774 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001775 }
1776
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001777 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001778}
1779
1780 char *
1781vartype_name(vartype_T type)
1782{
1783 switch (type)
1784 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001785 case VAR_UNKNOWN: break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001786 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001787 case VAR_SPECIAL: return "special";
1788 case VAR_BOOL: return "bool";
1789 case VAR_NUMBER: return "number";
1790 case VAR_FLOAT: return "float";
1791 case VAR_STRING: return "string";
1792 case VAR_BLOB: return "blob";
1793 case VAR_JOB: return "job";
1794 case VAR_CHANNEL: return "channel";
1795 case VAR_LIST: return "list";
1796 case VAR_DICT: return "dict";
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001797 case VAR_FUNC: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001798 case VAR_PARTIAL: return "partial";
1799 }
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001800 return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001801}
1802
1803/*
1804 * Return the name of a type.
1805 * The result may be in allocated memory, in which case "tofree" is set.
1806 */
1807 char *
1808type_name(type_T *type, char **tofree)
1809{
1810 char *name = vartype_name(type->tt_type);
1811
1812 *tofree = NULL;
1813 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1814 {
1815 char *member_free;
1816 char *member_name = type_name(type->tt_member, &member_free);
1817 size_t len;
1818
1819 len = STRLEN(name) + STRLEN(member_name) + 3;
1820 *tofree = alloc(len);
1821 if (*tofree != NULL)
1822 {
1823 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1824 vim_free(member_free);
1825 return *tofree;
1826 }
1827 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001828 if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
1829 {
1830 garray_T ga;
1831 int i;
1832
1833 ga_init2(&ga, 1, 100);
1834 if (ga_grow(&ga, 20) == FAIL)
1835 return "[unknown]";
1836 *tofree = ga.ga_data;
1837 STRCPY(ga.ga_data, "func(");
1838 ga.ga_len += 5;
1839
1840 for (i = 0; i < type->tt_argcount; ++i)
1841 {
1842 char *arg_free;
1843 char *arg_type = type_name(type->tt_args[i], &arg_free);
1844 int len;
1845
1846 if (i > 0)
1847 {
1848 STRCPY(ga.ga_data + ga.ga_len, ", ");
1849 ga.ga_len += 2;
1850 }
1851 len = (int)STRLEN(arg_type);
1852 if (ga_grow(&ga, len + 6) == FAIL)
1853 {
1854 vim_free(arg_free);
1855 return "[unknown]";
1856 }
1857 *tofree = ga.ga_data;
1858 STRCPY(ga.ga_data + ga.ga_len, arg_type);
1859 ga.ga_len += len;
1860 vim_free(arg_free);
1861 }
1862
1863 if (type->tt_member == &t_void)
1864 STRCPY(ga.ga_data + ga.ga_len, ")");
1865 else
1866 {
1867 char *ret_free;
1868 char *ret_name = type_name(type->tt_member, &ret_free);
1869 int len;
1870
1871 len = (int)STRLEN(ret_name) + 4;
1872 if (ga_grow(&ga, len) == FAIL)
1873 {
1874 vim_free(ret_free);
1875 return "[unknown]";
1876 }
1877 *tofree = ga.ga_data;
1878 STRCPY(ga.ga_data + ga.ga_len, "): ");
1879 STRCPY(ga.ga_data + ga.ga_len + 3, ret_name);
1880 vim_free(ret_free);
1881 }
1882 return ga.ga_data;
1883 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001884
1885 return name;
1886}
1887
1888/*
1889 * Find "name" in script-local items of script "sid".
1890 * Returns the index in "sn_var_vals" if found.
1891 * If found but not in "sn_var_vals" returns -1.
1892 * If not found returns -2.
1893 */
1894 int
1895get_script_item_idx(int sid, char_u *name, int check_writable)
1896{
1897 hashtab_T *ht;
1898 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001899 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001900 int idx;
1901
1902 // First look the name up in the hashtable.
1903 if (sid <= 0 || sid > script_items.ga_len)
1904 return -1;
1905 ht = &SCRIPT_VARS(sid);
1906 di = find_var_in_ht(ht, 0, name, TRUE);
1907 if (di == NULL)
1908 return -2;
1909
1910 // Now find the svar_T index in sn_var_vals.
1911 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
1912 {
1913 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1914
1915 if (sv->sv_tv == &di->di_tv)
1916 {
1917 if (check_writable && sv->sv_const)
1918 semsg(_(e_readonlyvar), name);
1919 return idx;
1920 }
1921 }
1922 return -1;
1923}
1924
1925/*
1926 * Find "name" in imported items of the current script/
1927 */
1928 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001929find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001930{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001931 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001932 int idx;
1933
1934 if (cctx != NULL)
1935 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1936 {
1937 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
1938 + idx;
1939
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001940 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1941 : STRLEN(import->imp_name) == len
1942 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001943 return import;
1944 }
1945
1946 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
1947 {
1948 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
1949
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01001950 if (len == 0 ? STRCMP(name, import->imp_name) == 0
1951 : STRLEN(import->imp_name) == len
1952 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001953 return import;
1954 }
1955 return NULL;
1956}
1957
1958/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001959 * Free all imported variables.
1960 */
1961 static void
1962free_imported(cctx_T *cctx)
1963{
1964 int idx;
1965
1966 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
1967 {
1968 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
1969
1970 vim_free(import->imp_name);
1971 }
1972 ga_clear(&cctx->ctx_imports);
1973}
1974
1975/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001976 * Generate an instruction to load script-local variable "name", without the
1977 * leading "s:".
1978 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001979 */
1980 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01001981compile_load_scriptvar(
1982 cctx_T *cctx,
1983 char_u *name, // variable NUL terminated
1984 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01001985 char_u **end, // end of variable
1986 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001987{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001988 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001989 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
1990 imported_T *import;
1991
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001992 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001993 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01001994 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001995 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
1996 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001997 }
1998 if (idx >= 0)
1999 {
2000 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2001
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002002 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002003 current_sctx.sc_sid, idx, sv->sv_type);
2004 return OK;
2005 }
2006
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002007 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002008 if (import != NULL)
2009 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002010 if (import->imp_all)
2011 {
2012 char_u *p = skipwhite(*end);
2013 int name_len;
2014 ufunc_T *ufunc;
2015 type_T *type;
2016
2017 // Used "import * as Name", need to lookup the member.
2018 if (*p != '.')
2019 {
2020 semsg(_("E1060: expected dot after name: %s"), start);
2021 return FAIL;
2022 }
2023 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002024 if (VIM_ISWHITE(*p))
2025 {
2026 emsg(_("E1074: no white space allowed after dot"));
2027 return FAIL;
2028 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002029
2030 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2031 // TODO: what if it is a function?
2032 if (idx < 0)
2033 return FAIL;
2034 *end = p;
2035
2036 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2037 import->imp_sid,
2038 idx,
2039 type);
2040 }
2041 else
2042 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002043 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002044 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2045 import->imp_sid,
2046 import->imp_var_vals_idx,
2047 import->imp_type);
2048 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002049 return OK;
2050 }
2051
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002052 if (error)
2053 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002054 return FAIL;
2055}
2056
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002057 static int
2058generate_funcref(cctx_T *cctx, char_u *name)
2059{
2060 ufunc_T *ufunc = find_func(name, cctx);
2061
2062 if (ufunc == NULL)
2063 return FAIL;
2064
2065 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2066}
2067
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002068/*
2069 * Compile a variable name into a load instruction.
2070 * "end" points to just after the name.
2071 * When "error" is FALSE do not give an error when not found.
2072 */
2073 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002074compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002075{
2076 type_T *type;
2077 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002078 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002079 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002080 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002081
2082 if (*(*arg + 1) == ':')
2083 {
2084 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002085 if (end <= *arg + 2)
2086 name = vim_strsave((char_u *)"[empty]");
2087 else
2088 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002089 if (name == NULL)
2090 return FAIL;
2091
2092 if (**arg == 'v')
2093 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002094 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002095 }
2096 else if (**arg == 'g')
2097 {
2098 // Global variables can be defined later, thus we don't check if it
2099 // exists, give error at runtime.
2100 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2101 }
2102 else if (**arg == 's')
2103 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002104 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002105 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002106 else if (**arg == 'b')
2107 {
2108 semsg("Namespace b: not supported yet: %s", *arg);
2109 goto theend;
2110 }
2111 else if (**arg == 'w')
2112 {
2113 semsg("Namespace w: not supported yet: %s", *arg);
2114 goto theend;
2115 }
2116 else if (**arg == 't')
2117 {
2118 semsg("Namespace t: not supported yet: %s", *arg);
2119 goto theend;
2120 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002121 else
2122 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002123 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002124 goto theend;
2125 }
2126 }
2127 else
2128 {
2129 size_t len = end - *arg;
2130 int idx;
2131 int gen_load = FALSE;
2132
2133 name = vim_strnsave(*arg, end - *arg);
2134 if (name == NULL)
2135 return FAIL;
2136
2137 idx = lookup_arg(*arg, len, cctx);
2138 if (idx >= 0)
2139 {
2140 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2141 type = cctx->ctx_ufunc->uf_arg_types[idx];
2142 else
2143 type = &t_any;
2144
2145 // Arguments are located above the frame pointer.
2146 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2147 if (cctx->ctx_ufunc->uf_va_name != NULL)
2148 --idx;
2149 gen_load = TRUE;
2150 }
2151 else if (lookup_vararg(*arg, len, cctx))
2152 {
2153 // varargs is always the last argument
2154 idx = -STACK_FRAME_SIZE - 1;
2155 type = cctx->ctx_ufunc->uf_va_type;
2156 gen_load = TRUE;
2157 }
2158 else
2159 {
2160 idx = lookup_local(*arg, len, cctx);
2161 if (idx >= 0)
2162 {
2163 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2164 gen_load = TRUE;
2165 }
2166 else
2167 {
2168 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2169 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2170 res = generate_PUSHBOOL(cctx, **arg == 't'
2171 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002172 else
2173 {
2174 // "var" can be script-local even without using "s:" if it
2175 // already exists.
2176 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2177 == SCRIPT_VERSION_VIM9
2178 || lookup_script(*arg, len) == OK)
2179 res = compile_load_scriptvar(cctx, name, *arg, &end,
2180 FALSE);
2181
2182 // When the name starts with an uppercase letter or "x:" it
2183 // can be a user defined function.
2184 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2185 res = generate_funcref(cctx, name);
2186 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002187 }
2188 }
2189 if (gen_load)
2190 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2191 }
2192
2193 *arg = end;
2194
2195theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002196 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002197 semsg(_(e_var_notfound), name);
2198 vim_free(name);
2199 return res;
2200}
2201
2202/*
2203 * Compile the argument expressions.
2204 * "arg" points to just after the "(" and is advanced to after the ")"
2205 */
2206 static int
2207compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2208{
2209 char_u *p = *arg;
2210
2211 while (*p != NUL && *p != ')')
2212 {
2213 if (compile_expr1(&p, cctx) == FAIL)
2214 return FAIL;
2215 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002216
2217 if (*p != ',' && *skipwhite(p) == ',')
2218 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002219 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002220 p = skipwhite(p);
2221 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002222 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002223 {
2224 ++p;
2225 if (!VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002226 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002227 }
2228 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002229 }
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002230 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002231 if (*p != ')')
2232 {
2233 emsg(_(e_missing_close));
2234 return FAIL;
2235 }
2236 *arg = p + 1;
2237 return OK;
2238}
2239
2240/*
2241 * Compile a function call: name(arg1, arg2)
2242 * "arg" points to "name", "arg + varlen" to the "(".
2243 * "argcount_init" is 1 for "value->method()"
2244 * Instructions:
2245 * EVAL arg1
2246 * EVAL arg2
2247 * BCALL / DCALL / UCALL
2248 */
2249 static int
2250compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2251{
2252 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002253 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002254 int argcount = argcount_init;
2255 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002256 char_u fname_buf[FLEN_FIXED + 1];
2257 char_u *tofree = NULL;
2258 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002259 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002260 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002261
2262 if (varlen >= sizeof(namebuf))
2263 {
2264 semsg(_("E1011: name too long: %s"), name);
2265 return FAIL;
2266 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002267 vim_strncpy(namebuf, *arg, varlen);
2268 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002269
2270 *arg = skipwhite(*arg + varlen + 1);
2271 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002272 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002273
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002274 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002275 {
2276 int idx;
2277
2278 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002279 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002280 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002281 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002282 else
2283 semsg(_(e_unknownfunc), namebuf);
2284 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002285 }
2286
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002287 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002288 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002289 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002290 {
2291 res = generate_CALL(cctx, ufunc, argcount);
2292 goto theend;
2293 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002294
2295 // If the name is a variable, load it and use PCALL.
2296 p = namebuf;
2297 if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002298 {
2299 res = generate_PCALL(cctx, argcount, FALSE);
2300 goto theend;
2301 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002302
2303 // The function may be defined only later. Need to figure out at runtime.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002304 res = generate_UCALL(cctx, name, argcount);
2305
2306theend:
2307 vim_free(tofree);
2308 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002309}
2310
2311// like NAMESPACE_CHAR but with 'a' and 'l'.
2312#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2313
2314/*
2315 * Find the end of a variable or function name. Unlike find_name_end() this
2316 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002317 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002318 * Return a pointer to just after the name. Equal to "arg" if there is no
2319 * valid name.
2320 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002321 static char_u *
2322to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002323{
2324 char_u *p;
2325
2326 // Quick check for valid starting character.
2327 if (!eval_isnamec1(*arg))
2328 return arg;
2329
2330 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2331 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2332 // and can be used in slice "[n:]".
2333 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002334 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002335 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2336 break;
2337 return p;
2338}
2339
2340/*
2341 * Like to_name_end() but also skip over a list or dict constant.
2342 */
2343 char_u *
2344to_name_const_end(char_u *arg)
2345{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002346 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002347 typval_T rettv;
2348
2349 if (p == arg && *arg == '[')
2350 {
2351
2352 // Can be "[1, 2, 3]->Func()".
2353 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2354 p = arg;
2355 }
2356 else if (p == arg && *arg == '#' && arg[1] == '{')
2357 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002358 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002359 ++p;
2360 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2361 p = arg;
2362 }
2363 else if (p == arg && *arg == '{')
2364 {
2365 int ret = get_lambda_tv(&p, &rettv, FALSE);
2366
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002367 // Can be "{x -> ret}()".
2368 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002369 if (ret == NOTDONE)
2370 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2371 if (ret != OK)
2372 p = arg;
2373 }
2374
2375 return p;
2376}
2377
2378 static void
2379type_mismatch(type_T *expected, type_T *actual)
2380{
2381 char *tofree1, *tofree2;
2382
2383 semsg(_("E1013: type mismatch, expected %s but got %s"),
2384 type_name(expected, &tofree1), type_name(actual, &tofree2));
2385 vim_free(tofree1);
2386 vim_free(tofree2);
2387}
2388
2389/*
2390 * Check if the expected and actual types match.
2391 */
2392 static int
2393check_type(type_T *expected, type_T *actual, int give_msg)
2394{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002395 int ret = OK;
2396
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002397 if (expected->tt_type != VAR_UNKNOWN)
2398 {
2399 if (expected->tt_type != actual->tt_type)
2400 {
2401 if (give_msg)
2402 type_mismatch(expected, actual);
2403 return FAIL;
2404 }
2405 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2406 {
Bram Moolenaar436472f2020-02-20 22:54:43 +01002407 // void is used for an empty list or dict
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002408 if (actual->tt_member != &t_void)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002409 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002410 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002411 else if (expected->tt_type == VAR_FUNC)
2412 {
2413 if (expected->tt_member != &t_any)
2414 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2415 if (ret == OK && expected->tt_argcount != -1
2416 && (actual->tt_argcount < expected->tt_min_argcount
2417 || actual->tt_argcount > expected->tt_argcount))
2418 ret = FAIL;
2419 }
2420 if (ret == FAIL && give_msg)
2421 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002422 }
2423 return OK;
2424}
2425
2426/*
2427 * Check that
2428 * - "actual" is "expected" type or
2429 * - "actual" is a type that can be "expected" type: add a runtime check; or
2430 * - return FAIL.
2431 */
2432 static int
2433need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2434{
Bram Moolenaar436472f2020-02-20 22:54:43 +01002435 if (check_type(expected, actual, FALSE))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002436 return OK;
2437 if (actual->tt_type != VAR_UNKNOWN)
2438 {
2439 type_mismatch(expected, actual);
2440 return FAIL;
2441 }
2442 generate_TYPECHECK(cctx, expected, offset);
2443 return OK;
2444}
2445
2446/*
2447 * parse a list: [expr, expr]
2448 * "*arg" points to the '['.
2449 */
2450 static int
2451compile_list(char_u **arg, cctx_T *cctx)
2452{
2453 char_u *p = skipwhite(*arg + 1);
2454 int count = 0;
2455
2456 while (*p != ']')
2457 {
2458 if (*p == NUL)
Bram Moolenaara30590d2020-03-28 22:06:23 +01002459 {
2460 semsg(_(e_list_end), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002461 return FAIL;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002462 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002463 if (compile_expr1(&p, cctx) == FAIL)
2464 break;
2465 ++count;
2466 if (*p == ',')
2467 ++p;
2468 p = skipwhite(p);
2469 }
2470 *arg = p + 1;
2471
2472 generate_NEWLIST(cctx, count);
2473 return OK;
2474}
2475
2476/*
2477 * parse a lambda: {arg, arg -> expr}
2478 * "*arg" points to the '{'.
2479 */
2480 static int
2481compile_lambda(char_u **arg, cctx_T *cctx)
2482{
2483 garray_T *instr = &cctx->ctx_instr;
2484 typval_T rettv;
2485 ufunc_T *ufunc;
2486
2487 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002488 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002489 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002490
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002491 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002492 ++ufunc->uf_refcount;
2493 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002494 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002495
2496 // The function will have one line: "return {expr}".
2497 // Compile it into instructions.
2498 compile_def_function(ufunc, TRUE);
2499
2500 if (ufunc->uf_dfunc_idx >= 0)
2501 {
2502 if (ga_grow(instr, 1) == FAIL)
2503 return FAIL;
2504 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2505 return OK;
2506 }
2507 return FAIL;
2508}
2509
2510/*
2511 * Compile a lamda call: expr->{lambda}(args)
2512 * "arg" points to the "{".
2513 */
2514 static int
2515compile_lambda_call(char_u **arg, cctx_T *cctx)
2516{
2517 ufunc_T *ufunc;
2518 typval_T rettv;
2519 int argcount = 1;
2520 int ret = FAIL;
2521
2522 // Get the funcref in "rettv".
2523 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2524 return FAIL;
2525
2526 if (**arg != '(')
2527 {
2528 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002529 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002530 else
2531 semsg(_(e_missing_paren), "lambda");
2532 clear_tv(&rettv);
2533 return FAIL;
2534 }
2535
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002536 ufunc = rettv.vval.v_partial->pt_func;
2537 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002538 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002539 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002540
2541 // The function will have one line: "return {expr}".
2542 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002543 compile_def_function(ufunc, TRUE);
2544
2545 // compile the arguments
2546 *arg = skipwhite(*arg + 1);
2547 if (compile_arguments(arg, cctx, &argcount) == OK)
2548 // call the compiled function
2549 ret = generate_CALL(cctx, ufunc, argcount);
2550
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002551 return ret;
2552}
2553
2554/*
2555 * parse a dict: {'key': val} or #{key: val}
2556 * "*arg" points to the '{'.
2557 */
2558 static int
2559compile_dict(char_u **arg, cctx_T *cctx, int literal)
2560{
2561 garray_T *instr = &cctx->ctx_instr;
2562 int count = 0;
2563 dict_T *d = dict_alloc();
2564 dictitem_T *item;
2565
2566 if (d == NULL)
2567 return FAIL;
2568 *arg = skipwhite(*arg + 1);
2569 while (**arg != '}' && **arg != NUL)
2570 {
2571 char_u *key = NULL;
2572
2573 if (literal)
2574 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002575 char_u *p = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002576
2577 if (p == *arg)
2578 {
2579 semsg(_("E1014: Invalid key: %s"), *arg);
2580 return FAIL;
2581 }
2582 key = vim_strnsave(*arg, p - *arg);
2583 if (generate_PUSHS(cctx, key) == FAIL)
2584 return FAIL;
2585 *arg = p;
2586 }
2587 else
2588 {
2589 isn_T *isn;
2590
2591 if (compile_expr1(arg, cctx) == FAIL)
2592 return FAIL;
2593 // TODO: check type is string
2594 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2595 if (isn->isn_type == ISN_PUSHS)
2596 key = isn->isn_arg.string;
2597 }
2598
2599 // Check for duplicate keys, if using string keys.
2600 if (key != NULL)
2601 {
2602 item = dict_find(d, key, -1);
2603 if (item != NULL)
2604 {
2605 semsg(_(e_duplicate_key), key);
2606 goto failret;
2607 }
2608 item = dictitem_alloc(key);
2609 if (item != NULL)
2610 {
2611 item->di_tv.v_type = VAR_UNKNOWN;
2612 item->di_tv.v_lock = 0;
2613 if (dict_add(d, item) == FAIL)
2614 dictitem_free(item);
2615 }
2616 }
2617
2618 *arg = skipwhite(*arg);
2619 if (**arg != ':')
2620 {
2621 semsg(_(e_missing_dict_colon), *arg);
2622 return FAIL;
2623 }
2624
2625 *arg = skipwhite(*arg + 1);
2626 if (compile_expr1(arg, cctx) == FAIL)
2627 return FAIL;
2628 ++count;
2629
2630 if (**arg == '}')
2631 break;
2632 if (**arg != ',')
2633 {
2634 semsg(_(e_missing_dict_comma), *arg);
2635 goto failret;
2636 }
2637 *arg = skipwhite(*arg + 1);
2638 }
2639
2640 if (**arg != '}')
2641 {
2642 semsg(_(e_missing_dict_end), *arg);
2643 goto failret;
2644 }
2645 *arg = *arg + 1;
2646
2647 dict_unref(d);
2648 return generate_NEWDICT(cctx, count);
2649
2650failret:
2651 dict_unref(d);
2652 return FAIL;
2653}
2654
2655/*
2656 * Compile "&option".
2657 */
2658 static int
2659compile_get_option(char_u **arg, cctx_T *cctx)
2660{
2661 typval_T rettv;
2662 char_u *start = *arg;
2663 int ret;
2664
2665 // parse the option and get the current value to get the type.
2666 rettv.v_type = VAR_UNKNOWN;
2667 ret = get_option_tv(arg, &rettv, TRUE);
2668 if (ret == OK)
2669 {
2670 // include the '&' in the name, get_option_tv() expects it.
2671 char_u *name = vim_strnsave(start, *arg - start);
2672 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2673
2674 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2675 vim_free(name);
2676 }
2677 clear_tv(&rettv);
2678
2679 return ret;
2680}
2681
2682/*
2683 * Compile "$VAR".
2684 */
2685 static int
2686compile_get_env(char_u **arg, cctx_T *cctx)
2687{
2688 char_u *start = *arg;
2689 int len;
2690 int ret;
2691 char_u *name;
2692
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002693 ++*arg;
2694 len = get_env_len(arg);
2695 if (len == 0)
2696 {
2697 semsg(_(e_syntax_at), start - 1);
2698 return FAIL;
2699 }
2700
2701 // include the '$' in the name, get_env_tv() expects it.
2702 name = vim_strnsave(start, len + 1);
2703 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2704 vim_free(name);
2705 return ret;
2706}
2707
2708/*
2709 * Compile "@r".
2710 */
2711 static int
2712compile_get_register(char_u **arg, cctx_T *cctx)
2713{
2714 int ret;
2715
2716 ++*arg;
2717 if (**arg == NUL)
2718 {
2719 semsg(_(e_syntax_at), *arg - 1);
2720 return FAIL;
2721 }
2722 if (!valid_yank_reg(**arg, TRUE))
2723 {
2724 emsg_invreg(**arg);
2725 return FAIL;
2726 }
2727 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2728 ++*arg;
2729 return ret;
2730}
2731
2732/*
2733 * Apply leading '!', '-' and '+' to constant "rettv".
2734 */
2735 static int
2736apply_leader(typval_T *rettv, char_u *start, char_u *end)
2737{
2738 char_u *p = end;
2739
2740 // this works from end to start
2741 while (p > start)
2742 {
2743 --p;
2744 if (*p == '-' || *p == '+')
2745 {
2746 // only '-' has an effect, for '+' we only check the type
2747#ifdef FEAT_FLOAT
2748 if (rettv->v_type == VAR_FLOAT)
2749 {
2750 if (*p == '-')
2751 rettv->vval.v_float = -rettv->vval.v_float;
2752 }
2753 else
2754#endif
2755 {
2756 varnumber_T val;
2757 int error = FALSE;
2758
2759 // tv_get_number_chk() accepts a string, but we don't want that
2760 // here
2761 if (check_not_string(rettv) == FAIL)
2762 return FAIL;
2763 val = tv_get_number_chk(rettv, &error);
2764 clear_tv(rettv);
2765 if (error)
2766 return FAIL;
2767 if (*p == '-')
2768 val = -val;
2769 rettv->v_type = VAR_NUMBER;
2770 rettv->vval.v_number = val;
2771 }
2772 }
2773 else
2774 {
2775 int v = tv2bool(rettv);
2776
2777 // '!' is permissive in the type.
2778 clear_tv(rettv);
2779 rettv->v_type = VAR_BOOL;
2780 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
2781 }
2782 }
2783 return OK;
2784}
2785
2786/*
2787 * Recognize v: variables that are constants and set "rettv".
2788 */
2789 static void
2790get_vim_constant(char_u **arg, typval_T *rettv)
2791{
2792 if (STRNCMP(*arg, "v:true", 6) == 0)
2793 {
2794 rettv->v_type = VAR_BOOL;
2795 rettv->vval.v_number = VVAL_TRUE;
2796 *arg += 6;
2797 }
2798 else if (STRNCMP(*arg, "v:false", 7) == 0)
2799 {
2800 rettv->v_type = VAR_BOOL;
2801 rettv->vval.v_number = VVAL_FALSE;
2802 *arg += 7;
2803 }
2804 else if (STRNCMP(*arg, "v:null", 6) == 0)
2805 {
2806 rettv->v_type = VAR_SPECIAL;
2807 rettv->vval.v_number = VVAL_NULL;
2808 *arg += 6;
2809 }
2810 else if (STRNCMP(*arg, "v:none", 6) == 0)
2811 {
2812 rettv->v_type = VAR_SPECIAL;
2813 rettv->vval.v_number = VVAL_NONE;
2814 *arg += 6;
2815 }
2816}
2817
2818/*
2819 * Compile code to apply '-', '+' and '!'.
2820 */
2821 static int
2822compile_leader(cctx_T *cctx, char_u *start, char_u *end)
2823{
2824 char_u *p = end;
2825
2826 // this works from end to start
2827 while (p > start)
2828 {
2829 --p;
2830 if (*p == '-' || *p == '+')
2831 {
2832 int negate = *p == '-';
2833 isn_T *isn;
2834
2835 // TODO: check type
2836 while (p > start && (p[-1] == '-' || p[-1] == '+'))
2837 {
2838 --p;
2839 if (*p == '-')
2840 negate = !negate;
2841 }
2842 // only '-' has an effect, for '+' we only check the type
2843 if (negate)
2844 isn = generate_instr(cctx, ISN_NEGATENR);
2845 else
2846 isn = generate_instr(cctx, ISN_CHECKNR);
2847 if (isn == NULL)
2848 return FAIL;
2849 }
2850 else
2851 {
2852 int invert = TRUE;
2853
2854 while (p > start && p[-1] == '!')
2855 {
2856 --p;
2857 invert = !invert;
2858 }
2859 if (generate_2BOOL(cctx, invert) == FAIL)
2860 return FAIL;
2861 }
2862 }
2863 return OK;
2864}
2865
2866/*
2867 * Compile whatever comes after "name" or "name()".
2868 */
2869 static int
2870compile_subscript(
2871 char_u **arg,
2872 cctx_T *cctx,
2873 char_u **start_leader,
2874 char_u *end_leader)
2875{
2876 for (;;)
2877 {
2878 if (**arg == '(')
2879 {
2880 int argcount = 0;
2881
2882 // funcref(arg)
2883 *arg = skipwhite(*arg + 1);
2884 if (compile_arguments(arg, cctx, &argcount) == FAIL)
2885 return FAIL;
2886 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
2887 return FAIL;
2888 }
2889 else if (**arg == '-' && (*arg)[1] == '>')
2890 {
2891 char_u *p;
2892
2893 // something->method()
2894 // Apply the '!', '-' and '+' first:
2895 // -1.0->func() works like (-1.0)->func()
2896 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
2897 return FAIL;
2898 *start_leader = end_leader; // don't apply again later
2899
2900 *arg = skipwhite(*arg + 2);
2901 if (**arg == '{')
2902 {
2903 // lambda call: list->{lambda}
2904 if (compile_lambda_call(arg, cctx) == FAIL)
2905 return FAIL;
2906 }
2907 else
2908 {
2909 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02002910 p = *arg;
2911 if (ASCII_ISALPHA(*p) && p[1] == ':')
2912 p += 2;
2913 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002914 ;
2915 if (*p != '(')
2916 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02002917 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002918 return FAIL;
2919 }
2920 // TODO: base value may not be the first argument
2921 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
2922 return FAIL;
2923 }
2924 }
2925 else if (**arg == '[')
2926 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01002927 garray_T *stack;
2928 type_T **typep;
2929
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002930 // list index: list[123]
2931 // TODO: more arguments
2932 // TODO: dict member dict['name']
2933 *arg = skipwhite(*arg + 1);
2934 if (compile_expr1(arg, cctx) == FAIL)
2935 return FAIL;
2936
2937 if (**arg != ']')
2938 {
2939 emsg(_(e_missbrac));
2940 return FAIL;
2941 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01002942 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002943
2944 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
2945 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01002946 stack = &cctx->ctx_type_stack;
2947 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
2948 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
2949 {
2950 emsg(_(e_listreq));
2951 return FAIL;
2952 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01002953 if ((*typep)->tt_type == VAR_LIST)
2954 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002955 }
2956 else if (**arg == '.' && (*arg)[1] != '.')
2957 {
2958 char_u *p;
2959
2960 ++*arg;
2961 p = *arg;
2962 // dictionary member: dict.name
2963 if (eval_isnamec1(*p))
2964 while (eval_isnamec(*p))
2965 MB_PTR_ADV(p);
2966 if (p == *arg)
2967 {
2968 semsg(_(e_syntax_at), *arg);
2969 return FAIL;
2970 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002971 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
2972 return FAIL;
2973 *arg = p;
2974 }
2975 else
2976 break;
2977 }
2978
2979 // TODO - see handle_subscript():
2980 // Turn "dict.Func" into a partial for "Func" bound to "dict".
2981 // Don't do this when "Func" is already a partial that was bound
2982 // explicitly (pt_auto is FALSE).
2983
2984 return OK;
2985}
2986
2987/*
2988 * Compile an expression at "*p" and add instructions to "instr".
2989 * "p" is advanced until after the expression, skipping white space.
2990 *
2991 * This is the equivalent of eval1(), eval2(), etc.
2992 */
2993
2994/*
2995 * number number constant
2996 * 0zFFFFFFFF Blob constant
2997 * "string" string constant
2998 * 'string' literal string constant
2999 * &option-name option value
3000 * @r register contents
3001 * identifier variable value
3002 * function() function call
3003 * $VAR environment variable
3004 * (expression) nested expression
3005 * [expr, expr] List
3006 * {key: val, key: val} Dictionary
3007 * #{key: val, key: val} Dictionary with literal keys
3008 *
3009 * Also handle:
3010 * ! in front logical NOT
3011 * - in front unary minus
3012 * + in front unary plus (ignored)
3013 * trailing (arg) funcref/partial call
3014 * trailing [] subscript in String or List
3015 * trailing .name entry in Dictionary
3016 * trailing ->name() method call
3017 */
3018 static int
3019compile_expr7(char_u **arg, cctx_T *cctx)
3020{
3021 typval_T rettv;
3022 char_u *start_leader, *end_leader;
3023 int ret = OK;
3024
3025 /*
3026 * Skip '!', '-' and '+' characters. They are handled later.
3027 */
3028 start_leader = *arg;
3029 while (**arg == '!' || **arg == '-' || **arg == '+')
3030 *arg = skipwhite(*arg + 1);
3031 end_leader = *arg;
3032
3033 rettv.v_type = VAR_UNKNOWN;
3034 switch (**arg)
3035 {
3036 /*
3037 * Number constant.
3038 */
3039 case '0': // also for blob starting with 0z
3040 case '1':
3041 case '2':
3042 case '3':
3043 case '4':
3044 case '5':
3045 case '6':
3046 case '7':
3047 case '8':
3048 case '9':
3049 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3050 return FAIL;
3051 break;
3052
3053 /*
3054 * String constant: "string".
3055 */
3056 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3057 return FAIL;
3058 break;
3059
3060 /*
3061 * Literal string constant: 'str''ing'.
3062 */
3063 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3064 return FAIL;
3065 break;
3066
3067 /*
3068 * Constant Vim variable.
3069 */
3070 case 'v': get_vim_constant(arg, &rettv);
3071 ret = NOTDONE;
3072 break;
3073
3074 /*
3075 * List: [expr, expr]
3076 */
3077 case '[': ret = compile_list(arg, cctx);
3078 break;
3079
3080 /*
3081 * Dictionary: #{key: val, key: val}
3082 */
3083 case '#': if ((*arg)[1] == '{')
3084 {
3085 ++*arg;
3086 ret = compile_dict(arg, cctx, TRUE);
3087 }
3088 else
3089 ret = NOTDONE;
3090 break;
3091
3092 /*
3093 * Lambda: {arg, arg -> expr}
3094 * Dictionary: {'key': val, 'key': val}
3095 */
3096 case '{': {
3097 char_u *start = skipwhite(*arg + 1);
3098
3099 // Find out what comes after the arguments.
3100 ret = get_function_args(&start, '-', NULL,
3101 NULL, NULL, NULL, TRUE);
3102 if (ret != FAIL && *start == '>')
3103 ret = compile_lambda(arg, cctx);
3104 else
3105 ret = compile_dict(arg, cctx, FALSE);
3106 }
3107 break;
3108
3109 /*
3110 * Option value: &name
3111 */
3112 case '&': ret = compile_get_option(arg, cctx);
3113 break;
3114
3115 /*
3116 * Environment variable: $VAR.
3117 */
3118 case '$': ret = compile_get_env(arg, cctx);
3119 break;
3120
3121 /*
3122 * Register contents: @r.
3123 */
3124 case '@': ret = compile_get_register(arg, cctx);
3125 break;
3126 /*
3127 * nested expression: (expression).
3128 */
3129 case '(': *arg = skipwhite(*arg + 1);
3130 ret = compile_expr1(arg, cctx); // recursive!
3131 *arg = skipwhite(*arg);
3132 if (**arg == ')')
3133 ++*arg;
3134 else if (ret == OK)
3135 {
3136 emsg(_(e_missing_close));
3137 ret = FAIL;
3138 }
3139 break;
3140
3141 default: ret = NOTDONE;
3142 break;
3143 }
3144 if (ret == FAIL)
3145 return FAIL;
3146
3147 if (rettv.v_type != VAR_UNKNOWN)
3148 {
3149 // apply the '!', '-' and '+' before the constant
3150 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3151 {
3152 clear_tv(&rettv);
3153 return FAIL;
3154 }
3155 start_leader = end_leader; // don't apply again below
3156
3157 // push constant
3158 switch (rettv.v_type)
3159 {
3160 case VAR_BOOL:
3161 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3162 break;
3163 case VAR_SPECIAL:
3164 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3165 break;
3166 case VAR_NUMBER:
3167 generate_PUSHNR(cctx, rettv.vval.v_number);
3168 break;
3169#ifdef FEAT_FLOAT
3170 case VAR_FLOAT:
3171 generate_PUSHF(cctx, rettv.vval.v_float);
3172 break;
3173#endif
3174 case VAR_BLOB:
3175 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3176 rettv.vval.v_blob = NULL;
3177 break;
3178 case VAR_STRING:
3179 generate_PUSHS(cctx, rettv.vval.v_string);
3180 rettv.vval.v_string = NULL;
3181 break;
3182 default:
3183 iemsg("constant type missing");
3184 return FAIL;
3185 }
3186 }
3187 else if (ret == NOTDONE)
3188 {
3189 char_u *p;
3190 int r;
3191
3192 if (!eval_isnamec1(**arg))
3193 {
3194 semsg(_("E1015: Name expected: %s"), *arg);
3195 return FAIL;
3196 }
3197
3198 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003199 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003200 if (*p == '(')
3201 r = compile_call(arg, p - *arg, cctx, 0);
3202 else
3203 r = compile_load(arg, p, cctx, TRUE);
3204 if (r == FAIL)
3205 return FAIL;
3206 }
3207
3208 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3209 return FAIL;
3210
3211 // Now deal with prefixed '-', '+' and '!', if not done already.
3212 return compile_leader(cctx, start_leader, end_leader);
3213}
3214
3215/*
3216 * * number multiplication
3217 * / number division
3218 * % number modulo
3219 */
3220 static int
3221compile_expr6(char_u **arg, cctx_T *cctx)
3222{
3223 char_u *op;
3224
3225 // get the first variable
3226 if (compile_expr7(arg, cctx) == FAIL)
3227 return FAIL;
3228
3229 /*
3230 * Repeat computing, until no "*", "/" or "%" is following.
3231 */
3232 for (;;)
3233 {
3234 op = skipwhite(*arg);
3235 if (*op != '*' && *op != '/' && *op != '%')
3236 break;
3237 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[1]))
3238 {
3239 char_u buf[3];
3240
3241 vim_strncpy(buf, op, 1);
3242 semsg(_(e_white_both), buf);
3243 }
3244 *arg = skipwhite(op + 1);
3245
3246 // get the second variable
3247 if (compile_expr7(arg, cctx) == FAIL)
3248 return FAIL;
3249
3250 generate_two_op(cctx, op);
3251 }
3252
3253 return OK;
3254}
3255
3256/*
3257 * + number addition
3258 * - number subtraction
3259 * .. string concatenation
3260 */
3261 static int
3262compile_expr5(char_u **arg, cctx_T *cctx)
3263{
3264 char_u *op;
3265 int oplen;
3266
3267 // get the first variable
3268 if (compile_expr6(arg, cctx) == FAIL)
3269 return FAIL;
3270
3271 /*
3272 * Repeat computing, until no "+", "-" or ".." is following.
3273 */
3274 for (;;)
3275 {
3276 op = skipwhite(*arg);
3277 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3278 break;
3279 oplen = (*op == '.' ? 2 : 1);
3280
3281 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[oplen]))
3282 {
3283 char_u buf[3];
3284
3285 vim_strncpy(buf, op, oplen);
3286 semsg(_(e_white_both), buf);
3287 }
3288
3289 *arg = skipwhite(op + oplen);
3290
3291 // get the second variable
3292 if (compile_expr6(arg, cctx) == FAIL)
3293 return FAIL;
3294
3295 if (*op == '.')
3296 {
3297 if (may_generate_2STRING(-2, cctx) == FAIL
3298 || may_generate_2STRING(-1, cctx) == FAIL)
3299 return FAIL;
3300 generate_instr_drop(cctx, ISN_CONCAT, 1);
3301 }
3302 else
3303 generate_two_op(cctx, op);
3304 }
3305
3306 return OK;
3307}
3308
Bram Moolenaar080457c2020-03-03 21:53:32 +01003309 static exptype_T
3310get_compare_type(char_u *p, int *len, int *type_is)
3311{
3312 exptype_T type = EXPR_UNKNOWN;
3313 int i;
3314
3315 switch (p[0])
3316 {
3317 case '=': if (p[1] == '=')
3318 type = EXPR_EQUAL;
3319 else if (p[1] == '~')
3320 type = EXPR_MATCH;
3321 break;
3322 case '!': if (p[1] == '=')
3323 type = EXPR_NEQUAL;
3324 else if (p[1] == '~')
3325 type = EXPR_NOMATCH;
3326 break;
3327 case '>': if (p[1] != '=')
3328 {
3329 type = EXPR_GREATER;
3330 *len = 1;
3331 }
3332 else
3333 type = EXPR_GEQUAL;
3334 break;
3335 case '<': if (p[1] != '=')
3336 {
3337 type = EXPR_SMALLER;
3338 *len = 1;
3339 }
3340 else
3341 type = EXPR_SEQUAL;
3342 break;
3343 case 'i': if (p[1] == 's')
3344 {
3345 // "is" and "isnot"; but not a prefix of a name
3346 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3347 *len = 5;
3348 i = p[*len];
3349 if (!isalnum(i) && i != '_')
3350 {
3351 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3352 *type_is = TRUE;
3353 }
3354 }
3355 break;
3356 }
3357 return type;
3358}
3359
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003360/*
3361 * expr5a == expr5b
3362 * expr5a =~ expr5b
3363 * expr5a != expr5b
3364 * expr5a !~ expr5b
3365 * expr5a > expr5b
3366 * expr5a >= expr5b
3367 * expr5a < expr5b
3368 * expr5a <= expr5b
3369 * expr5a is expr5b
3370 * expr5a isnot expr5b
3371 *
3372 * Produces instructions:
3373 * EVAL expr5a Push result of "expr5a"
3374 * EVAL expr5b Push result of "expr5b"
3375 * COMPARE one of the compare instructions
3376 */
3377 static int
3378compile_expr4(char_u **arg, cctx_T *cctx)
3379{
3380 exptype_T type = EXPR_UNKNOWN;
3381 char_u *p;
3382 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003383 int type_is = FALSE;
3384
3385 // get the first variable
3386 if (compile_expr5(arg, cctx) == FAIL)
3387 return FAIL;
3388
3389 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003390 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003391
3392 /*
3393 * If there is a comparative operator, use it.
3394 */
3395 if (type != EXPR_UNKNOWN)
3396 {
3397 int ic = FALSE; // Default: do not ignore case
3398
3399 if (type_is && (p[len] == '?' || p[len] == '#'))
3400 {
3401 semsg(_(e_invexpr2), *arg);
3402 return FAIL;
3403 }
3404 // extra question mark appended: ignore case
3405 if (p[len] == '?')
3406 {
3407 ic = TRUE;
3408 ++len;
3409 }
3410 // extra '#' appended: match case (ignored)
3411 else if (p[len] == '#')
3412 ++len;
3413 // nothing appended: match case
3414
3415 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[len]))
3416 {
3417 char_u buf[7];
3418
3419 vim_strncpy(buf, p, len);
3420 semsg(_(e_white_both), buf);
3421 }
3422
3423 // get the second variable
3424 *arg = skipwhite(p + len);
3425 if (compile_expr5(arg, cctx) == FAIL)
3426 return FAIL;
3427
3428 generate_COMPARE(cctx, type, ic);
3429 }
3430
3431 return OK;
3432}
3433
3434/*
3435 * Compile || or &&.
3436 */
3437 static int
3438compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3439{
3440 char_u *p = skipwhite(*arg);
3441 int opchar = *op;
3442
3443 if (p[0] == opchar && p[1] == opchar)
3444 {
3445 garray_T *instr = &cctx->ctx_instr;
3446 garray_T end_ga;
3447
3448 /*
3449 * Repeat until there is no following "||" or "&&"
3450 */
3451 ga_init2(&end_ga, sizeof(int), 10);
3452 while (p[0] == opchar && p[1] == opchar)
3453 {
3454 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
3455 semsg(_(e_white_both), op);
3456
3457 if (ga_grow(&end_ga, 1) == FAIL)
3458 {
3459 ga_clear(&end_ga);
3460 return FAIL;
3461 }
3462 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3463 ++end_ga.ga_len;
3464 generate_JUMP(cctx, opchar == '|'
3465 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3466
3467 // eval the next expression
3468 *arg = skipwhite(p + 2);
3469 if ((opchar == '|' ? compile_expr3(arg, cctx)
3470 : compile_expr4(arg, cctx)) == FAIL)
3471 {
3472 ga_clear(&end_ga);
3473 return FAIL;
3474 }
3475 p = skipwhite(*arg);
3476 }
3477
3478 // Fill in the end label in all jumps.
3479 while (end_ga.ga_len > 0)
3480 {
3481 isn_T *isn;
3482
3483 --end_ga.ga_len;
3484 isn = ((isn_T *)instr->ga_data)
3485 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3486 isn->isn_arg.jump.jump_where = instr->ga_len;
3487 }
3488 ga_clear(&end_ga);
3489 }
3490
3491 return OK;
3492}
3493
3494/*
3495 * expr4a && expr4a && expr4a logical AND
3496 *
3497 * Produces instructions:
3498 * EVAL expr4a Push result of "expr4a"
3499 * JUMP_AND_KEEP_IF_FALSE end
3500 * EVAL expr4b Push result of "expr4b"
3501 * JUMP_AND_KEEP_IF_FALSE end
3502 * EVAL expr4c Push result of "expr4c"
3503 * end:
3504 */
3505 static int
3506compile_expr3(char_u **arg, cctx_T *cctx)
3507{
3508 // get the first variable
3509 if (compile_expr4(arg, cctx) == FAIL)
3510 return FAIL;
3511
3512 // || and && work almost the same
3513 return compile_and_or(arg, cctx, "&&");
3514}
3515
3516/*
3517 * expr3a || expr3b || expr3c logical OR
3518 *
3519 * Produces instructions:
3520 * EVAL expr3a Push result of "expr3a"
3521 * JUMP_AND_KEEP_IF_TRUE end
3522 * EVAL expr3b Push result of "expr3b"
3523 * JUMP_AND_KEEP_IF_TRUE end
3524 * EVAL expr3c Push result of "expr3c"
3525 * end:
3526 */
3527 static int
3528compile_expr2(char_u **arg, cctx_T *cctx)
3529{
3530 // eval the first expression
3531 if (compile_expr3(arg, cctx) == FAIL)
3532 return FAIL;
3533
3534 // || and && work almost the same
3535 return compile_and_or(arg, cctx, "||");
3536}
3537
3538/*
3539 * Toplevel expression: expr2 ? expr1a : expr1b
3540 *
3541 * Produces instructions:
3542 * EVAL expr2 Push result of "expr"
3543 * JUMP_IF_FALSE alt jump if false
3544 * EVAL expr1a
3545 * JUMP_ALWAYS end
3546 * alt: EVAL expr1b
3547 * end:
3548 */
3549 static int
3550compile_expr1(char_u **arg, cctx_T *cctx)
3551{
3552 char_u *p;
3553
3554 // evaluate the first expression
3555 if (compile_expr2(arg, cctx) == FAIL)
3556 return FAIL;
3557
3558 p = skipwhite(*arg);
3559 if (*p == '?')
3560 {
3561 garray_T *instr = &cctx->ctx_instr;
3562 garray_T *stack = &cctx->ctx_type_stack;
3563 int alt_idx = instr->ga_len;
3564 int end_idx;
3565 isn_T *isn;
3566 type_T *type1;
3567 type_T *type2;
3568
3569 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3570 semsg(_(e_white_both), "?");
3571
3572 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3573
3574 // evaluate the second expression; any type is accepted
3575 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003576 if (compile_expr1(arg, cctx) == FAIL)
3577 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003578
3579 // remember the type and drop it
3580 --stack->ga_len;
3581 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3582
3583 end_idx = instr->ga_len;
3584 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3585
3586 // jump here from JUMP_IF_FALSE
3587 isn = ((isn_T *)instr->ga_data) + alt_idx;
3588 isn->isn_arg.jump.jump_where = instr->ga_len;
3589
3590 // Check for the ":".
3591 p = skipwhite(*arg);
3592 if (*p != ':')
3593 {
3594 emsg(_(e_missing_colon));
3595 return FAIL;
3596 }
3597 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
3598 semsg(_(e_white_both), ":");
3599
3600 // evaluate the third expression
3601 *arg = skipwhite(p + 1);
Bram Moolenaara6d53682020-01-28 23:04:06 +01003602 if (compile_expr1(arg, cctx) == FAIL)
3603 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003604
3605 // If the types differ, the result has a more generic type.
3606 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003607 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003608
3609 // jump here from JUMP_ALWAYS
3610 isn = ((isn_T *)instr->ga_data) + end_idx;
3611 isn->isn_arg.jump.jump_where = instr->ga_len;
3612 }
3613 return OK;
3614}
3615
3616/*
3617 * compile "return [expr]"
3618 */
3619 static char_u *
3620compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3621{
3622 char_u *p = arg;
3623 garray_T *stack = &cctx->ctx_type_stack;
3624 type_T *stack_type;
3625
3626 if (*p != NUL && *p != '|' && *p != '\n')
3627 {
3628 // compile return argument into instructions
3629 if (compile_expr1(&p, cctx) == FAIL)
3630 return NULL;
3631
3632 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3633 if (set_return_type)
3634 cctx->ctx_ufunc->uf_ret_type = stack_type;
3635 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3636 == FAIL)
3637 return NULL;
3638 }
3639 else
3640 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003641 // "set_return_type" cannot be TRUE, only used for a lambda which
3642 // always has an argument.
3643 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003644 {
3645 emsg(_("E1003: Missing return value"));
3646 return NULL;
3647 }
3648
3649 // No argument, return zero.
3650 generate_PUSHNR(cctx, 0);
3651 }
3652
3653 if (generate_instr(cctx, ISN_RETURN) == NULL)
3654 return NULL;
3655
3656 // "return val | endif" is possible
3657 return skipwhite(p);
3658}
3659
3660/*
3661 * Return the length of an assignment operator, or zero if there isn't one.
3662 */
3663 int
3664assignment_len(char_u *p, int *heredoc)
3665{
3666 if (*p == '=')
3667 {
3668 if (p[1] == '<' && p[2] == '<')
3669 {
3670 *heredoc = TRUE;
3671 return 3;
3672 }
3673 return 1;
3674 }
3675 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3676 return 2;
3677 if (STRNCMP(p, "..=", 3) == 0)
3678 return 3;
3679 return 0;
3680}
3681
3682// words that cannot be used as a variable
3683static char *reserved[] = {
3684 "true",
3685 "false",
3686 NULL
3687};
3688
3689/*
3690 * Get a line for "=<<".
3691 * Return a pointer to the line in allocated memory.
3692 * Return NULL for end-of-file or some error.
3693 */
3694 static char_u *
3695heredoc_getline(
3696 int c UNUSED,
3697 void *cookie,
3698 int indent UNUSED,
3699 int do_concat UNUSED)
3700{
3701 cctx_T *cctx = (cctx_T *)cookie;
3702
3703 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003704 {
3705 iemsg("Heredoc got to end");
3706 return NULL;
3707 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003708 ++cctx->ctx_lnum;
3709 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3710 [cctx->ctx_lnum]);
3711}
3712
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003713typedef enum {
3714 dest_local,
3715 dest_option,
3716 dest_env,
3717 dest_global,
3718 dest_vimvar,
3719 dest_script,
3720 dest_reg,
3721} assign_dest_T;
3722
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003723/*
3724 * compile "let var [= expr]", "const var = expr" and "var = expr"
3725 * "arg" points to "var".
3726 */
3727 static char_u *
3728compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3729{
3730 char_u *p;
3731 char_u *ret = NULL;
3732 int var_count = 0;
3733 int semicolon = 0;
3734 size_t varlen;
3735 garray_T *instr = &cctx->ctx_instr;
3736 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02003737 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003738 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003739 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003740 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003741 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003742 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003743 int oplen = 0;
3744 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003745 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003746 lvar_T *lvar;
3747 char_u *name;
3748 char_u *sp;
3749 int has_type = FALSE;
3750 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
3751 int instr_count = -1;
3752
3753 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
3754 if (p == NULL)
3755 return NULL;
3756 if (var_count > 0)
3757 {
3758 // TODO: let [var, var] = list
3759 emsg("Cannot handle a list yet");
3760 return NULL;
3761 }
3762
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003763 // "a: type" is declaring variable "a" with a type, not "a:".
3764 if (is_decl && p == arg + 2 && p[-1] == ':')
3765 --p;
3766
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003767 varlen = p - arg;
3768 name = vim_strnsave(arg, (int)varlen);
3769 if (name == NULL)
3770 return NULL;
3771
Bram Moolenaar080457c2020-03-03 21:53:32 +01003772 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003773 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003774 if (*arg == '&')
3775 {
3776 int cc;
3777 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003778
Bram Moolenaar080457c2020-03-03 21:53:32 +01003779 dest = dest_option;
3780 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003781 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003782 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003783 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003784 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003785 if (is_decl)
3786 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003787 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003788 goto theend;
3789 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01003790 p = arg;
3791 p = find_option_end(&p, &opt_flags);
3792 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003793 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003794 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01003795 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003796 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003797 }
3798 cc = *p;
3799 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01003800 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003801 *p = cc;
3802 if (opt_type == -3)
3803 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003804 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003805 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003806 }
3807 if (opt_type == -2 || opt_type == 0)
3808 type = &t_string;
3809 else
3810 type = &t_number; // both number and boolean option
3811 }
3812 else if (*arg == '$')
3813 {
3814 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003815 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003816 if (is_decl)
3817 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003818 semsg(_("E1065: Cannot declare an environment variable: %s"),
3819 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003820 goto theend;
3821 }
3822 }
3823 else if (*arg == '@')
3824 {
3825 if (!valid_yank_reg(arg[1], TRUE))
3826 {
3827 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02003828 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003829 }
3830 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003831 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01003832 if (is_decl)
3833 {
3834 semsg(_("E1066: Cannot declare a register: %s"), name);
3835 goto theend;
3836 }
3837 }
3838 else if (STRNCMP(arg, "g:", 2) == 0)
3839 {
3840 dest = dest_global;
3841 if (is_decl)
3842 {
3843 semsg(_("E1016: Cannot declare a global variable: %s"), name);
3844 goto theend;
3845 }
3846 }
3847 else if (STRNCMP(arg, "v:", 2) == 0)
3848 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02003849 typval_T *vtv;
3850
Bram Moolenaar080457c2020-03-03 21:53:32 +01003851 vimvaridx = find_vim_var(name + 2);
3852 if (vimvaridx < 0)
3853 {
3854 semsg(_(e_var_notfound), arg);
3855 goto theend;
3856 }
3857 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003858 vtv = get_vim_var_tv(vimvaridx);
3859 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003860 if (is_decl)
3861 {
3862 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
3863 goto theend;
3864 }
3865 }
3866 else
3867 {
3868 for (idx = 0; reserved[idx] != NULL; ++idx)
3869 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003870 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003871 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003872 goto theend;
3873 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01003874
3875 idx = lookup_local(arg, varlen, cctx);
3876 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003877 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01003878 if (is_decl)
3879 {
3880 semsg(_("E1017: Variable already declared: %s"), name);
3881 goto theend;
3882 }
3883 else
3884 {
3885 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3886 if (lvar->lv_const)
3887 {
3888 semsg(_("E1018: Cannot assign to a constant: %s"), name);
3889 goto theend;
3890 }
3891 }
3892 }
3893 else if (STRNCMP(arg, "s:", 2) == 0
3894 || lookup_script(arg, varlen) == OK
3895 || find_imported(arg, varlen, cctx) != NULL)
3896 {
3897 dest = dest_script;
3898 if (is_decl)
3899 {
3900 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003901 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003902 goto theend;
3903 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003904 }
3905 }
3906 }
3907
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003908 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003909 {
3910 if (is_decl && *p == ':')
3911 {
3912 // parse optional type: "let var: type = expr"
3913 p = skipwhite(p + 1);
3914 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003915 has_type = TRUE;
3916 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02003917 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003918 {
3919 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
3920 type = lvar->lv_type;
3921 }
3922 }
3923
3924 sp = p;
3925 p = skipwhite(p);
3926 op = p;
3927 oplen = assignment_len(p, &heredoc);
3928 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
3929 {
3930 char_u buf[4];
3931
3932 vim_strncpy(buf, op, oplen);
3933 semsg(_(e_white_both), buf);
3934 }
3935
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003936 if (oplen == 3 && !heredoc && dest != dest_global
3937 && type->tt_type != VAR_STRING && type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003938 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01003939 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003940 goto theend;
3941 }
3942
Bram Moolenaar080457c2020-03-03 21:53:32 +01003943 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003944 {
3945 if (oplen > 1 && !heredoc)
3946 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003947 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003948 semsg(_("E1020: cannot use an operator on a new variable: %s"),
3949 name);
3950 goto theend;
3951 }
3952
3953 // new local variable
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02003954 if ((type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
3955 && var_check_func_name(name, TRUE))
3956 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003957 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
3958 if (idx < 0)
3959 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02003960 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003961 }
3962
3963 if (heredoc)
3964 {
3965 list_T *l;
3966 listitem_T *li;
3967
3968 // [let] varname =<< [trim] {end}
3969 eap->getline = heredoc_getline;
3970 eap->cookie = cctx;
3971 l = heredoc_get(eap, op + 3);
3972
3973 // Push each line and the create the list.
3974 for (li = l->lv_first; li != NULL; li = li->li_next)
3975 {
3976 generate_PUSHS(cctx, li->li_tv.vval.v_string);
3977 li->li_tv.vval.v_string = NULL;
3978 }
3979 generate_NEWLIST(cctx, l->lv_len);
3980 type = &t_list_string;
3981 list_free(l);
3982 p += STRLEN(p);
3983 }
3984 else if (oplen > 0)
3985 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02003986 int r;
3987 type_T *stacktype;
3988 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02003989
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003990 // for "+=", "*=", "..=" etc. first load the current value
3991 if (*op != '=')
3992 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003993 switch (dest)
3994 {
3995 case dest_option:
3996 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02003997 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003998 break;
3999 case dest_global:
4000 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4001 break;
4002 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004003 compile_load_scriptvar(cctx,
4004 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004005 break;
4006 case dest_env:
4007 // Include $ in the name here
4008 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4009 break;
4010 case dest_reg:
4011 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4012 break;
4013 case dest_vimvar:
4014 generate_LOADV(cctx, name + 2, TRUE);
4015 break;
4016 case dest_local:
4017 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4018 break;
4019 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004020 }
4021
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004022 // Compile the expression. Temporarily hide the new local variable
4023 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004024 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004025 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004026 instr_count = instr->ga_len;
4027 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004028 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004029 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004030 ++cctx->ctx_locals.ga_len;
4031 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004032 goto theend;
4033
Bram Moolenaara8c17702020-04-01 21:17:24 +02004034 stack = &cctx->ctx_type_stack;
Bram Moolenaarea94fbe2020-04-01 22:36:49 +02004035 stacktype = stack->ga_len == 0 ? &t_void
4036 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004037 if (idx >= 0 && (is_decl || !has_type))
4038 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004039 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004040 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004041 {
4042 if (stacktype->tt_type == VAR_VOID)
4043 {
4044 emsg(_("E1031: Cannot use void value"));
4045 goto theend;
4046 }
4047 else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004048 {
4049 // An empty list or dict has a &t_void member, for a
4050 // variable that implies &t_any.
4051 if (stacktype == &t_list_empty)
4052 lvar->lv_type = &t_list_any;
4053 else if (stacktype == &t_dict_empty)
4054 lvar->lv_type = &t_dict_any;
4055 else
4056 lvar->lv_type = stacktype;
4057 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004058 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004059 else if (check_type(lvar->lv_type, stacktype, TRUE) == FAIL)
4060 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004061 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004062 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
4063 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004064 }
4065 else if (cmdidx == CMD_const)
4066 {
4067 emsg(_("E1021: const requires a value"));
4068 goto theend;
4069 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004070 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004071 {
4072 emsg(_("E1022: type or initialization required"));
4073 goto theend;
4074 }
4075 else
4076 {
4077 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004078 if (ga_grow(instr, 1) == FAIL)
4079 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004080 switch (type->tt_type)
4081 {
4082 case VAR_BOOL:
4083 generate_PUSHBOOL(cctx, VVAL_FALSE);
4084 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004085 case VAR_FLOAT:
4086#ifdef FEAT_FLOAT
4087 generate_PUSHF(cctx, 0.0);
4088#endif
4089 break;
4090 case VAR_STRING:
4091 generate_PUSHS(cctx, NULL);
4092 break;
4093 case VAR_BLOB:
4094 generate_PUSHBLOB(cctx, NULL);
4095 break;
4096 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004097 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004098 break;
4099 case VAR_PARTIAL:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01004100 generate_PUSHPARTIAL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004101 break;
4102 case VAR_LIST:
4103 generate_NEWLIST(cctx, 0);
4104 break;
4105 case VAR_DICT:
4106 generate_NEWDICT(cctx, 0);
4107 break;
4108 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004109 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004110 break;
4111 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004112 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004113 break;
4114 case VAR_NUMBER:
4115 case VAR_UNKNOWN:
4116 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004117 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004118 generate_PUSHNR(cctx, 0);
4119 break;
4120 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004121 }
4122
4123 if (oplen > 0 && *op != '=')
4124 {
4125 type_T *expected = &t_number;
4126 garray_T *stack = &cctx->ctx_type_stack;
4127 type_T *stacktype;
4128
4129 // TODO: if type is known use float or any operation
4130
4131 if (*op == '.')
4132 expected = &t_string;
4133 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4134 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4135 goto theend;
4136
4137 if (*op == '.')
4138 generate_instr_drop(cctx, ISN_CONCAT, 1);
4139 else
4140 {
4141 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4142
4143 if (isn == NULL)
4144 goto theend;
4145 switch (*op)
4146 {
4147 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4148 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4149 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4150 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4151 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4152 }
4153 }
4154 }
4155
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004156 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004157 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004158 case dest_option:
4159 generate_STOREOPT(cctx, name + 1, opt_flags);
4160 break;
4161 case dest_global:
4162 // include g: with the name, easier to execute that way
4163 generate_STORE(cctx, ISN_STOREG, 0, name);
4164 break;
4165 case dest_env:
4166 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4167 break;
4168 case dest_reg:
4169 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4170 break;
4171 case dest_vimvar:
4172 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4173 break;
4174 case dest_script:
4175 {
4176 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4177 imported_T *import = NULL;
4178 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004179
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004180 if (name[1] != ':')
4181 {
4182 import = find_imported(name, 0, cctx);
4183 if (import != NULL)
4184 sid = import->imp_sid;
4185 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004186
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004187 idx = get_script_item_idx(sid, rawname, TRUE);
4188 // TODO: specific type
4189 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004190 {
4191 char_u *name_s = name;
4192
4193 // Include s: in the name for store_var()
4194 if (name[1] != ':')
4195 {
4196 int len = (int)STRLEN(name) + 3;
4197
4198 name_s = alloc(len);
4199 if (name_s == NULL)
4200 name_s = name;
4201 else
4202 vim_snprintf((char *)name_s, len, "s:%s", name);
4203 }
4204 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4205 if (name_s != name)
4206 vim_free(name_s);
4207 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004208 else
4209 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4210 sid, idx, &t_any);
4211 }
4212 break;
4213 case dest_local:
4214 {
4215 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004216
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004217 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4218 // into ISN_STORENR
4219 if (instr->ga_len == instr_count + 1
4220 && isn->isn_type == ISN_PUSHNR)
4221 {
4222 varnumber_T val = isn->isn_arg.number;
4223 garray_T *stack = &cctx->ctx_type_stack;
4224
4225 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004226 isn->isn_arg.storenr.stnr_idx = idx;
4227 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004228 if (stack->ga_len > 0)
4229 --stack->ga_len;
4230 }
4231 else
4232 generate_STORE(cctx, ISN_STORE, idx, NULL);
4233 }
4234 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004235 }
4236 ret = p;
4237
4238theend:
4239 vim_free(name);
4240 return ret;
4241}
4242
4243/*
4244 * Compile an :import command.
4245 */
4246 static char_u *
4247compile_import(char_u *arg, cctx_T *cctx)
4248{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004249 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004250}
4251
4252/*
4253 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4254 */
4255 static int
4256compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4257{
4258 garray_T *instr = &cctx->ctx_instr;
4259 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4260
4261 if (endlabel == NULL)
4262 return FAIL;
4263 endlabel->el_next = *el;
4264 *el = endlabel;
4265 endlabel->el_end_label = instr->ga_len;
4266
4267 generate_JUMP(cctx, when, 0);
4268 return OK;
4269}
4270
4271 static void
4272compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4273{
4274 garray_T *instr = &cctx->ctx_instr;
4275
4276 while (*el != NULL)
4277 {
4278 endlabel_T *cur = (*el);
4279 isn_T *isn;
4280
4281 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4282 isn->isn_arg.jump.jump_where = instr->ga_len;
4283 *el = cur->el_next;
4284 vim_free(cur);
4285 }
4286}
4287
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004288 static void
4289compile_free_jump_to_end(endlabel_T **el)
4290{
4291 while (*el != NULL)
4292 {
4293 endlabel_T *cur = (*el);
4294
4295 *el = cur->el_next;
4296 vim_free(cur);
4297 }
4298}
4299
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004300/*
4301 * Create a new scope and set up the generic items.
4302 */
4303 static scope_T *
4304new_scope(cctx_T *cctx, scopetype_T type)
4305{
4306 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4307
4308 if (scope == NULL)
4309 return NULL;
4310 scope->se_outer = cctx->ctx_scope;
4311 cctx->ctx_scope = scope;
4312 scope->se_type = type;
4313 scope->se_local_count = cctx->ctx_locals.ga_len;
4314 return scope;
4315}
4316
4317/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004318 * Free the current scope and go back to the outer scope.
4319 */
4320 static void
4321drop_scope(cctx_T *cctx)
4322{
4323 scope_T *scope = cctx->ctx_scope;
4324
4325 if (scope == NULL)
4326 {
4327 iemsg("calling drop_scope() without a scope");
4328 return;
4329 }
4330 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004331 switch (scope->se_type)
4332 {
4333 case IF_SCOPE:
4334 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4335 case FOR_SCOPE:
4336 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4337 case WHILE_SCOPE:
4338 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4339 case TRY_SCOPE:
4340 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4341 case NO_SCOPE:
4342 case BLOCK_SCOPE:
4343 break;
4344 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004345 vim_free(scope);
4346}
4347
4348/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004349 * Evaluate an expression that is a constant:
4350 * has(arg)
4351 *
4352 * Also handle:
4353 * ! in front logical NOT
4354 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004355 * Return FAIL if the expression is not a constant.
4356 */
4357 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004358evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004359{
4360 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004361 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004362 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004363
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004364 /*
4365 * Skip '!' characters. They are handled later.
4366 */
4367 start_leader = *arg;
4368 while (**arg == '!')
4369 *arg = skipwhite(*arg + 1);
4370 end_leader = *arg;
4371
4372 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004373 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004374 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004375 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4376 {
4377 tv->v_type = VAR_SPECIAL;
4378 tv->vval.v_number = VVAL_TRUE;
4379 *arg += 4;
4380 return OK;
4381 }
4382 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4383 {
4384 tv->v_type = VAR_SPECIAL;
4385 tv->vval.v_number = VVAL_FALSE;
4386 *arg += 5;
4387 return OK;
4388 }
4389
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004390 if (STRNCMP("has(", *arg, 4) == 0)
4391 {
4392 has_call = TRUE;
4393 *arg = skipwhite(*arg + 4);
4394 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004395
4396 if (**arg == '"')
4397 {
4398 if (get_string_tv(arg, tv, TRUE) == FAIL)
4399 return FAIL;
4400 }
4401 else if (**arg == '\'')
4402 {
4403 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4404 return FAIL;
4405 }
4406 else
4407 return FAIL;
4408
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004409 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004410 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004411 *arg = skipwhite(*arg);
4412 if (**arg != ')')
4413 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004414 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004415
4416 argvars[0] = *tv;
4417 argvars[1].v_type = VAR_UNKNOWN;
4418 tv->v_type = VAR_NUMBER;
4419 tv->vval.v_number = 0;
4420 f_has(argvars, tv);
4421 clear_tv(&argvars[0]);
4422
4423 while (start_leader < end_leader)
4424 {
4425 if (*start_leader == '!')
4426 tv->vval.v_number = !tv->vval.v_number;
4427 ++start_leader;
4428 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004429 }
4430
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004431 return OK;
4432}
4433
Bram Moolenaar080457c2020-03-03 21:53:32 +01004434 static int
4435evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4436{
4437 exptype_T type = EXPR_UNKNOWN;
4438 char_u *p;
4439 int len = 2;
4440 int type_is = FALSE;
4441
4442 // get the first variable
4443 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4444 return FAIL;
4445
4446 p = skipwhite(*arg);
4447 type = get_compare_type(p, &len, &type_is);
4448
4449 /*
4450 * If there is a comparative operator, use it.
4451 */
4452 if (type != EXPR_UNKNOWN)
4453 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004454 typval_T tv2;
4455 char_u *s1, *s2;
4456 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4457 int n;
4458
4459 // TODO: Only string == string is supported now
4460 if (tv->v_type != VAR_STRING)
4461 return FAIL;
4462 if (type != EXPR_EQUAL)
4463 return FAIL;
4464
4465 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004466 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004467 *arg = skipwhite(p + len);
4468 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4469 || tv2.v_type != VAR_STRING)
4470 {
4471 clear_tv(&tv2);
4472 return FAIL;
4473 }
4474 s1 = tv_get_string_buf(tv, buf1);
4475 s2 = tv_get_string_buf(&tv2, buf2);
4476 n = STRCMP(s1, s2);
4477 clear_tv(tv);
4478 clear_tv(&tv2);
4479 tv->v_type = VAR_BOOL;
4480 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004481 }
4482
4483 return OK;
4484}
4485
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004486static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4487
4488/*
4489 * Compile constant || or &&.
4490 */
4491 static int
4492evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4493{
4494 char_u *p = skipwhite(*arg);
4495 int opchar = *op;
4496
4497 if (p[0] == opchar && p[1] == opchar)
4498 {
4499 int val = tv2bool(tv);
4500
4501 /*
4502 * Repeat until there is no following "||" or "&&"
4503 */
4504 while (p[0] == opchar && p[1] == opchar)
4505 {
4506 typval_T tv2;
4507
4508 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4509 return FAIL;
4510
4511 // eval the next expression
4512 *arg = skipwhite(p + 2);
4513 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004514 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004515 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004516 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004517 {
4518 clear_tv(&tv2);
4519 return FAIL;
4520 }
4521 if ((opchar == '&') == val)
4522 {
4523 // false || tv2 or true && tv2: use tv2
4524 clear_tv(tv);
4525 *tv = tv2;
4526 val = tv2bool(tv);
4527 }
4528 else
4529 clear_tv(&tv2);
4530 p = skipwhite(*arg);
4531 }
4532 }
4533
4534 return OK;
4535}
4536
4537/*
4538 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4539 * Return FAIL if the expression is not a constant.
4540 */
4541 static int
4542evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4543{
4544 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004545 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004546 return FAIL;
4547
4548 // || and && work almost the same
4549 return evaluate_const_and_or(arg, cctx, "&&", tv);
4550}
4551
4552/*
4553 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4554 * Return FAIL if the expression is not a constant.
4555 */
4556 static int
4557evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4558{
4559 // evaluate the first expression
4560 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4561 return FAIL;
4562
4563 // || and && work almost the same
4564 return evaluate_const_and_or(arg, cctx, "||", tv);
4565}
4566
4567/*
4568 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4569 * E.g. for "has('feature')".
4570 * This does not produce error messages. "tv" should be cleared afterwards.
4571 * Return FAIL if the expression is not a constant.
4572 */
4573 static int
4574evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4575{
4576 char_u *p;
4577
4578 // evaluate the first expression
4579 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4580 return FAIL;
4581
4582 p = skipwhite(*arg);
4583 if (*p == '?')
4584 {
4585 int val = tv2bool(tv);
4586 typval_T tv2;
4587
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004588 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004589 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4590 return FAIL;
4591
4592 // evaluate the second expression; any type is accepted
4593 clear_tv(tv);
4594 *arg = skipwhite(p + 1);
4595 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
4596 return FAIL;
4597
4598 // Check for the ":".
4599 p = skipwhite(*arg);
4600 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4601 return FAIL;
4602
4603 // evaluate the third expression
4604 *arg = skipwhite(p + 1);
4605 tv2.v_type = VAR_UNKNOWN;
4606 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
4607 {
4608 clear_tv(&tv2);
4609 return FAIL;
4610 }
4611 if (val)
4612 {
4613 // use the expr after "?"
4614 clear_tv(&tv2);
4615 }
4616 else
4617 {
4618 // use the expr after ":"
4619 clear_tv(tv);
4620 *tv = tv2;
4621 }
4622 }
4623 return OK;
4624}
4625
4626/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004627 * compile "if expr"
4628 *
4629 * "if expr" Produces instructions:
4630 * EVAL expr Push result of "expr"
4631 * JUMP_IF_FALSE end
4632 * ... body ...
4633 * end:
4634 *
4635 * "if expr | else" Produces instructions:
4636 * EVAL expr Push result of "expr"
4637 * JUMP_IF_FALSE else
4638 * ... body ...
4639 * JUMP_ALWAYS end
4640 * else:
4641 * ... body ...
4642 * end:
4643 *
4644 * "if expr1 | elseif expr2 | else" Produces instructions:
4645 * EVAL expr Push result of "expr"
4646 * JUMP_IF_FALSE elseif
4647 * ... body ...
4648 * JUMP_ALWAYS end
4649 * elseif:
4650 * EVAL expr Push result of "expr"
4651 * JUMP_IF_FALSE else
4652 * ... body ...
4653 * JUMP_ALWAYS end
4654 * else:
4655 * ... body ...
4656 * end:
4657 */
4658 static char_u *
4659compile_if(char_u *arg, cctx_T *cctx)
4660{
4661 char_u *p = arg;
4662 garray_T *instr = &cctx->ctx_instr;
4663 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004664 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004665
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004666 // compile "expr"; if we know it evaluates to FALSE skip the block
4667 tv.v_type = VAR_UNKNOWN;
4668 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4669 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4670 else
4671 cctx->ctx_skip = MAYBE;
4672 clear_tv(&tv);
4673 if (cctx->ctx_skip == MAYBE)
4674 {
4675 p = arg;
4676 if (compile_expr1(&p, cctx) == FAIL)
4677 return NULL;
4678 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004679
4680 scope = new_scope(cctx, IF_SCOPE);
4681 if (scope == NULL)
4682 return NULL;
4683
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004684 if (cctx->ctx_skip == MAYBE)
4685 {
4686 // "where" is set when ":elseif", "else" or ":endif" is found
4687 scope->se_u.se_if.is_if_label = instr->ga_len;
4688 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4689 }
4690 else
4691 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004692
4693 return p;
4694}
4695
4696 static char_u *
4697compile_elseif(char_u *arg, cctx_T *cctx)
4698{
4699 char_u *p = arg;
4700 garray_T *instr = &cctx->ctx_instr;
4701 isn_T *isn;
4702 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004703 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004704
4705 if (scope == NULL || scope->se_type != IF_SCOPE)
4706 {
4707 emsg(_(e_elseif_without_if));
4708 return NULL;
4709 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004710 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004711
Bram Moolenaar158906c2020-02-06 20:39:45 +01004712 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004713 {
4714 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004715 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004716 return NULL;
4717 // previous "if" or "elseif" jumps here
4718 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4719 isn->isn_arg.jump.jump_where = instr->ga_len;
4720 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004721
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004722 // compile "expr"; if we know it evaluates to FALSE skip the block
4723 tv.v_type = VAR_UNKNOWN;
4724 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4725 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4726 else
4727 cctx->ctx_skip = MAYBE;
4728 clear_tv(&tv);
4729 if (cctx->ctx_skip == MAYBE)
4730 {
4731 p = arg;
4732 if (compile_expr1(&p, cctx) == FAIL)
4733 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004734
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004735 // "where" is set when ":elseif", "else" or ":endif" is found
4736 scope->se_u.se_if.is_if_label = instr->ga_len;
4737 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4738 }
4739 else
4740 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004741
4742 return p;
4743}
4744
4745 static char_u *
4746compile_else(char_u *arg, cctx_T *cctx)
4747{
4748 char_u *p = arg;
4749 garray_T *instr = &cctx->ctx_instr;
4750 isn_T *isn;
4751 scope_T *scope = cctx->ctx_scope;
4752
4753 if (scope == NULL || scope->se_type != IF_SCOPE)
4754 {
4755 emsg(_(e_else_without_if));
4756 return NULL;
4757 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004758 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004759
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004760 // jump from previous block to the end, unless the else block is empty
4761 if (cctx->ctx_skip == MAYBE)
4762 {
4763 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004764 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004765 return NULL;
4766 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004767
Bram Moolenaar158906c2020-02-06 20:39:45 +01004768 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004769 {
4770 if (scope->se_u.se_if.is_if_label >= 0)
4771 {
4772 // previous "if" or "elseif" jumps here
4773 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4774 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01004775 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004776 }
4777 }
4778
4779 if (cctx->ctx_skip != MAYBE)
4780 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004781
4782 return p;
4783}
4784
4785 static char_u *
4786compile_endif(char_u *arg, cctx_T *cctx)
4787{
4788 scope_T *scope = cctx->ctx_scope;
4789 ifscope_T *ifscope;
4790 garray_T *instr = &cctx->ctx_instr;
4791 isn_T *isn;
4792
4793 if (scope == NULL || scope->se_type != IF_SCOPE)
4794 {
4795 emsg(_(e_endif_without_if));
4796 return NULL;
4797 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004798 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004799 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004800
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004801 if (scope->se_u.se_if.is_if_label >= 0)
4802 {
4803 // previous "if" or "elseif" jumps here
4804 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4805 isn->isn_arg.jump.jump_where = instr->ga_len;
4806 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004807 // Fill in the "end" label in jumps at the end of the blocks.
4808 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004809 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004810
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004811 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004812 return arg;
4813}
4814
4815/*
4816 * compile "for var in expr"
4817 *
4818 * Produces instructions:
4819 * PUSHNR -1
4820 * STORE loop-idx Set index to -1
4821 * EVAL expr Push result of "expr"
4822 * top: FOR loop-idx, end Increment index, use list on bottom of stack
4823 * - if beyond end, jump to "end"
4824 * - otherwise get item from list and push it
4825 * STORE var Store item in "var"
4826 * ... body ...
4827 * JUMP top Jump back to repeat
4828 * end: DROP Drop the result of "expr"
4829 *
4830 */
4831 static char_u *
4832compile_for(char_u *arg, cctx_T *cctx)
4833{
4834 char_u *p;
4835 size_t varlen;
4836 garray_T *instr = &cctx->ctx_instr;
4837 garray_T *stack = &cctx->ctx_type_stack;
4838 scope_T *scope;
4839 int loop_idx; // index of loop iteration variable
4840 int var_idx; // index of "var"
4841 type_T *vartype;
4842
4843 // TODO: list of variables: "for [key, value] in dict"
4844 // parse "var"
4845 for (p = arg; eval_isnamec1(*p); ++p)
4846 ;
4847 varlen = p - arg;
4848 var_idx = lookup_local(arg, varlen, cctx);
4849 if (var_idx >= 0)
4850 {
4851 semsg(_("E1023: variable already defined: %s"), arg);
4852 return NULL;
4853 }
4854
4855 // consume "in"
4856 p = skipwhite(p);
4857 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
4858 {
4859 emsg(_(e_missing_in));
4860 return NULL;
4861 }
4862 p = skipwhite(p + 2);
4863
4864
4865 scope = new_scope(cctx, FOR_SCOPE);
4866 if (scope == NULL)
4867 return NULL;
4868
4869 // Reserve a variable to store the loop iteration counter.
4870 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
4871 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004872 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004873 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004874 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004875 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004876 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004877
4878 // Reserve a variable to store "var"
4879 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
4880 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004881 {
4882 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004883 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004884 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004885
4886 generate_STORENR(cctx, loop_idx, -1);
4887
4888 // compile "expr", it remains on the stack until "endfor"
4889 arg = p;
4890 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004891 {
4892 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004893 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004894 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004895
4896 // now we know the type of "var"
4897 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4898 if (vartype->tt_type != VAR_LIST)
4899 {
4900 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004901 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004902 return NULL;
4903 }
4904 if (vartype->tt_member->tt_type != VAR_UNKNOWN)
4905 {
4906 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
4907
4908 lvar->lv_type = vartype->tt_member;
4909 }
4910
4911 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004912 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004913
4914 generate_FOR(cctx, loop_idx);
4915 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
4916
4917 return arg;
4918}
4919
4920/*
4921 * compile "endfor"
4922 */
4923 static char_u *
4924compile_endfor(char_u *arg, cctx_T *cctx)
4925{
4926 garray_T *instr = &cctx->ctx_instr;
4927 scope_T *scope = cctx->ctx_scope;
4928 forscope_T *forscope;
4929 isn_T *isn;
4930
4931 if (scope == NULL || scope->se_type != FOR_SCOPE)
4932 {
4933 emsg(_(e_for));
4934 return NULL;
4935 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004936 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004937 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004938 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004939
4940 // At end of ":for" scope jump back to the FOR instruction.
4941 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
4942
4943 // Fill in the "end" label in the FOR statement so it can jump here
4944 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
4945 isn->isn_arg.forloop.for_end = instr->ga_len;
4946
4947 // Fill in the "end" label any BREAK statements
4948 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
4949
4950 // Below the ":for" scope drop the "expr" list from the stack.
4951 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
4952 return NULL;
4953
4954 vim_free(scope);
4955
4956 return arg;
4957}
4958
4959/*
4960 * compile "while expr"
4961 *
4962 * Produces instructions:
4963 * top: EVAL expr Push result of "expr"
4964 * JUMP_IF_FALSE end jump if false
4965 * ... body ...
4966 * JUMP top Jump back to repeat
4967 * end:
4968 *
4969 */
4970 static char_u *
4971compile_while(char_u *arg, cctx_T *cctx)
4972{
4973 char_u *p = arg;
4974 garray_T *instr = &cctx->ctx_instr;
4975 scope_T *scope;
4976
4977 scope = new_scope(cctx, WHILE_SCOPE);
4978 if (scope == NULL)
4979 return NULL;
4980
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004981 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004982
4983 // compile "expr"
4984 if (compile_expr1(&p, cctx) == FAIL)
4985 return NULL;
4986
4987 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01004988 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004989 JUMP_IF_FALSE, cctx) == FAIL)
4990 return FAIL;
4991
4992 return p;
4993}
4994
4995/*
4996 * compile "endwhile"
4997 */
4998 static char_u *
4999compile_endwhile(char_u *arg, cctx_T *cctx)
5000{
5001 scope_T *scope = cctx->ctx_scope;
5002
5003 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5004 {
5005 emsg(_(e_while));
5006 return NULL;
5007 }
5008 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005009 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005010
5011 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005012 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005013
5014 // Fill in the "end" label in the WHILE statement so it can jump here.
5015 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005016 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005017
5018 vim_free(scope);
5019
5020 return arg;
5021}
5022
5023/*
5024 * compile "continue"
5025 */
5026 static char_u *
5027compile_continue(char_u *arg, cctx_T *cctx)
5028{
5029 scope_T *scope = cctx->ctx_scope;
5030
5031 for (;;)
5032 {
5033 if (scope == NULL)
5034 {
5035 emsg(_(e_continue));
5036 return NULL;
5037 }
5038 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5039 break;
5040 scope = scope->se_outer;
5041 }
5042
5043 // Jump back to the FOR or WHILE instruction.
5044 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005045 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5046 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005047 return arg;
5048}
5049
5050/*
5051 * compile "break"
5052 */
5053 static char_u *
5054compile_break(char_u *arg, cctx_T *cctx)
5055{
5056 scope_T *scope = cctx->ctx_scope;
5057 endlabel_T **el;
5058
5059 for (;;)
5060 {
5061 if (scope == NULL)
5062 {
5063 emsg(_(e_break));
5064 return NULL;
5065 }
5066 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5067 break;
5068 scope = scope->se_outer;
5069 }
5070
5071 // Jump to the end of the FOR or WHILE loop.
5072 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005073 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005074 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005075 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005076 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5077 return FAIL;
5078
5079 return arg;
5080}
5081
5082/*
5083 * compile "{" start of block
5084 */
5085 static char_u *
5086compile_block(char_u *arg, cctx_T *cctx)
5087{
5088 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5089 return NULL;
5090 return skipwhite(arg + 1);
5091}
5092
5093/*
5094 * compile end of block: drop one scope
5095 */
5096 static void
5097compile_endblock(cctx_T *cctx)
5098{
5099 scope_T *scope = cctx->ctx_scope;
5100
5101 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005102 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005103 vim_free(scope);
5104}
5105
5106/*
5107 * compile "try"
5108 * Creates a new scope for the try-endtry, pointing to the first catch and
5109 * finally.
5110 * Creates another scope for the "try" block itself.
5111 * TRY instruction sets up exception handling at runtime.
5112 *
5113 * "try"
5114 * TRY -> catch1, -> finally push trystack entry
5115 * ... try block
5116 * "throw {exception}"
5117 * EVAL {exception}
5118 * THROW create exception
5119 * ... try block
5120 * " catch {expr}"
5121 * JUMP -> finally
5122 * catch1: PUSH exeception
5123 * EVAL {expr}
5124 * MATCH
5125 * JUMP nomatch -> catch2
5126 * CATCH remove exception
5127 * ... catch block
5128 * " catch"
5129 * JUMP -> finally
5130 * catch2: CATCH remove exception
5131 * ... catch block
5132 * " finally"
5133 * finally:
5134 * ... finally block
5135 * " endtry"
5136 * ENDTRY pop trystack entry, may rethrow
5137 */
5138 static char_u *
5139compile_try(char_u *arg, cctx_T *cctx)
5140{
5141 garray_T *instr = &cctx->ctx_instr;
5142 scope_T *try_scope;
5143 scope_T *scope;
5144
5145 // scope that holds the jumps that go to catch/finally/endtry
5146 try_scope = new_scope(cctx, TRY_SCOPE);
5147 if (try_scope == NULL)
5148 return NULL;
5149
5150 // "catch" is set when the first ":catch" is found.
5151 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005152 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005153 if (generate_instr(cctx, ISN_TRY) == NULL)
5154 return NULL;
5155
5156 // scope for the try block itself
5157 scope = new_scope(cctx, BLOCK_SCOPE);
5158 if (scope == NULL)
5159 return NULL;
5160
5161 return arg;
5162}
5163
5164/*
5165 * compile "catch {expr}"
5166 */
5167 static char_u *
5168compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5169{
5170 scope_T *scope = cctx->ctx_scope;
5171 garray_T *instr = &cctx->ctx_instr;
5172 char_u *p;
5173 isn_T *isn;
5174
5175 // end block scope from :try or :catch
5176 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5177 compile_endblock(cctx);
5178 scope = cctx->ctx_scope;
5179
5180 // Error if not in a :try scope
5181 if (scope == NULL || scope->se_type != TRY_SCOPE)
5182 {
5183 emsg(_(e_catch));
5184 return NULL;
5185 }
5186
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005187 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005188 {
5189 emsg(_("E1033: catch unreachable after catch-all"));
5190 return NULL;
5191 }
5192
5193 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005194 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005195 JUMP_ALWAYS, cctx) == FAIL)
5196 return NULL;
5197
5198 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005199 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005200 if (isn->isn_arg.try.try_catch == 0)
5201 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005202 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005203 {
5204 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005205 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005206 isn->isn_arg.jump.jump_where = instr->ga_len;
5207 }
5208
5209 p = skipwhite(arg);
5210 if (ends_excmd(*p))
5211 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005212 scope->se_u.se_try.ts_caught_all = TRUE;
5213 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005214 }
5215 else
5216 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005217 char_u *end;
5218 char_u *pat;
5219 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005220 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005221 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005222
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005223 // Push v:exception, push {expr} and MATCH
5224 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5225
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005226 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005227 if (*end != *p)
5228 {
5229 semsg(_("E1067: Separator mismatch: %s"), p);
5230 vim_free(tofree);
5231 return FAIL;
5232 }
5233 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005234 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005235 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005236 len = (int)(end - tofree);
5237 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005238 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005239 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005240 if (pat == NULL)
5241 return FAIL;
5242 if (generate_PUSHS(cctx, pat) == FAIL)
5243 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005244
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005245 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5246 return NULL;
5247
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005248 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005249 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5250 return NULL;
5251 }
5252
5253 if (generate_instr(cctx, ISN_CATCH) == NULL)
5254 return NULL;
5255
5256 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5257 return NULL;
5258 return p;
5259}
5260
5261 static char_u *
5262compile_finally(char_u *arg, cctx_T *cctx)
5263{
5264 scope_T *scope = cctx->ctx_scope;
5265 garray_T *instr = &cctx->ctx_instr;
5266 isn_T *isn;
5267
5268 // end block scope from :try or :catch
5269 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5270 compile_endblock(cctx);
5271 scope = cctx->ctx_scope;
5272
5273 // Error if not in a :try scope
5274 if (scope == NULL || scope->se_type != TRY_SCOPE)
5275 {
5276 emsg(_(e_finally));
5277 return NULL;
5278 }
5279
5280 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005281 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005282 if (isn->isn_arg.try.try_finally != 0)
5283 {
5284 emsg(_(e_finally_dup));
5285 return NULL;
5286 }
5287
5288 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005289 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005290
Bram Moolenaar585fea72020-04-02 22:33:21 +02005291 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005292 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005293 {
5294 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005295 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005296 isn->isn_arg.jump.jump_where = instr->ga_len;
5297 }
5298
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005299 // TODO: set index in ts_finally_label jumps
5300
5301 return arg;
5302}
5303
5304 static char_u *
5305compile_endtry(char_u *arg, cctx_T *cctx)
5306{
5307 scope_T *scope = cctx->ctx_scope;
5308 garray_T *instr = &cctx->ctx_instr;
5309 isn_T *isn;
5310
5311 // end block scope from :catch or :finally
5312 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5313 compile_endblock(cctx);
5314 scope = cctx->ctx_scope;
5315
5316 // Error if not in a :try scope
5317 if (scope == NULL || scope->se_type != TRY_SCOPE)
5318 {
5319 if (scope == NULL)
5320 emsg(_(e_no_endtry));
5321 else if (scope->se_type == WHILE_SCOPE)
5322 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005323 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005324 emsg(_(e_endfor));
5325 else
5326 emsg(_(e_endif));
5327 return NULL;
5328 }
5329
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005330 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005331 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5332 {
5333 emsg(_("E1032: missing :catch or :finally"));
5334 return NULL;
5335 }
5336
5337 // Fill in the "end" label in jumps at the end of the blocks, if not done
5338 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005339 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005340
5341 // End :catch or :finally scope: set value in ISN_TRY instruction
5342 if (isn->isn_arg.try.try_finally == 0)
5343 isn->isn_arg.try.try_finally = instr->ga_len;
5344 compile_endblock(cctx);
5345
5346 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5347 return NULL;
5348 return arg;
5349}
5350
5351/*
5352 * compile "throw {expr}"
5353 */
5354 static char_u *
5355compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5356{
5357 char_u *p = skipwhite(arg);
5358
5359 if (ends_excmd(*p))
5360 {
5361 emsg(_(e_argreq));
5362 return NULL;
5363 }
5364 if (compile_expr1(&p, cctx) == FAIL)
5365 return NULL;
5366 if (may_generate_2STRING(-1, cctx) == FAIL)
5367 return NULL;
5368 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5369 return NULL;
5370
5371 return p;
5372}
5373
5374/*
5375 * compile "echo expr"
5376 */
5377 static char_u *
5378compile_echo(char_u *arg, int with_white, cctx_T *cctx)
5379{
5380 char_u *p = arg;
5381 int count = 0;
5382
Bram Moolenaarad39c092020-02-26 18:23:43 +01005383 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005384 {
5385 if (compile_expr1(&p, cctx) == FAIL)
5386 return NULL;
5387 ++count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005388 p = skipwhite(p);
5389 if (ends_excmd(*p))
5390 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005391 }
5392
5393 generate_ECHO(cctx, with_white, count);
Bram Moolenaarad39c092020-02-26 18:23:43 +01005394 return p;
5395}
5396
5397/*
5398 * compile "execute expr"
5399 */
5400 static char_u *
5401compile_execute(char_u *arg, cctx_T *cctx)
5402{
5403 char_u *p = arg;
5404 int count = 0;
5405
5406 for (;;)
5407 {
5408 if (compile_expr1(&p, cctx) == FAIL)
5409 return NULL;
5410 ++count;
5411 p = skipwhite(p);
5412 if (ends_excmd(*p))
5413 break;
5414 }
5415
5416 generate_EXECUTE(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005417
5418 return p;
5419}
5420
5421/*
5422 * After ex_function() has collected all the function lines: parse and compile
5423 * the lines into instructions.
5424 * Adds the function to "def_functions".
5425 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5426 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005427 * This can be used recursively through compile_lambda(), which may reallocate
5428 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005429 */
5430 void
5431compile_def_function(ufunc_T *ufunc, int set_return_type)
5432{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005433 char_u *line = NULL;
5434 char_u *p;
5435 exarg_T ea;
5436 char *errormsg = NULL; // error message
5437 int had_return = FALSE;
5438 cctx_T cctx;
5439 garray_T *instr;
5440 int called_emsg_before = called_emsg;
5441 int ret = FAIL;
5442 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005443 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005444
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005445 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005446 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005447
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005448 if (ufunc->uf_dfunc_idx >= 0)
5449 {
5450 // Redefining a function that was compiled before.
5451 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5452
5453 // Free old instructions.
5454 delete_def_function_contents(dfunc);
5455 }
5456 else
5457 {
5458 // Add the function to "def_functions".
5459 if (ga_grow(&def_functions, 1) == FAIL)
5460 return;
5461 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
5462 vim_memset(dfunc, 0, sizeof(dfunc_T));
5463 dfunc->df_idx = def_functions.ga_len;
5464 ufunc->uf_dfunc_idx = dfunc->df_idx;
5465 dfunc->df_ufunc = ufunc;
5466 ++def_functions.ga_len;
5467 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005468 }
5469
5470 vim_memset(&cctx, 0, sizeof(cctx));
5471 cctx.ctx_ufunc = ufunc;
5472 cctx.ctx_lnum = -1;
5473 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5474 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5475 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5476 cctx.ctx_type_list = &ufunc->uf_type_list;
5477 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5478 instr = &cctx.ctx_instr;
5479
5480 // Most modern script version.
5481 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5482
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005483 if (ufunc->uf_def_args.ga_len > 0)
5484 {
5485 int count = ufunc->uf_def_args.ga_len;
5486 int i;
5487 char_u *arg;
5488 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5489
5490 // Produce instructions for the default values of optional arguments.
5491 // Store the instruction index in uf_def_arg_idx[] so that we know
5492 // where to start when the function is called, depending on the number
5493 // of arguments.
5494 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5495 if (ufunc->uf_def_arg_idx == NULL)
5496 goto erret;
5497 for (i = 0; i < count; ++i)
5498 {
5499 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5500 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
5501 if (compile_expr1(&arg, &cctx) == FAIL
5502 || generate_STORE(&cctx, ISN_STORE,
5503 i - count - off, NULL) == FAIL)
5504 goto erret;
5505 }
5506
5507 // If a varargs is following, push an empty list.
5508 if (ufunc->uf_va_name != NULL)
5509 {
5510 if (generate_NEWLIST(&cctx, 0) == FAIL
5511 || generate_STORE(&cctx, ISN_STORE, -off, NULL) == FAIL)
5512 goto erret;
5513 }
5514
5515 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5516 }
5517
5518 /*
5519 * Loop over all the lines of the function and generate instructions.
5520 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005521 for (;;)
5522 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005523 int is_ex_command;
5524
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005525 // Bail out on the first error to avoid a flood of errors and report
5526 // the right line number when inside try/catch.
5527 if (emsg_before != called_emsg)
5528 goto erret;
5529
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005530 if (line != NULL && *line == '|')
5531 // the line continues after a '|'
5532 ++line;
5533 else if (line != NULL && *line != NUL)
5534 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005535 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005536 goto erret;
5537 }
5538 else
5539 {
5540 do
5541 {
5542 ++cctx.ctx_lnum;
5543 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
5544 break;
5545 line = ((char_u **)ufunc->uf_lines.ga_data)[cctx.ctx_lnum];
5546 } while (line == NULL);
5547 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len)
5548 break;
5549 SOURCING_LNUM = ufunc->uf_script_ctx.sc_lnum + cctx.ctx_lnum + 1;
5550 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005551 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005552
5553 had_return = FALSE;
5554 vim_memset(&ea, 0, sizeof(ea));
5555 ea.cmdlinep = &line;
5556 ea.cmd = skipwhite(line);
5557
5558 // "}" ends a block scope
5559 if (*ea.cmd == '}')
5560 {
5561 scopetype_T stype = cctx.ctx_scope == NULL
5562 ? NO_SCOPE : cctx.ctx_scope->se_type;
5563
5564 if (stype == BLOCK_SCOPE)
5565 {
5566 compile_endblock(&cctx);
5567 line = ea.cmd;
5568 }
5569 else
5570 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005571 emsg(_("E1025: using } outside of a block scope"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005572 goto erret;
5573 }
5574 if (line != NULL)
5575 line = skipwhite(ea.cmd + 1);
5576 continue;
5577 }
5578
5579 // "{" starts a block scope
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01005580 // "{'a': 1}->func() is something else
5581 if (*ea.cmd == '{' && ends_excmd(*skipwhite(ea.cmd + 1)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005582 {
5583 line = compile_block(ea.cmd, &cctx);
5584 continue;
5585 }
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005586 is_ex_command = *ea.cmd == ':';
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005587
5588 /*
5589 * COMMAND MODIFIERS
5590 */
5591 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
5592 {
5593 if (errormsg != NULL)
5594 goto erret;
5595 // empty line or comment
5596 line = (char_u *)"";
5597 continue;
5598 }
5599
5600 // Skip ":call" to get to the function name.
5601 if (checkforcmd(&ea.cmd, "call", 3))
5602 ea.cmd = skipwhite(ea.cmd);
5603
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005604 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005605 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005606 // Assuming the command starts with a variable or function name,
5607 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
5608 // val".
5609 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
5610 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005611 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02005612 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005613 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005614 int oplen;
5615 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005616
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005617 oplen = assignment_len(skipwhite(p), &heredoc);
5618 if (oplen > 0)
5619 {
5620 // Recognize an assignment if we recognize the variable
5621 // name:
5622 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005623 // "local = expr" where "local" is a local var.
5624 // "script = expr" where "script" is a script-local var.
5625 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005626 // "&opt = expr"
5627 // "$ENV = expr"
5628 // "@r = expr"
5629 if (*ea.cmd == '&'
5630 || *ea.cmd == '$'
5631 || *ea.cmd == '@'
5632 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
5633 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
5634 || lookup_script(ea.cmd, p - ea.cmd) == OK
5635 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
5636 {
5637 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
5638 if (line == NULL)
5639 goto erret;
5640 continue;
5641 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005642 }
5643 }
5644 }
5645
5646 /*
5647 * COMMAND after range
5648 */
5649 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005650 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
5651 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005652
5653 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
5654 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005655 if (cctx.ctx_skip == TRUE)
5656 {
5657 line += STRLEN(line);
5658 continue;
5659 }
5660
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005661 // Expression or function call.
5662 if (ea.cmdidx == CMD_eval)
5663 {
5664 p = ea.cmd;
5665 if (compile_expr1(&p, &cctx) == FAIL)
5666 goto erret;
5667
5668 // drop the return value
5669 generate_instr_drop(&cctx, ISN_DROP, 1);
5670 line = p;
5671 continue;
5672 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02005673 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005674 iemsg("Command from find_ex_command() not handled");
5675 goto erret;
5676 }
5677
5678 p = skipwhite(p);
5679
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005680 if (cctx.ctx_skip == TRUE
5681 && ea.cmdidx != CMD_elseif
5682 && ea.cmdidx != CMD_else
5683 && ea.cmdidx != CMD_endif)
5684 {
5685 line += STRLEN(line);
5686 continue;
5687 }
5688
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005689 switch (ea.cmdidx)
5690 {
5691 case CMD_def:
5692 case CMD_function:
5693 // TODO: Nested function
5694 emsg("Nested function not implemented yet");
5695 goto erret;
5696
5697 case CMD_return:
5698 line = compile_return(p, set_return_type, &cctx);
5699 had_return = TRUE;
5700 break;
5701
5702 case CMD_let:
5703 case CMD_const:
5704 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
5705 break;
5706
5707 case CMD_import:
5708 line = compile_import(p, &cctx);
5709 break;
5710
5711 case CMD_if:
5712 line = compile_if(p, &cctx);
5713 break;
5714 case CMD_elseif:
5715 line = compile_elseif(p, &cctx);
5716 break;
5717 case CMD_else:
5718 line = compile_else(p, &cctx);
5719 break;
5720 case CMD_endif:
5721 line = compile_endif(p, &cctx);
5722 break;
5723
5724 case CMD_while:
5725 line = compile_while(p, &cctx);
5726 break;
5727 case CMD_endwhile:
5728 line = compile_endwhile(p, &cctx);
5729 break;
5730
5731 case CMD_for:
5732 line = compile_for(p, &cctx);
5733 break;
5734 case CMD_endfor:
5735 line = compile_endfor(p, &cctx);
5736 break;
5737 case CMD_continue:
5738 line = compile_continue(p, &cctx);
5739 break;
5740 case CMD_break:
5741 line = compile_break(p, &cctx);
5742 break;
5743
5744 case CMD_try:
5745 line = compile_try(p, &cctx);
5746 break;
5747 case CMD_catch:
5748 line = compile_catch(p, &cctx);
5749 break;
5750 case CMD_finally:
5751 line = compile_finally(p, &cctx);
5752 break;
5753 case CMD_endtry:
5754 line = compile_endtry(p, &cctx);
5755 break;
5756 case CMD_throw:
5757 line = compile_throw(p, &cctx);
5758 break;
5759
5760 case CMD_echo:
5761 line = compile_echo(p, TRUE, &cctx);
5762 break;
5763 case CMD_echon:
5764 line = compile_echo(p, FALSE, &cctx);
5765 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005766 case CMD_execute:
5767 line = compile_execute(p, &cctx);
5768 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005769
5770 default:
5771 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01005772 // TODO:
5773 // CMD_echomsg
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01005774 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005775 generate_EXEC(&cctx, line);
5776 line = (char_u *)"";
5777 break;
5778 }
5779 if (line == NULL)
5780 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02005781 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005782
5783 if (cctx.ctx_type_stack.ga_len < 0)
5784 {
5785 iemsg("Type stack underflow");
5786 goto erret;
5787 }
5788 }
5789
5790 if (cctx.ctx_scope != NULL)
5791 {
5792 if (cctx.ctx_scope->se_type == IF_SCOPE)
5793 emsg(_(e_endif));
5794 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
5795 emsg(_(e_endwhile));
5796 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
5797 emsg(_(e_endfor));
5798 else
5799 emsg(_("E1026: Missing }"));
5800 goto erret;
5801 }
5802
5803 if (!had_return)
5804 {
5805 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
5806 {
5807 emsg(_("E1027: Missing return statement"));
5808 goto erret;
5809 }
5810
5811 // Return zero if there is no return at the end.
5812 generate_PUSHNR(&cctx, 0);
5813 generate_instr(&cctx, ISN_RETURN);
5814 }
5815
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005816 {
5817 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5818 + ufunc->uf_dfunc_idx;
5819 dfunc->df_deleted = FALSE;
5820 dfunc->df_instr = instr->ga_data;
5821 dfunc->df_instr_count = instr->ga_len;
5822 dfunc->df_varcount = cctx.ctx_max_local;
5823 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005824
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005825 {
5826 int argcount = ufunc->uf_args.ga_len
5827 + (ufunc->uf_va_name == NULL ? 0 : 1);
5828
5829 // Create a type for the function, with the return type and any
5830 // argument types.
5831 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type, argcount,
5832 &ufunc->uf_type_list);
5833 if (argcount > 0)
5834 {
5835 if (func_type_add_arg_types(ufunc->uf_func_type, argcount,
5836 argcount - ufunc->uf_def_args.ga_len,
5837 &ufunc->uf_type_list) == FAIL)
5838 {
5839 ret = FAIL;
5840 goto erret;
5841 }
5842 if (ufunc->uf_arg_types == NULL)
5843 {
5844 int i;
5845
5846 // lambda does not have argument types.
5847 for (i = 0; i < argcount; ++i)
5848 ufunc->uf_func_type->tt_args[i] = &t_any;
5849 }
5850 else
5851 mch_memmove(ufunc->uf_func_type->tt_args,
5852 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
5853 }
5854 }
5855
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005856 ret = OK;
5857
5858erret:
5859 if (ret == FAIL)
5860 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01005861 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005862 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5863 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005864
5865 for (idx = 0; idx < instr->ga_len; ++idx)
5866 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005867 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01005868
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005869 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005870 if (!dfunc->df_deleted)
5871 --def_functions.ga_len;
5872
Bram Moolenaar3cca2992020-04-02 22:57:36 +02005873 while (cctx.ctx_scope != NULL)
5874 drop_scope(&cctx);
5875
Bram Moolenaar20431c92020-03-20 18:39:46 +01005876 // Don't execute this function body.
5877 ga_clear_strings(&ufunc->uf_lines);
5878
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005879 if (errormsg != NULL)
5880 emsg(errormsg);
5881 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01005882 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005883 }
5884
5885 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005886 free_imported(&cctx);
5887 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005888 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005889}
5890
5891/*
5892 * Delete an instruction, free what it contains.
5893 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01005894 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005895delete_instr(isn_T *isn)
5896{
5897 switch (isn->isn_type)
5898 {
5899 case ISN_EXEC:
5900 case ISN_LOADENV:
5901 case ISN_LOADG:
5902 case ISN_LOADOPT:
5903 case ISN_MEMBER:
5904 case ISN_PUSHEXC:
5905 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005906 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005907 case ISN_STOREG:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005908 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005909 vim_free(isn->isn_arg.string);
5910 break;
5911
5912 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005913 case ISN_STORES:
5914 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005915 break;
5916
5917 case ISN_STOREOPT:
5918 vim_free(isn->isn_arg.storeopt.so_name);
5919 break;
5920
5921 case ISN_PUSHBLOB: // push blob isn_arg.blob
5922 blob_unref(isn->isn_arg.blob);
5923 break;
5924
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005925 case ISN_PUSHPARTIAL:
Bram Moolenaar087d2e12020-03-01 15:36:42 +01005926 partial_unref(isn->isn_arg.partial);
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005927 break;
5928
5929 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005930#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005931 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005932#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005933 break;
5934
5935 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005936#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005937 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01005938#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005939 break;
5940
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005941 case ISN_UCALL:
5942 vim_free(isn->isn_arg.ufunc.cuf_name);
5943 break;
5944
5945 case ISN_2BOOL:
5946 case ISN_2STRING:
5947 case ISN_ADDBLOB:
5948 case ISN_ADDLIST:
5949 case ISN_BCALL:
5950 case ISN_CATCH:
5951 case ISN_CHECKNR:
5952 case ISN_CHECKTYPE:
5953 case ISN_COMPAREANY:
5954 case ISN_COMPAREBLOB:
5955 case ISN_COMPAREBOOL:
5956 case ISN_COMPAREDICT:
5957 case ISN_COMPAREFLOAT:
5958 case ISN_COMPAREFUNC:
5959 case ISN_COMPARELIST:
5960 case ISN_COMPARENR:
5961 case ISN_COMPAREPARTIAL:
5962 case ISN_COMPARESPECIAL:
5963 case ISN_COMPARESTRING:
5964 case ISN_CONCAT:
5965 case ISN_DCALL:
5966 case ISN_DROP:
5967 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01005968 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005969 case ISN_ENDTRY:
5970 case ISN_FOR:
5971 case ISN_FUNCREF:
5972 case ISN_INDEX:
5973 case ISN_JUMP:
5974 case ISN_LOAD:
5975 case ISN_LOADSCRIPT:
5976 case ISN_LOADREG:
5977 case ISN_LOADV:
5978 case ISN_NEGATENR:
5979 case ISN_NEWDICT:
5980 case ISN_NEWLIST:
5981 case ISN_OPNR:
5982 case ISN_OPFLOAT:
5983 case ISN_OPANY:
5984 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02005985 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005986 case ISN_PUSHF:
5987 case ISN_PUSHNR:
5988 case ISN_PUSHBOOL:
5989 case ISN_PUSHSPEC:
5990 case ISN_RETURN:
5991 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005992 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005993 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01005994 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005995 case ISN_STORESCRIPT:
5996 case ISN_THROW:
5997 case ISN_TRY:
5998 // nothing allocated
5999 break;
6000 }
6001}
6002
6003/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006004 * Free all instructions for "dfunc".
6005 */
6006 static void
6007delete_def_function_contents(dfunc_T *dfunc)
6008{
6009 int idx;
6010
6011 ga_clear(&dfunc->df_def_args_isn);
6012
6013 if (dfunc->df_instr != NULL)
6014 {
6015 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6016 delete_instr(dfunc->df_instr + idx);
6017 VIM_CLEAR(dfunc->df_instr);
6018 }
6019
6020 dfunc->df_deleted = TRUE;
6021}
6022
6023/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006024 * When a user function is deleted, delete any associated def function.
6025 */
6026 void
6027delete_def_function(ufunc_T *ufunc)
6028{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006029 if (ufunc->uf_dfunc_idx >= 0)
6030 {
6031 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6032 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006033
Bram Moolenaar20431c92020-03-20 18:39:46 +01006034 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006035 }
6036}
6037
6038#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006039/*
6040 * Free all functions defined with ":def".
6041 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006042 void
6043free_def_functions(void)
6044{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006045 int idx;
6046
6047 for (idx = 0; idx < def_functions.ga_len; ++idx)
6048 {
6049 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6050
6051 delete_def_function_contents(dfunc);
6052 }
6053
6054 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006055}
6056#endif
6057
6058
6059#endif // FEAT_EVAL