blob: 7e1c22e8b52f9d9d0bea20eb84021014735ac8e2 [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
Bram Moolenaar7a092242020-04-16 22:10:49 +0200111 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100112 garray_T ctx_instr; // generated instructions
113
114 garray_T ctx_locals; // currently visible local variables
115 int ctx_max_local; // maximum number of locals at one time
116
117 garray_T ctx_imports; // imported items
118
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100119 int ctx_skip; // when TRUE skip commands, when FALSE skip
120 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100121 scope_T *ctx_scope; // current scope, NULL at toplevel
122
123 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200124 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100125};
126
127static char e_var_notfound[] = N_("E1001: variable not found: %s");
128static char e_syntax_at[] = N_("E1002: Syntax error at %s");
129
130static int compile_expr1(char_u **arg, cctx_T *cctx);
131static int compile_expr2(char_u **arg, cctx_T *cctx);
132static int compile_expr3(char_u **arg, cctx_T *cctx);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100133static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200134static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
135static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100136
137/*
138 * Lookup variable "name" in the local scope and return the index.
139 */
140 static int
141lookup_local(char_u *name, size_t len, cctx_T *cctx)
142{
143 int idx;
144
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100145 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146 return -1;
147 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
148 {
149 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
150
151 if (STRNCMP(name, lvar->lv_name, len) == 0
152 && STRLEN(lvar->lv_name) == len)
153 return idx;
154 }
155 return -1;
156}
157
158/*
159 * Lookup an argument in the current function.
160 * Returns the argument index or -1 if not found.
161 */
162 static int
163lookup_arg(char_u *name, size_t len, cctx_T *cctx)
164{
165 int idx;
166
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100167 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100168 return -1;
169 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
170 {
171 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
172
173 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
174 return idx;
175 }
176 return -1;
177}
178
179/*
180 * Lookup a vararg argument in the current function.
181 * Returns TRUE if there is a match.
182 */
183 static int
184lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
185{
186 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
187
188 return len > 0 && va_name != NULL
189 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
190}
191
192/*
193 * Lookup a variable in the current script.
194 * Returns OK or FAIL.
195 */
196 static int
197lookup_script(char_u *name, size_t len)
198{
199 int cc;
200 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
201 dictitem_T *di;
202
203 cc = name[len];
204 name[len] = NUL;
205 di = find_var_in_ht(ht, 0, name, TRUE);
206 name[len] = cc;
207 return di == NULL ? FAIL: OK;
208}
209
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100210/*
211 * Check if "p[len]" is already defined, either in script "import_sid" or in
212 * compilation context "cctx".
213 * Return FAIL and give an error if it defined.
214 */
215 int
216check_defined(char_u *p, int len, cctx_T *cctx)
217{
218 if (lookup_script(p, len) == OK
219 || (cctx != NULL
220 && (lookup_local(p, len, cctx) >= 0
221 || find_imported(p, len, cctx) != NULL)))
222 {
223 semsg("E1073: imported name already defined: %s", p);
224 return FAIL;
225 }
226 return OK;
227}
228
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200229/*
230 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
231 * be freed later.
232 */
233 static type_T *
234alloc_type(garray_T *type_gap)
235{
236 type_T *type;
237
238 if (ga_grow(type_gap, 1) == FAIL)
239 return NULL;
240 type = ALLOC_CLEAR_ONE(type_T);
241 if (type != NULL)
242 {
243 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
244 ++type_gap->ga_len;
245 }
246 return type;
247}
248
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100249 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200250get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100251{
252 type_T *type;
253
254 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200255 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100256 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200257 if (member_type->tt_type == VAR_VOID
258 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100259 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100260 if (member_type->tt_type == VAR_BOOL)
261 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100262 if (member_type->tt_type == VAR_NUMBER)
263 return &t_list_number;
264 if (member_type->tt_type == VAR_STRING)
265 return &t_list_string;
266
267 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200268 type = alloc_type(type_gap);
269 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100270 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 type->tt_type = VAR_LIST;
272 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200273 type->tt_argcount = 0;
274 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100275 return type;
276}
277
278 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200279get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100280{
281 type_T *type;
282
283 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200284 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100285 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200286 if (member_type->tt_type == VAR_VOID
287 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100288 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100289 if (member_type->tt_type == VAR_BOOL)
290 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100291 if (member_type->tt_type == VAR_NUMBER)
292 return &t_dict_number;
293 if (member_type->tt_type == VAR_STRING)
294 return &t_dict_string;
295
296 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200297 type = alloc_type(type_gap);
298 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100299 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100300 type->tt_type = VAR_DICT;
301 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200302 type->tt_argcount = 0;
303 type->tt_args = NULL;
304 return type;
305}
306
307/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200308 * Allocate a new type for a function.
309 */
310 static type_T *
311alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
312{
313 type_T *type = alloc_type(type_gap);
314
315 if (type == NULL)
316 return &t_any;
317 type->tt_type = VAR_FUNC;
318 type->tt_member = ret_type;
319 type->tt_argcount = argcount;
320 type->tt_args = NULL;
321 return type;
322}
323
324/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200325 * Get a function type, based on the return type "ret_type".
326 * If "argcount" is -1 or 0 a predefined type can be used.
327 * If "argcount" > 0 always create a new type, so that arguments can be added.
328 */
329 static type_T *
330get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
331{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200332 // recognize commonly used types
333 if (argcount <= 0)
334 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200335 if (ret_type == &t_unknown)
336 {
337 // (argcount == 0) is not possible
338 return &t_func_unknown;
339 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200340 if (ret_type == &t_void)
341 {
342 if (argcount == 0)
343 return &t_func_0_void;
344 else
345 return &t_func_void;
346 }
347 if (ret_type == &t_any)
348 {
349 if (argcount == 0)
350 return &t_func_0_any;
351 else
352 return &t_func_any;
353 }
354 if (ret_type == &t_number)
355 {
356 if (argcount == 0)
357 return &t_func_0_number;
358 else
359 return &t_func_number;
360 }
361 if (ret_type == &t_string)
362 {
363 if (argcount == 0)
364 return &t_func_0_string;
365 else
366 return &t_func_string;
367 }
368 }
369
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200370 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100371}
372
Bram Moolenaara8c17702020-04-01 21:17:24 +0200373/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200374 * For a function type, reserve space for "argcount" argument types (including
375 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200376 */
377 static int
378func_type_add_arg_types(
379 type_T *functype,
380 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200381 garray_T *type_gap)
382{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200383 // To make it easy to free the space needed for the argument types, add the
384 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200385 if (ga_grow(type_gap, 1) == FAIL)
386 return FAIL;
387 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
388 if (functype->tt_args == NULL)
389 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200390 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
391 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200392 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200393 return OK;
394}
395
396/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200397 * Return the type_T for a typval. Only for primitive types.
398 */
399 static type_T *
400typval2type(typval_T *tv)
401{
402 if (tv->v_type == VAR_NUMBER)
403 return &t_number;
404 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200405 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200406 if (tv->v_type == VAR_STRING)
407 return &t_string;
408 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
409 return &t_list_string;
410 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
411 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200412 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200413}
414
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100415/////////////////////////////////////////////////////////////////////
416// Following generate_ functions expect the caller to call ga_grow().
417
Bram Moolenaar080457c2020-03-03 21:53:32 +0100418#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
419#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
420
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100421/*
422 * Generate an instruction without arguments.
423 * Returns a pointer to the new instruction, NULL if failed.
424 */
425 static isn_T *
426generate_instr(cctx_T *cctx, isntype_T isn_type)
427{
428 garray_T *instr = &cctx->ctx_instr;
429 isn_T *isn;
430
Bram Moolenaar080457c2020-03-03 21:53:32 +0100431 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100432 if (ga_grow(instr, 1) == FAIL)
433 return NULL;
434 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
435 isn->isn_type = isn_type;
436 isn->isn_lnum = cctx->ctx_lnum + 1;
437 ++instr->ga_len;
438
439 return isn;
440}
441
442/*
443 * Generate an instruction without arguments.
444 * "drop" will be removed from the stack.
445 * Returns a pointer to the new instruction, NULL if failed.
446 */
447 static isn_T *
448generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
449{
450 garray_T *stack = &cctx->ctx_type_stack;
451
Bram Moolenaar080457c2020-03-03 21:53:32 +0100452 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100453 stack->ga_len -= drop;
454 return generate_instr(cctx, isn_type);
455}
456
457/*
458 * Generate instruction "isn_type" and put "type" on the type stack.
459 */
460 static isn_T *
461generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
462{
463 isn_T *isn;
464 garray_T *stack = &cctx->ctx_type_stack;
465
466 if ((isn = generate_instr(cctx, isn_type)) == NULL)
467 return NULL;
468
469 if (ga_grow(stack, 1) == FAIL)
470 return NULL;
471 ((type_T **)stack->ga_data)[stack->ga_len] = type;
472 ++stack->ga_len;
473
474 return isn;
475}
476
477/*
478 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
479 */
480 static int
481may_generate_2STRING(int offset, cctx_T *cctx)
482{
483 isn_T *isn;
484 garray_T *stack = &cctx->ctx_type_stack;
485 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
486
487 if ((*type)->tt_type == VAR_STRING)
488 return OK;
489 *type = &t_string;
490
491 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
492 return FAIL;
493 isn->isn_arg.number = offset;
494
495 return OK;
496}
497
498 static int
499check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
500{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200501 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100502 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200503 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100504 {
505 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100506 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100507 else
508 semsg(_("E1036: %c requires number or float arguments"), *op);
509 return FAIL;
510 }
511 return OK;
512}
513
514/*
515 * Generate an instruction with two arguments. The instruction depends on the
516 * type of the arguments.
517 */
518 static int
519generate_two_op(cctx_T *cctx, char_u *op)
520{
521 garray_T *stack = &cctx->ctx_type_stack;
522 type_T *type1;
523 type_T *type2;
524 vartype_T vartype;
525 isn_T *isn;
526
Bram Moolenaar080457c2020-03-03 21:53:32 +0100527 RETURN_OK_IF_SKIP(cctx);
528
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100529 // Get the known type of the two items on the stack. If they are matching
530 // use a type-specific instruction. Otherwise fall back to runtime type
531 // checking.
532 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
533 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200534 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100535 if (type1->tt_type == type2->tt_type
536 && (type1->tt_type == VAR_NUMBER
537 || type1->tt_type == VAR_LIST
538#ifdef FEAT_FLOAT
539 || type1->tt_type == VAR_FLOAT
540#endif
541 || type1->tt_type == VAR_BLOB))
542 vartype = type1->tt_type;
543
544 switch (*op)
545 {
546 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200547 && type1->tt_type != VAR_ANY
548 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100549 && check_number_or_float(
550 type1->tt_type, type2->tt_type, op) == FAIL)
551 return FAIL;
552 isn = generate_instr_drop(cctx,
553 vartype == VAR_NUMBER ? ISN_OPNR
554 : vartype == VAR_LIST ? ISN_ADDLIST
555 : vartype == VAR_BLOB ? ISN_ADDBLOB
556#ifdef FEAT_FLOAT
557 : vartype == VAR_FLOAT ? ISN_OPFLOAT
558#endif
559 : ISN_OPANY, 1);
560 if (isn != NULL)
561 isn->isn_arg.op.op_type = EXPR_ADD;
562 break;
563
564 case '-':
565 case '*':
566 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
567 op) == FAIL)
568 return FAIL;
569 if (vartype == VAR_NUMBER)
570 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
571#ifdef FEAT_FLOAT
572 else if (vartype == VAR_FLOAT)
573 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
574#endif
575 else
576 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
577 if (isn != NULL)
578 isn->isn_arg.op.op_type = *op == '*'
579 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
580 break;
581
Bram Moolenaar4c683752020-04-05 21:38:23 +0200582 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100583 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200584 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100585 && type2->tt_type != VAR_NUMBER))
586 {
587 emsg(_("E1035: % requires number arguments"));
588 return FAIL;
589 }
590 isn = generate_instr_drop(cctx,
591 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
592 if (isn != NULL)
593 isn->isn_arg.op.op_type = EXPR_REM;
594 break;
595 }
596
597 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200598 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100599 {
600 type_T *type = &t_any;
601
602#ifdef FEAT_FLOAT
603 // float+number and number+float results in float
604 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
605 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
606 type = &t_float;
607#endif
608 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
609 }
610
611 return OK;
612}
613
614/*
615 * Generate an ISN_COMPARE* instruction with a boolean result.
616 */
617 static int
618generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
619{
620 isntype_T isntype = ISN_DROP;
621 isn_T *isn;
622 garray_T *stack = &cctx->ctx_type_stack;
623 vartype_T type1;
624 vartype_T type2;
625
Bram Moolenaar080457c2020-03-03 21:53:32 +0100626 RETURN_OK_IF_SKIP(cctx);
627
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100628 // Get the known type of the two items on the stack. If they are matching
629 // use a type-specific instruction. Otherwise fall back to runtime type
630 // checking.
631 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
632 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200633 if (type1 == VAR_UNKNOWN)
634 type1 = VAR_ANY;
635 if (type2 == VAR_UNKNOWN)
636 type2 = VAR_ANY;
637
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100638 if (type1 == type2)
639 {
640 switch (type1)
641 {
642 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
643 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
644 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
645 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
646 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
647 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
648 case VAR_LIST: isntype = ISN_COMPARELIST; break;
649 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
650 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100651 default: isntype = ISN_COMPAREANY; break;
652 }
653 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200654 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100655 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
656 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
657 isntype = ISN_COMPAREANY;
658
659 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
660 && (isntype == ISN_COMPAREBOOL
661 || isntype == ISN_COMPARESPECIAL
662 || isntype == ISN_COMPARENR
663 || isntype == ISN_COMPAREFLOAT))
664 {
665 semsg(_("E1037: Cannot use \"%s\" with %s"),
666 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
667 return FAIL;
668 }
669 if (isntype == ISN_DROP
670 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
671 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
672 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
673 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
674 && exptype != EXPR_IS && exptype != EXPR_ISNOT
675 && (type1 == VAR_BLOB || type2 == VAR_BLOB
676 || type1 == VAR_LIST || type2 == VAR_LIST))))
677 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100678 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100679 vartype_name(type1), vartype_name(type2));
680 return FAIL;
681 }
682
683 if ((isn = generate_instr(cctx, isntype)) == NULL)
684 return FAIL;
685 isn->isn_arg.op.op_type = exptype;
686 isn->isn_arg.op.op_ic = ic;
687
688 // takes two arguments, puts one bool back
689 if (stack->ga_len >= 2)
690 {
691 --stack->ga_len;
692 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
693 }
694
695 return OK;
696}
697
698/*
699 * Generate an ISN_2BOOL instruction.
700 */
701 static int
702generate_2BOOL(cctx_T *cctx, int invert)
703{
704 isn_T *isn;
705 garray_T *stack = &cctx->ctx_type_stack;
706
Bram Moolenaar080457c2020-03-03 21:53:32 +0100707 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100708 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
709 return FAIL;
710 isn->isn_arg.number = invert;
711
712 // type becomes bool
713 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
714
715 return OK;
716}
717
718 static int
719generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
720{
721 isn_T *isn;
722 garray_T *stack = &cctx->ctx_type_stack;
723
Bram Moolenaar080457c2020-03-03 21:53:32 +0100724 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100725 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
726 return FAIL;
727 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
728 isn->isn_arg.type.ct_off = offset;
729
730 // type becomes vartype
731 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
732
733 return OK;
734}
735
736/*
737 * Generate an ISN_PUSHNR instruction.
738 */
739 static int
740generate_PUSHNR(cctx_T *cctx, varnumber_T number)
741{
742 isn_T *isn;
743
Bram Moolenaar080457c2020-03-03 21:53:32 +0100744 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100745 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
746 return FAIL;
747 isn->isn_arg.number = number;
748
749 return OK;
750}
751
752/*
753 * Generate an ISN_PUSHBOOL instruction.
754 */
755 static int
756generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
757{
758 isn_T *isn;
759
Bram Moolenaar080457c2020-03-03 21:53:32 +0100760 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100761 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
762 return FAIL;
763 isn->isn_arg.number = number;
764
765 return OK;
766}
767
768/*
769 * Generate an ISN_PUSHSPEC instruction.
770 */
771 static int
772generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
773{
774 isn_T *isn;
775
Bram Moolenaar080457c2020-03-03 21:53:32 +0100776 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100777 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
778 return FAIL;
779 isn->isn_arg.number = number;
780
781 return OK;
782}
783
784#ifdef FEAT_FLOAT
785/*
786 * Generate an ISN_PUSHF instruction.
787 */
788 static int
789generate_PUSHF(cctx_T *cctx, float_T fnumber)
790{
791 isn_T *isn;
792
Bram Moolenaar080457c2020-03-03 21:53:32 +0100793 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100794 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
795 return FAIL;
796 isn->isn_arg.fnumber = fnumber;
797
798 return OK;
799}
800#endif
801
802/*
803 * Generate an ISN_PUSHS instruction.
804 * Consumes "str".
805 */
806 static int
807generate_PUSHS(cctx_T *cctx, char_u *str)
808{
809 isn_T *isn;
810
Bram Moolenaar080457c2020-03-03 21:53:32 +0100811 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100812 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
813 return FAIL;
814 isn->isn_arg.string = str;
815
816 return OK;
817}
818
819/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100820 * Generate an ISN_PUSHCHANNEL instruction.
821 * Consumes "channel".
822 */
823 static int
824generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
825{
826 isn_T *isn;
827
Bram Moolenaar080457c2020-03-03 21:53:32 +0100828 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100829 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
830 return FAIL;
831 isn->isn_arg.channel = channel;
832
833 return OK;
834}
835
836/*
837 * Generate an ISN_PUSHJOB instruction.
838 * Consumes "job".
839 */
840 static int
841generate_PUSHJOB(cctx_T *cctx, job_T *job)
842{
843 isn_T *isn;
844
Bram Moolenaar080457c2020-03-03 21:53:32 +0100845 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100846 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100847 return FAIL;
848 isn->isn_arg.job = job;
849
850 return OK;
851}
852
853/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100854 * Generate an ISN_PUSHBLOB instruction.
855 * Consumes "blob".
856 */
857 static int
858generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
859{
860 isn_T *isn;
861
Bram Moolenaar080457c2020-03-03 21:53:32 +0100862 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100863 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
864 return FAIL;
865 isn->isn_arg.blob = blob;
866
867 return OK;
868}
869
870/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100871 * Generate an ISN_PUSHFUNC instruction with name "name".
872 * Consumes "name".
873 */
874 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200875generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100876{
877 isn_T *isn;
878
Bram Moolenaar080457c2020-03-03 21:53:32 +0100879 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200880 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100881 return FAIL;
882 isn->isn_arg.string = name;
883
884 return OK;
885}
886
887/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100888 * Generate an ISN_STORE instruction.
889 */
890 static int
891generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
892{
893 isn_T *isn;
894
Bram Moolenaar080457c2020-03-03 21:53:32 +0100895 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100896 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
897 return FAIL;
898 if (name != NULL)
899 isn->isn_arg.string = vim_strsave(name);
900 else
901 isn->isn_arg.number = idx;
902
903 return OK;
904}
905
906/*
907 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
908 */
909 static int
910generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
911{
912 isn_T *isn;
913
Bram Moolenaar080457c2020-03-03 21:53:32 +0100914 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100915 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
916 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100917 isn->isn_arg.storenr.stnr_idx = idx;
918 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100919
920 return OK;
921}
922
923/*
924 * Generate an ISN_STOREOPT instruction
925 */
926 static int
927generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
928{
929 isn_T *isn;
930
Bram Moolenaar080457c2020-03-03 21:53:32 +0100931 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100932 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
933 return FAIL;
934 isn->isn_arg.storeopt.so_name = vim_strsave(name);
935 isn->isn_arg.storeopt.so_flags = opt_flags;
936
937 return OK;
938}
939
940/*
941 * Generate an ISN_LOAD or similar instruction.
942 */
943 static int
944generate_LOAD(
945 cctx_T *cctx,
946 isntype_T isn_type,
947 int idx,
948 char_u *name,
949 type_T *type)
950{
951 isn_T *isn;
952
Bram Moolenaar080457c2020-03-03 21:53:32 +0100953 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100954 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
955 return FAIL;
956 if (name != NULL)
957 isn->isn_arg.string = vim_strsave(name);
958 else
959 isn->isn_arg.number = idx;
960
961 return OK;
962}
963
964/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200965 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100966 */
967 static int
968generate_LOADV(
969 cctx_T *cctx,
970 char_u *name,
971 int error)
972{
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200973 int di_flags;
974 int vidx = find_vim_var(name, &di_flags);
975 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100976
Bram Moolenaar080457c2020-03-03 21:53:32 +0100977 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100978 if (vidx < 0)
979 {
980 if (error)
981 semsg(_(e_var_notfound), name);
982 return FAIL;
983 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200984 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100985
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200986 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100987}
988
989/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200990 * Generate an ISN_UNLET instruction.
991 */
992 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200993generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200994{
995 isn_T *isn;
996
997 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200998 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200999 return FAIL;
1000 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1001 isn->isn_arg.unlet.ul_forceit = forceit;
1002
1003 return OK;
1004}
1005
1006/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001007 * Generate an ISN_LOADS instruction.
1008 */
1009 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001010generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001012 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001013 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001014 int sid,
1015 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001016{
1017 isn_T *isn;
1018
Bram Moolenaar080457c2020-03-03 21:53:32 +01001019 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001020 if (isn_type == ISN_LOADS)
1021 isn = generate_instr_type(cctx, isn_type, type);
1022 else
1023 isn = generate_instr_drop(cctx, isn_type, 1);
1024 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001025 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001026 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1027 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001028
1029 return OK;
1030}
1031
1032/*
1033 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1034 */
1035 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001036generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001037 cctx_T *cctx,
1038 isntype_T isn_type,
1039 int sid,
1040 int idx,
1041 type_T *type)
1042{
1043 isn_T *isn;
1044
Bram Moolenaar080457c2020-03-03 21:53:32 +01001045 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001046 if (isn_type == ISN_LOADSCRIPT)
1047 isn = generate_instr_type(cctx, isn_type, type);
1048 else
1049 isn = generate_instr_drop(cctx, isn_type, 1);
1050 if (isn == NULL)
1051 return FAIL;
1052 isn->isn_arg.script.script_sid = sid;
1053 isn->isn_arg.script.script_idx = idx;
1054 return OK;
1055}
1056
1057/*
1058 * Generate an ISN_NEWLIST instruction.
1059 */
1060 static int
1061generate_NEWLIST(cctx_T *cctx, int count)
1062{
1063 isn_T *isn;
1064 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001065 type_T *type;
1066 type_T *member;
1067
Bram Moolenaar080457c2020-03-03 21:53:32 +01001068 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001069 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1070 return FAIL;
1071 isn->isn_arg.number = count;
1072
1073 // drop the value types
1074 stack->ga_len -= count;
1075
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001076 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001077 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001078 if (count > 0)
1079 member = ((type_T **)stack->ga_data)[stack->ga_len];
1080 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001081 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001082 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001083
1084 // add the list type to the type stack
1085 if (ga_grow(stack, 1) == FAIL)
1086 return FAIL;
1087 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1088 ++stack->ga_len;
1089
1090 return OK;
1091}
1092
1093/*
1094 * Generate an ISN_NEWDICT instruction.
1095 */
1096 static int
1097generate_NEWDICT(cctx_T *cctx, int count)
1098{
1099 isn_T *isn;
1100 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001101 type_T *type;
1102 type_T *member;
1103
Bram Moolenaar080457c2020-03-03 21:53:32 +01001104 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001105 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1106 return FAIL;
1107 isn->isn_arg.number = count;
1108
1109 // drop the key and value types
1110 stack->ga_len -= 2 * count;
1111
Bram Moolenaar436472f2020-02-20 22:54:43 +01001112 // Use the first value type for the list member type. Use "void" for an
1113 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001114 if (count > 0)
1115 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1116 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001117 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001118 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001119
1120 // add the dict type to the type stack
1121 if (ga_grow(stack, 1) == FAIL)
1122 return FAIL;
1123 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1124 ++stack->ga_len;
1125
1126 return OK;
1127}
1128
1129/*
1130 * Generate an ISN_FUNCREF instruction.
1131 */
1132 static int
1133generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
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_FUNCREF)) == NULL)
1140 return FAIL;
1141 isn->isn_arg.number = dfunc_idx;
1142
1143 if (ga_grow(stack, 1) == FAIL)
1144 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001145 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001146 // TODO: argument and return types
1147 ++stack->ga_len;
1148
1149 return OK;
1150}
1151
1152/*
1153 * Generate an ISN_JUMP instruction.
1154 */
1155 static int
1156generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1157{
1158 isn_T *isn;
1159 garray_T *stack = &cctx->ctx_type_stack;
1160
Bram Moolenaar080457c2020-03-03 21:53:32 +01001161 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001162 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1163 return FAIL;
1164 isn->isn_arg.jump.jump_when = when;
1165 isn->isn_arg.jump.jump_where = where;
1166
1167 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1168 --stack->ga_len;
1169
1170 return OK;
1171}
1172
1173 static int
1174generate_FOR(cctx_T *cctx, int loop_idx)
1175{
1176 isn_T *isn;
1177 garray_T *stack = &cctx->ctx_type_stack;
1178
Bram Moolenaar080457c2020-03-03 21:53:32 +01001179 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001180 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1181 return FAIL;
1182 isn->isn_arg.forloop.for_idx = loop_idx;
1183
1184 if (ga_grow(stack, 1) == FAIL)
1185 return FAIL;
1186 // type doesn't matter, will be stored next
1187 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1188 ++stack->ga_len;
1189
1190 return OK;
1191}
1192
1193/*
1194 * Generate an ISN_BCALL instruction.
1195 * Return FAIL if the number of arguments is wrong.
1196 */
1197 static int
1198generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1199{
1200 isn_T *isn;
1201 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001202 type_T *argtypes[MAX_FUNC_ARGS];
1203 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001204
Bram Moolenaar080457c2020-03-03 21:53:32 +01001205 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001206 if (check_internal_func(func_idx, argcount) == FAIL)
1207 return FAIL;
1208
1209 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1210 return FAIL;
1211 isn->isn_arg.bfunc.cbf_idx = func_idx;
1212 isn->isn_arg.bfunc.cbf_argcount = argcount;
1213
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001214 for (i = 0; i < argcount; ++i)
1215 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1216
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001217 stack->ga_len -= argcount; // drop the arguments
1218 if (ga_grow(stack, 1) == FAIL)
1219 return FAIL;
1220 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001221 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001222 ++stack->ga_len; // add return value
1223
1224 return OK;
1225}
1226
1227/*
1228 * Generate an ISN_DCALL or ISN_UCALL instruction.
1229 * Return FAIL if the number of arguments is wrong.
1230 */
1231 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001232generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001233{
1234 isn_T *isn;
1235 garray_T *stack = &cctx->ctx_type_stack;
1236 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001237 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001238
Bram Moolenaar080457c2020-03-03 21:53:32 +01001239 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001240 if (argcount > regular_args && !has_varargs(ufunc))
1241 {
1242 semsg(_(e_toomanyarg), ufunc->uf_name);
1243 return FAIL;
1244 }
1245 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1246 {
1247 semsg(_(e_toofewarg), ufunc->uf_name);
1248 return FAIL;
1249 }
1250
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001251 if (ufunc->uf_dfunc_idx >= 0)
1252 {
1253 int i;
1254
1255 for (i = 0; i < argcount; ++i)
1256 {
1257 type_T *expected;
1258 type_T *actual;
1259
1260 if (i < regular_args)
1261 {
1262 if (ufunc->uf_arg_types == NULL)
1263 continue;
1264 expected = ufunc->uf_arg_types[i];
1265 }
1266 else
1267 expected = ufunc->uf_va_type->tt_member;
1268 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1269 if (check_type(expected, actual, FALSE) == FAIL)
1270 {
1271 arg_type_mismatch(expected, actual, i + 1);
1272 return FAIL;
1273 }
1274 }
1275 }
1276
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001277 if ((isn = generate_instr(cctx,
1278 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1279 return FAIL;
1280 if (ufunc->uf_dfunc_idx >= 0)
1281 {
1282 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1283 isn->isn_arg.dfunc.cdf_argcount = argcount;
1284 }
1285 else
1286 {
1287 // A user function may be deleted and redefined later, can't use the
1288 // ufunc pointer, need to look it up again at runtime.
1289 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1290 isn->isn_arg.ufunc.cuf_argcount = argcount;
1291 }
1292
1293 stack->ga_len -= argcount; // drop the arguments
1294 if (ga_grow(stack, 1) == FAIL)
1295 return FAIL;
1296 // add return value
1297 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1298 ++stack->ga_len;
1299
1300 return OK;
1301}
1302
1303/*
1304 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1305 */
1306 static int
1307generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1308{
1309 isn_T *isn;
1310 garray_T *stack = &cctx->ctx_type_stack;
1311
Bram Moolenaar080457c2020-03-03 21:53:32 +01001312 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001313 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1314 return FAIL;
1315 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1316 isn->isn_arg.ufunc.cuf_argcount = argcount;
1317
1318 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001319 if (ga_grow(stack, 1) == FAIL)
1320 return FAIL;
1321 // add return value
1322 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1323 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001324
1325 return OK;
1326}
1327
1328/*
1329 * Generate an ISN_PCALL instruction.
1330 */
1331 static int
1332generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1333{
1334 isn_T *isn;
1335 garray_T *stack = &cctx->ctx_type_stack;
1336
Bram Moolenaar080457c2020-03-03 21:53:32 +01001337 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001338
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001339 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1340 return FAIL;
1341 isn->isn_arg.pfunc.cpf_top = at_top;
1342 isn->isn_arg.pfunc.cpf_argcount = argcount;
1343
1344 stack->ga_len -= argcount; // drop the arguments
1345
1346 // drop the funcref/partial, get back the return value
1347 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1348
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001349 // If partial is above the arguments it must be cleared and replaced with
1350 // the return value.
1351 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1352 return FAIL;
1353
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001354 return OK;
1355}
1356
1357/*
1358 * Generate an ISN_MEMBER instruction.
1359 */
1360 static int
1361generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1362{
1363 isn_T *isn;
1364 garray_T *stack = &cctx->ctx_type_stack;
1365 type_T *type;
1366
Bram Moolenaar080457c2020-03-03 21:53:32 +01001367 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001368 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1369 return FAIL;
1370 isn->isn_arg.string = vim_strnsave(name, (int)len);
1371
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001372 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001373 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001374 if (type->tt_type != VAR_DICT && type != &t_any)
1375 {
1376 emsg(_(e_dictreq));
1377 return FAIL;
1378 }
1379 // change dict type to dict member type
1380 if (type->tt_type == VAR_DICT)
1381 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001382
1383 return OK;
1384}
1385
1386/*
1387 * Generate an ISN_ECHO instruction.
1388 */
1389 static int
1390generate_ECHO(cctx_T *cctx, int with_white, int count)
1391{
1392 isn_T *isn;
1393
Bram Moolenaar080457c2020-03-03 21:53:32 +01001394 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001395 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1396 return FAIL;
1397 isn->isn_arg.echo.echo_with_white = with_white;
1398 isn->isn_arg.echo.echo_count = count;
1399
1400 return OK;
1401}
1402
Bram Moolenaarad39c092020-02-26 18:23:43 +01001403/*
1404 * Generate an ISN_EXECUTE instruction.
1405 */
1406 static int
1407generate_EXECUTE(cctx_T *cctx, int count)
1408{
1409 isn_T *isn;
1410
1411 if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL)
1412 return FAIL;
1413 isn->isn_arg.number = count;
1414
1415 return OK;
1416}
1417
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001418 static int
1419generate_EXEC(cctx_T *cctx, char_u *line)
1420{
1421 isn_T *isn;
1422
Bram Moolenaar080457c2020-03-03 21:53:32 +01001423 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001424 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1425 return FAIL;
1426 isn->isn_arg.string = vim_strsave(line);
1427 return OK;
1428}
1429
1430static char e_white_both[] =
1431 N_("E1004: white space required before and after '%s'");
Bram Moolenaard77a8522020-04-03 21:59:57 +02001432static char e_white_after[] = N_("E1069: white space required after '%s'");
1433static char e_no_white_before[] = N_("E1068: No white space allowed before '%s'");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001434
1435/*
1436 * Reserve space for a local variable.
1437 * Return the index or -1 if it failed.
1438 */
1439 static int
1440reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1441{
1442 int idx;
1443 lvar_T *lvar;
1444
1445 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1446 {
1447 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1448 return -1;
1449 }
1450
1451 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1452 return -1;
1453 idx = cctx->ctx_locals.ga_len;
1454 if (cctx->ctx_max_local < idx + 1)
1455 cctx->ctx_max_local = idx + 1;
1456 ++cctx->ctx_locals.ga_len;
1457
1458 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1459 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1460 lvar->lv_const = isConst;
1461 lvar->lv_type = type;
1462
1463 return idx;
1464}
1465
1466/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001467 * Remove local variables above "new_top".
1468 */
1469 static void
1470unwind_locals(cctx_T *cctx, int new_top)
1471{
1472 if (cctx->ctx_locals.ga_len > new_top)
1473 {
1474 int idx;
1475 lvar_T *lvar;
1476
1477 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1478 {
1479 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1480 vim_free(lvar->lv_name);
1481 }
1482 }
1483 cctx->ctx_locals.ga_len = new_top;
1484}
1485
1486/*
1487 * Free all local variables.
1488 */
1489 static void
1490free_local(cctx_T *cctx)
1491{
1492 unwind_locals(cctx, 0);
1493 ga_clear(&cctx->ctx_locals);
1494}
1495
1496/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001497 * Skip over a type definition and return a pointer to just after it.
1498 */
1499 char_u *
1500skip_type(char_u *start)
1501{
1502 char_u *p = start;
1503
1504 while (ASCII_ISALNUM(*p) || *p == '_')
1505 ++p;
1506
1507 // Skip over "<type>"; this is permissive about white space.
1508 if (*skipwhite(p) == '<')
1509 {
1510 p = skipwhite(p);
1511 p = skip_type(skipwhite(p + 1));
1512 p = skipwhite(p);
1513 if (*p == '>')
1514 ++p;
1515 }
1516 return p;
1517}
1518
1519/*
1520 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001521 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001522 * Returns NULL in case of failure.
1523 */
1524 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001525parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001526{
1527 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001528 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001529
1530 if (**arg != '<')
1531 {
1532 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001533 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001534 else
1535 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001536 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001537 }
1538 *arg = skipwhite(*arg + 1);
1539
Bram Moolenaard77a8522020-04-03 21:59:57 +02001540 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001541
1542 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001543 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001544 {
1545 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001546 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001547 }
1548 ++*arg;
1549
1550 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001551 return get_list_type(member_type, type_gap);
1552 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001553}
1554
1555/*
1556 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001557 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001558 */
1559 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001560parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001561{
1562 char_u *p = *arg;
1563 size_t len;
1564
1565 // skip over the first word
1566 while (ASCII_ISALNUM(*p) || *p == '_')
1567 ++p;
1568 len = p - *arg;
1569
1570 switch (**arg)
1571 {
1572 case 'a':
1573 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1574 {
1575 *arg += len;
1576 return &t_any;
1577 }
1578 break;
1579 case 'b':
1580 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1581 {
1582 *arg += len;
1583 return &t_bool;
1584 }
1585 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1586 {
1587 *arg += len;
1588 return &t_blob;
1589 }
1590 break;
1591 case 'c':
1592 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1593 {
1594 *arg += len;
1595 return &t_channel;
1596 }
1597 break;
1598 case 'd':
1599 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1600 {
1601 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001602 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001603 }
1604 break;
1605 case 'f':
1606 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1607 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001608#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001609 *arg += len;
1610 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001611#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001612 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001613 return &t_any;
1614#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001615 }
1616 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1617 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001618 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001619 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001620 int argcount = -1;
1621 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001622 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001623 type_T *arg_type[MAX_FUNC_ARGS + 1];
1624
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001625 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001626 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001627 if (**arg == '(')
1628 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001629 // "func" may or may not return a value, "func()" does
1630 // not return a value.
1631 ret_type = &t_void;
1632
Bram Moolenaard77a8522020-04-03 21:59:57 +02001633 p = ++*arg;
1634 argcount = 0;
1635 while (*p != NUL && *p != ')')
1636 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001637 if (*p == '?')
1638 {
1639 if (first_optional == -1)
1640 first_optional = argcount;
1641 ++p;
1642 }
1643 else if (first_optional != -1)
1644 {
1645 emsg(_("E1007: mandatory argument after optional argument"));
1646 return &t_any;
1647 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001648 else if (STRNCMP(p, "...", 3) == 0)
1649 {
1650 flags |= TTFLAG_VARARGS;
1651 p += 3;
1652 }
1653
1654 arg_type[argcount++] = parse_type(&p, type_gap);
1655
1656 // Nothing comes after "...{type}".
1657 if (flags & TTFLAG_VARARGS)
1658 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001659
Bram Moolenaard77a8522020-04-03 21:59:57 +02001660 if (*p != ',' && *skipwhite(p) == ',')
1661 {
1662 semsg(_(e_no_white_before), ",");
1663 return &t_any;
1664 }
1665 if (*p == ',')
1666 {
1667 ++p;
1668 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001669 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001670 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001671 return &t_any;
1672 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001673 }
1674 p = skipwhite(p);
1675 if (argcount == MAX_FUNC_ARGS)
1676 {
1677 emsg(_("E740: Too many argument types"));
1678 return &t_any;
1679 }
1680 }
1681
1682 p = skipwhite(p);
1683 if (*p != ')')
1684 {
1685 emsg(_(e_missing_close));
1686 return &t_any;
1687 }
1688 *arg = p + 1;
1689 }
1690 if (**arg == ':')
1691 {
1692 // parse return type
1693 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001694 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001695 semsg(_(e_white_after), ":");
1696 *arg = skipwhite(*arg);
1697 ret_type = parse_type(arg, type_gap);
1698 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001699 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001700 type = get_func_type(ret_type, argcount, type_gap);
1701 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001702 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001703 type = alloc_func_type(ret_type, argcount, type_gap);
1704 type->tt_flags = flags;
1705 if (argcount > 0)
1706 {
1707 type->tt_argcount = argcount;
1708 type->tt_min_argcount = first_optional == -1
1709 ? argcount : first_optional;
1710 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001711 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001712 return &t_any;
1713 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001714 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001715 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001716 }
1717 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001718 }
1719 break;
1720 case 'j':
1721 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1722 {
1723 *arg += len;
1724 return &t_job;
1725 }
1726 break;
1727 case 'l':
1728 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1729 {
1730 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001731 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001732 }
1733 break;
1734 case 'n':
1735 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1736 {
1737 *arg += len;
1738 return &t_number;
1739 }
1740 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001741 case 's':
1742 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1743 {
1744 *arg += len;
1745 return &t_string;
1746 }
1747 break;
1748 case 'v':
1749 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1750 {
1751 *arg += len;
1752 return &t_void;
1753 }
1754 break;
1755 }
1756
1757 semsg(_("E1010: Type not recognized: %s"), *arg);
1758 return &t_any;
1759}
1760
1761/*
1762 * Check if "type1" and "type2" are exactly the same.
1763 */
1764 static int
1765equal_type(type_T *type1, type_T *type2)
1766{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001767 int i;
1768
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001769 if (type1->tt_type != type2->tt_type)
1770 return FALSE;
1771 switch (type1->tt_type)
1772 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001773 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001774 case VAR_ANY:
1775 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001776 case VAR_SPECIAL:
1777 case VAR_BOOL:
1778 case VAR_NUMBER:
1779 case VAR_FLOAT:
1780 case VAR_STRING:
1781 case VAR_BLOB:
1782 case VAR_JOB:
1783 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001784 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001785 case VAR_LIST:
1786 case VAR_DICT:
1787 return equal_type(type1->tt_member, type2->tt_member);
1788 case VAR_FUNC:
1789 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001790 if (!equal_type(type1->tt_member, type2->tt_member)
1791 || type1->tt_argcount != type2->tt_argcount)
1792 return FALSE;
1793 if (type1->tt_argcount < 0
1794 || type1->tt_args == NULL || type2->tt_args == NULL)
1795 return TRUE;
1796 for (i = 0; i < type1->tt_argcount; ++i)
1797 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1798 return FALSE;
1799 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001800 }
1801 return TRUE;
1802}
1803
1804/*
1805 * Find the common type of "type1" and "type2" and put it in "dest".
1806 * "type2" and "dest" may be the same.
1807 */
1808 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001809common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001810{
1811 if (equal_type(type1, type2))
1812 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001813 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001814 return;
1815 }
1816
1817 if (type1->tt_type == type2->tt_type)
1818 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001819 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1820 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001821 type_T *common;
1822
Bram Moolenaard77a8522020-04-03 21:59:57 +02001823 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001824 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001825 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001826 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001827 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001828 return;
1829 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001830 if (type1->tt_type == VAR_FUNC)
1831 {
1832 type_T *common;
1833
1834 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1835 if (type1->tt_argcount == type2->tt_argcount
1836 && type1->tt_argcount >= 0)
1837 {
1838 int argcount = type1->tt_argcount;
1839 int i;
1840
1841 *dest = alloc_func_type(common, argcount, type_gap);
1842 if (type1->tt_args != NULL && type2->tt_args != NULL)
1843 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001844 if (func_type_add_arg_types(*dest, argcount,
1845 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001846 for (i = 0; i < argcount; ++i)
1847 common_type(type1->tt_args[i], type2->tt_args[i],
1848 &(*dest)->tt_args[i], type_gap);
1849 }
1850 }
1851 else
1852 *dest = alloc_func_type(common, -1, type_gap);
1853 return;
1854 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001855 }
1856
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001857 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001858}
1859
1860 char *
1861vartype_name(vartype_T type)
1862{
1863 switch (type)
1864 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001865 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001866 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001867 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001868 case VAR_SPECIAL: return "special";
1869 case VAR_BOOL: return "bool";
1870 case VAR_NUMBER: return "number";
1871 case VAR_FLOAT: return "float";
1872 case VAR_STRING: return "string";
1873 case VAR_BLOB: return "blob";
1874 case VAR_JOB: return "job";
1875 case VAR_CHANNEL: return "channel";
1876 case VAR_LIST: return "list";
1877 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001878
1879 case VAR_FUNC:
1880 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001881 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001882 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001883}
1884
1885/*
1886 * Return the name of a type.
1887 * The result may be in allocated memory, in which case "tofree" is set.
1888 */
1889 char *
1890type_name(type_T *type, char **tofree)
1891{
1892 char *name = vartype_name(type->tt_type);
1893
1894 *tofree = NULL;
1895 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1896 {
1897 char *member_free;
1898 char *member_name = type_name(type->tt_member, &member_free);
1899 size_t len;
1900
1901 len = STRLEN(name) + STRLEN(member_name) + 3;
1902 *tofree = alloc(len);
1903 if (*tofree != NULL)
1904 {
1905 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1906 vim_free(member_free);
1907 return *tofree;
1908 }
1909 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001910 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001911 {
1912 garray_T ga;
1913 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001914 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001915
1916 ga_init2(&ga, 1, 100);
1917 if (ga_grow(&ga, 20) == FAIL)
1918 return "[unknown]";
1919 *tofree = ga.ga_data;
1920 STRCPY(ga.ga_data, "func(");
1921 ga.ga_len += 5;
1922
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001923 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001924 {
1925 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001926 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001927 int len;
1928
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001929 if (type->tt_args == NULL)
1930 arg_type = "[unknown]";
1931 else
1932 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001933 if (i > 0)
1934 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001935 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001936 ga.ga_len += 2;
1937 }
1938 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001939 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001940 {
1941 vim_free(arg_free);
1942 return "[unknown]";
1943 }
1944 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001945 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001946 {
1947 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1948 ga.ga_len += 3;
1949 }
1950 else if (i >= type->tt_min_argcount)
1951 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001952 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001953 ga.ga_len += len;
1954 vim_free(arg_free);
1955 }
1956
1957 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001958 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001959 else
1960 {
1961 char *ret_free;
1962 char *ret_name = type_name(type->tt_member, &ret_free);
1963 int len;
1964
1965 len = (int)STRLEN(ret_name) + 4;
1966 if (ga_grow(&ga, len) == FAIL)
1967 {
1968 vim_free(ret_free);
1969 return "[unknown]";
1970 }
1971 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001972 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1973 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001974 vim_free(ret_free);
1975 }
1976 return ga.ga_data;
1977 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001978
1979 return name;
1980}
1981
1982/*
1983 * Find "name" in script-local items of script "sid".
1984 * Returns the index in "sn_var_vals" if found.
1985 * If found but not in "sn_var_vals" returns -1.
1986 * If not found returns -2.
1987 */
1988 int
1989get_script_item_idx(int sid, char_u *name, int check_writable)
1990{
1991 hashtab_T *ht;
1992 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001993 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001994 int idx;
1995
1996 // First look the name up in the hashtable.
1997 if (sid <= 0 || sid > script_items.ga_len)
1998 return -1;
1999 ht = &SCRIPT_VARS(sid);
2000 di = find_var_in_ht(ht, 0, name, TRUE);
2001 if (di == NULL)
2002 return -2;
2003
2004 // Now find the svar_T index in sn_var_vals.
2005 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2006 {
2007 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2008
2009 if (sv->sv_tv == &di->di_tv)
2010 {
2011 if (check_writable && sv->sv_const)
2012 semsg(_(e_readonlyvar), name);
2013 return idx;
2014 }
2015 }
2016 return -1;
2017}
2018
2019/*
2020 * Find "name" in imported items of the current script/
2021 */
2022 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002023find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002024{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002025 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002026 int idx;
2027
2028 if (cctx != NULL)
2029 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2030 {
2031 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2032 + idx;
2033
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002034 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2035 : STRLEN(import->imp_name) == len
2036 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002037 return import;
2038 }
2039
2040 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2041 {
2042 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2043
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002044 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2045 : STRLEN(import->imp_name) == len
2046 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002047 return import;
2048 }
2049 return NULL;
2050}
2051
2052/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002053 * Free all imported variables.
2054 */
2055 static void
2056free_imported(cctx_T *cctx)
2057{
2058 int idx;
2059
2060 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2061 {
2062 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2063
2064 vim_free(import->imp_name);
2065 }
2066 ga_clear(&cctx->ctx_imports);
2067}
2068
2069/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002070 * Get the next line of the function from "cctx".
2071 * Returns NULL when at the end.
2072 */
2073 static char_u *
2074next_line_from_context(cctx_T *cctx)
2075{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002076 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002077
2078 do
2079 {
2080 ++cctx->ctx_lnum;
2081 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002082 {
2083 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002084 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002085 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002086 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002087 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002088 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2089 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002090 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002091 return line;
2092}
2093
2094/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002095 * Return TRUE if "p" points at a "#" but not at "#{".
2096 */
2097 static int
2098comment_start(char_u *p)
2099{
2100 return p[0] == '#' && p[1] != '{';
2101}
2102
2103/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002104 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002105 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002106 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2107 */
2108 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002109may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002110{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002111 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002112 {
2113 char_u *next = next_line_from_context(cctx);
2114
2115 if (next == NULL)
2116 return FAIL;
2117 *arg = skipwhite(next);
2118 }
2119 return OK;
2120}
2121
2122/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002123 * Generate an instruction to load script-local variable "name", without the
2124 * leading "s:".
2125 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002126 */
2127 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002128compile_load_scriptvar(
2129 cctx_T *cctx,
2130 char_u *name, // variable NUL terminated
2131 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002132 char_u **end, // end of variable
2133 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002134{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002135 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002136 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2137 imported_T *import;
2138
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002139 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002140 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002141 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002142 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2143 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002144 }
2145 if (idx >= 0)
2146 {
2147 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2148
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002149 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002150 current_sctx.sc_sid, idx, sv->sv_type);
2151 return OK;
2152 }
2153
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002154 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002155 if (import != NULL)
2156 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002157 if (import->imp_all)
2158 {
2159 char_u *p = skipwhite(*end);
2160 int name_len;
2161 ufunc_T *ufunc;
2162 type_T *type;
2163
2164 // Used "import * as Name", need to lookup the member.
2165 if (*p != '.')
2166 {
2167 semsg(_("E1060: expected dot after name: %s"), start);
2168 return FAIL;
2169 }
2170 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002171 if (VIM_ISWHITE(*p))
2172 {
2173 emsg(_("E1074: no white space allowed after dot"));
2174 return FAIL;
2175 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002176
2177 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2178 // TODO: what if it is a function?
2179 if (idx < 0)
2180 return FAIL;
2181 *end = p;
2182
2183 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2184 import->imp_sid,
2185 idx,
2186 type);
2187 }
2188 else
2189 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002190 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002191 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2192 import->imp_sid,
2193 import->imp_var_vals_idx,
2194 import->imp_type);
2195 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002196 return OK;
2197 }
2198
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002199 if (error)
2200 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002201 return FAIL;
2202}
2203
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002204 static int
2205generate_funcref(cctx_T *cctx, char_u *name)
2206{
2207 ufunc_T *ufunc = find_func(name, cctx);
2208
2209 if (ufunc == NULL)
2210 return FAIL;
2211
2212 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2213}
2214
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002215/*
2216 * Compile a variable name into a load instruction.
2217 * "end" points to just after the name.
2218 * When "error" is FALSE do not give an error when not found.
2219 */
2220 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002221compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002222{
2223 type_T *type;
2224 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002225 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002226 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002227 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002228
2229 if (*(*arg + 1) == ':')
2230 {
2231 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002232 if (end <= *arg + 2)
2233 name = vim_strsave((char_u *)"[empty]");
2234 else
2235 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002236 if (name == NULL)
2237 return FAIL;
2238
2239 if (**arg == 'v')
2240 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002241 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002242 }
2243 else if (**arg == 'g')
2244 {
2245 // Global variables can be defined later, thus we don't check if it
2246 // exists, give error at runtime.
2247 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2248 }
2249 else if (**arg == 's')
2250 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002251 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002252 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002253 else if (**arg == 'b')
2254 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002255 // Buffer-local variables can be defined later, thus we don't check
2256 // if it exists, give error at runtime.
2257 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002258 }
2259 else if (**arg == 'w')
2260 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002261 // Window-local variables can be defined later, thus we don't check
2262 // if it exists, give error at runtime.
2263 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002264 }
2265 else if (**arg == 't')
2266 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002267 // Tabpage-local variables can be defined later, thus we don't
2268 // check if it exists, give error at runtime.
2269 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002270 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002271 else
2272 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002273 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002274 goto theend;
2275 }
2276 }
2277 else
2278 {
2279 size_t len = end - *arg;
2280 int idx;
2281 int gen_load = FALSE;
2282
2283 name = vim_strnsave(*arg, end - *arg);
2284 if (name == NULL)
2285 return FAIL;
2286
2287 idx = lookup_arg(*arg, len, cctx);
2288 if (idx >= 0)
2289 {
2290 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2291 type = cctx->ctx_ufunc->uf_arg_types[idx];
2292 else
2293 type = &t_any;
2294
2295 // Arguments are located above the frame pointer.
2296 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2297 if (cctx->ctx_ufunc->uf_va_name != NULL)
2298 --idx;
2299 gen_load = TRUE;
2300 }
2301 else if (lookup_vararg(*arg, len, cctx))
2302 {
2303 // varargs is always the last argument
2304 idx = -STACK_FRAME_SIZE - 1;
2305 type = cctx->ctx_ufunc->uf_va_type;
2306 gen_load = TRUE;
2307 }
2308 else
2309 {
2310 idx = lookup_local(*arg, len, cctx);
2311 if (idx >= 0)
2312 {
2313 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2314 gen_load = TRUE;
2315 }
2316 else
2317 {
2318 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2319 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2320 res = generate_PUSHBOOL(cctx, **arg == 't'
2321 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002322 else
2323 {
2324 // "var" can be script-local even without using "s:" if it
2325 // already exists.
2326 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2327 == SCRIPT_VERSION_VIM9
2328 || lookup_script(*arg, len) == OK)
2329 res = compile_load_scriptvar(cctx, name, *arg, &end,
2330 FALSE);
2331
2332 // When the name starts with an uppercase letter or "x:" it
2333 // can be a user defined function.
2334 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2335 res = generate_funcref(cctx, name);
2336 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002337 }
2338 }
2339 if (gen_load)
2340 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2341 }
2342
2343 *arg = end;
2344
2345theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002346 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002347 semsg(_(e_var_notfound), name);
2348 vim_free(name);
2349 return res;
2350}
2351
2352/*
2353 * Compile the argument expressions.
2354 * "arg" points to just after the "(" and is advanced to after the ")"
2355 */
2356 static int
2357compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2358{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002359 char_u *p = *arg;
2360 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002361
Bram Moolenaare6085c52020-04-12 20:19:16 +02002362 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002363 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002364 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002365 {
2366 p = next_line_from_context(cctx);
2367 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002368 goto failret;
2369 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002370 p = skipwhite(p);
2371 }
2372 if (*p == ')')
2373 {
2374 *arg = p + 1;
2375 return OK;
2376 }
2377
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002378 if (compile_expr1(&p, cctx) == FAIL)
2379 return FAIL;
2380 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002381
2382 if (*p != ',' && *skipwhite(p) == ',')
2383 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002384 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002385 p = skipwhite(p);
2386 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002387 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002388 {
2389 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002390 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002391 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002392 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002393 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002394 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002396failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002397 emsg(_(e_missing_close));
2398 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002399}
2400
2401/*
2402 * Compile a function call: name(arg1, arg2)
2403 * "arg" points to "name", "arg + varlen" to the "(".
2404 * "argcount_init" is 1 for "value->method()"
2405 * Instructions:
2406 * EVAL arg1
2407 * EVAL arg2
2408 * BCALL / DCALL / UCALL
2409 */
2410 static int
2411compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2412{
2413 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002414 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002415 int argcount = argcount_init;
2416 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002417 char_u fname_buf[FLEN_FIXED + 1];
2418 char_u *tofree = NULL;
2419 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002420 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002421 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002422
2423 if (varlen >= sizeof(namebuf))
2424 {
2425 semsg(_("E1011: name too long: %s"), name);
2426 return FAIL;
2427 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002428 vim_strncpy(namebuf, *arg, varlen);
2429 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002430
2431 *arg = skipwhite(*arg + varlen + 1);
2432 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002433 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002434
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002435 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002436 {
2437 int idx;
2438
2439 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002440 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002441 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002442 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002443 else
2444 semsg(_(e_unknownfunc), namebuf);
2445 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002446 }
2447
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002448 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002449 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002450 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002451 {
2452 res = generate_CALL(cctx, ufunc, argcount);
2453 goto theend;
2454 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002455
2456 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002457 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002458 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002459 if (STRNCMP(namebuf, "g:", 2) != 0
2460 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002461 {
2462 res = generate_PCALL(cctx, argcount, FALSE);
2463 goto theend;
2464 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002465
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002466 // A global function may be defined only later. Need to figure out at
2467 // runtime.
2468 if (STRNCMP(namebuf, "g:", 2) == 0)
2469 res = generate_UCALL(cctx, name, argcount);
2470 else
2471 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002472
2473theend:
2474 vim_free(tofree);
2475 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002476}
2477
2478// like NAMESPACE_CHAR but with 'a' and 'l'.
2479#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2480
2481/*
2482 * Find the end of a variable or function name. Unlike find_name_end() this
2483 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002484 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002485 * Return a pointer to just after the name. Equal to "arg" if there is no
2486 * valid name.
2487 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002488 static char_u *
2489to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002490{
2491 char_u *p;
2492
2493 // Quick check for valid starting character.
2494 if (!eval_isnamec1(*arg))
2495 return arg;
2496
2497 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2498 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2499 // and can be used in slice "[n:]".
2500 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002501 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002502 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2503 break;
2504 return p;
2505}
2506
2507/*
2508 * Like to_name_end() but also skip over a list or dict constant.
2509 */
2510 char_u *
2511to_name_const_end(char_u *arg)
2512{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002513 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002514 typval_T rettv;
2515
2516 if (p == arg && *arg == '[')
2517 {
2518
2519 // Can be "[1, 2, 3]->Func()".
2520 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2521 p = arg;
2522 }
2523 else if (p == arg && *arg == '#' && arg[1] == '{')
2524 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002525 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002526 ++p;
2527 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2528 p = arg;
2529 }
2530 else if (p == arg && *arg == '{')
2531 {
2532 int ret = get_lambda_tv(&p, &rettv, FALSE);
2533
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002534 // Can be "{x -> ret}()".
2535 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002536 if (ret == NOTDONE)
2537 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2538 if (ret != OK)
2539 p = arg;
2540 }
2541
2542 return p;
2543}
2544
2545 static void
2546type_mismatch(type_T *expected, type_T *actual)
2547{
2548 char *tofree1, *tofree2;
2549
2550 semsg(_("E1013: type mismatch, expected %s but got %s"),
2551 type_name(expected, &tofree1), type_name(actual, &tofree2));
2552 vim_free(tofree1);
2553 vim_free(tofree2);
2554}
2555
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002556 static void
2557arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2558{
2559 char *tofree1, *tofree2;
2560
2561 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2562 argidx,
2563 type_name(expected, &tofree1), type_name(actual, &tofree2));
2564 vim_free(tofree1);
2565 vim_free(tofree2);
2566}
2567
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002568/*
2569 * Check if the expected and actual types match.
2570 */
2571 static int
2572check_type(type_T *expected, type_T *actual, int give_msg)
2573{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002574 int ret = OK;
2575
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002576 // When expected is "unknown" we accept any actual type.
2577 // When expected is "any" we accept any actual type except "void".
2578 if (expected->tt_type != VAR_UNKNOWN
2579 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002580 {
2581 if (expected->tt_type != actual->tt_type)
2582 {
2583 if (give_msg)
2584 type_mismatch(expected, actual);
2585 return FAIL;
2586 }
2587 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2588 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002589 // "unknown" is used for an empty list or dict
2590 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002591 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002592 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002593 else if (expected->tt_type == VAR_FUNC)
2594 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002595 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002596 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2597 if (ret == OK && expected->tt_argcount != -1
2598 && (actual->tt_argcount < expected->tt_min_argcount
2599 || actual->tt_argcount > expected->tt_argcount))
2600 ret = FAIL;
2601 }
2602 if (ret == FAIL && give_msg)
2603 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002604 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002605 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002606}
2607
2608/*
2609 * Check that
2610 * - "actual" is "expected" type or
2611 * - "actual" is a type that can be "expected" type: add a runtime check; or
2612 * - return FAIL.
2613 */
2614 static int
2615need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2616{
Bram Moolenaar89228602020-04-05 22:14:54 +02002617 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002618 return OK;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002619 if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002620 {
2621 type_mismatch(expected, actual);
2622 return FAIL;
2623 }
2624 generate_TYPECHECK(cctx, expected, offset);
2625 return OK;
2626}
2627
2628/*
2629 * parse a list: [expr, expr]
2630 * "*arg" points to the '['.
2631 */
2632 static int
2633compile_list(char_u **arg, cctx_T *cctx)
2634{
2635 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002636 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002637 int count = 0;
2638
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002639 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002640 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002641 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002642 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002643 p = next_line_from_context(cctx);
2644 if (p == NULL)
2645 {
2646 semsg(_(e_list_end), *arg);
2647 return FAIL;
2648 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002649 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002650 p = skipwhite(p);
2651 }
2652 if (*p == ']')
2653 {
2654 ++p;
2655 // Allow for following comment, after at least one space.
2656 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2657 p += STRLEN(p);
2658 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002659 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002660 if (compile_expr1(&p, cctx) == FAIL)
2661 break;
2662 ++count;
2663 if (*p == ',')
2664 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002665 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002666 p = skipwhite(p);
2667 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002668 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002669
2670 generate_NEWLIST(cctx, count);
2671 return OK;
2672}
2673
2674/*
2675 * parse a lambda: {arg, arg -> expr}
2676 * "*arg" points to the '{'.
2677 */
2678 static int
2679compile_lambda(char_u **arg, cctx_T *cctx)
2680{
2681 garray_T *instr = &cctx->ctx_instr;
2682 typval_T rettv;
2683 ufunc_T *ufunc;
2684
2685 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002686 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002687 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002688
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002689 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002690 ++ufunc->uf_refcount;
2691 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002692 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002693
2694 // The function will have one line: "return {expr}".
2695 // Compile it into instructions.
2696 compile_def_function(ufunc, TRUE);
2697
2698 if (ufunc->uf_dfunc_idx >= 0)
2699 {
2700 if (ga_grow(instr, 1) == FAIL)
2701 return FAIL;
2702 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2703 return OK;
2704 }
2705 return FAIL;
2706}
2707
2708/*
2709 * Compile a lamda call: expr->{lambda}(args)
2710 * "arg" points to the "{".
2711 */
2712 static int
2713compile_lambda_call(char_u **arg, cctx_T *cctx)
2714{
2715 ufunc_T *ufunc;
2716 typval_T rettv;
2717 int argcount = 1;
2718 int ret = FAIL;
2719
2720 // Get the funcref in "rettv".
2721 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2722 return FAIL;
2723
2724 if (**arg != '(')
2725 {
2726 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002727 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002728 else
2729 semsg(_(e_missing_paren), "lambda");
2730 clear_tv(&rettv);
2731 return FAIL;
2732 }
2733
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002734 ufunc = rettv.vval.v_partial->pt_func;
2735 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002736 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002737 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002738
2739 // The function will have one line: "return {expr}".
2740 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002741 compile_def_function(ufunc, TRUE);
2742
2743 // compile the arguments
2744 *arg = skipwhite(*arg + 1);
2745 if (compile_arguments(arg, cctx, &argcount) == OK)
2746 // call the compiled function
2747 ret = generate_CALL(cctx, ufunc, argcount);
2748
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002749 return ret;
2750}
2751
2752/*
2753 * parse a dict: {'key': val} or #{key: val}
2754 * "*arg" points to the '{'.
2755 */
2756 static int
2757compile_dict(char_u **arg, cctx_T *cctx, int literal)
2758{
2759 garray_T *instr = &cctx->ctx_instr;
2760 int count = 0;
2761 dict_T *d = dict_alloc();
2762 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002763 char_u *whitep = *arg;
2764 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002765
2766 if (d == NULL)
2767 return FAIL;
2768 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002769 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002770 {
2771 char_u *key = NULL;
2772
Bram Moolenaar2c330432020-04-13 14:41:35 +02002773 while (**arg == NUL || (literal && **arg == '"')
2774 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002775 {
2776 *arg = next_line_from_context(cctx);
2777 if (*arg == NULL)
2778 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002779 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002780 *arg = skipwhite(*arg);
2781 }
2782
2783 if (**arg == '}')
2784 break;
2785
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002786 if (literal)
2787 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002788 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002789
Bram Moolenaar2c330432020-04-13 14:41:35 +02002790 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002791 {
2792 semsg(_("E1014: Invalid key: %s"), *arg);
2793 return FAIL;
2794 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002795 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002796 if (generate_PUSHS(cctx, key) == FAIL)
2797 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002798 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002799 }
2800 else
2801 {
2802 isn_T *isn;
2803
2804 if (compile_expr1(arg, cctx) == FAIL)
2805 return FAIL;
2806 // TODO: check type is string
2807 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2808 if (isn->isn_type == ISN_PUSHS)
2809 key = isn->isn_arg.string;
2810 }
2811
2812 // Check for duplicate keys, if using string keys.
2813 if (key != NULL)
2814 {
2815 item = dict_find(d, key, -1);
2816 if (item != NULL)
2817 {
2818 semsg(_(e_duplicate_key), key);
2819 goto failret;
2820 }
2821 item = dictitem_alloc(key);
2822 if (item != NULL)
2823 {
2824 item->di_tv.v_type = VAR_UNKNOWN;
2825 item->di_tv.v_lock = 0;
2826 if (dict_add(d, item) == FAIL)
2827 dictitem_free(item);
2828 }
2829 }
2830
2831 *arg = skipwhite(*arg);
2832 if (**arg != ':')
2833 {
2834 semsg(_(e_missing_dict_colon), *arg);
2835 return FAIL;
2836 }
2837
Bram Moolenaar2c330432020-04-13 14:41:35 +02002838 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002839 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002840 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002841 {
2842 *arg = next_line_from_context(cctx);
2843 if (*arg == NULL)
2844 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002845 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002846 *arg = skipwhite(*arg);
2847 }
2848
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002849 if (compile_expr1(arg, cctx) == FAIL)
2850 return FAIL;
2851 ++count;
2852
Bram Moolenaar2c330432020-04-13 14:41:35 +02002853 whitep = *arg;
2854 p = skipwhite(*arg);
2855 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002856 {
2857 *arg = next_line_from_context(cctx);
2858 if (*arg == NULL)
2859 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002860 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002861 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002862 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002863 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002864 if (**arg == '}')
2865 break;
2866 if (**arg != ',')
2867 {
2868 semsg(_(e_missing_dict_comma), *arg);
2869 goto failret;
2870 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002871 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002872 *arg = skipwhite(*arg + 1);
2873 }
2874
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002875 *arg = *arg + 1;
2876
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002877 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002878 p = skipwhite(*arg);
2879 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002880 *arg += STRLEN(*arg);
2881
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002882 dict_unref(d);
2883 return generate_NEWDICT(cctx, count);
2884
2885failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002886 if (*arg == NULL)
2887 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002888 dict_unref(d);
2889 return FAIL;
2890}
2891
2892/*
2893 * Compile "&option".
2894 */
2895 static int
2896compile_get_option(char_u **arg, cctx_T *cctx)
2897{
2898 typval_T rettv;
2899 char_u *start = *arg;
2900 int ret;
2901
2902 // parse the option and get the current value to get the type.
2903 rettv.v_type = VAR_UNKNOWN;
2904 ret = get_option_tv(arg, &rettv, TRUE);
2905 if (ret == OK)
2906 {
2907 // include the '&' in the name, get_option_tv() expects it.
2908 char_u *name = vim_strnsave(start, *arg - start);
2909 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2910
2911 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2912 vim_free(name);
2913 }
2914 clear_tv(&rettv);
2915
2916 return ret;
2917}
2918
2919/*
2920 * Compile "$VAR".
2921 */
2922 static int
2923compile_get_env(char_u **arg, cctx_T *cctx)
2924{
2925 char_u *start = *arg;
2926 int len;
2927 int ret;
2928 char_u *name;
2929
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002930 ++*arg;
2931 len = get_env_len(arg);
2932 if (len == 0)
2933 {
2934 semsg(_(e_syntax_at), start - 1);
2935 return FAIL;
2936 }
2937
2938 // include the '$' in the name, get_env_tv() expects it.
2939 name = vim_strnsave(start, len + 1);
2940 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2941 vim_free(name);
2942 return ret;
2943}
2944
2945/*
2946 * Compile "@r".
2947 */
2948 static int
2949compile_get_register(char_u **arg, cctx_T *cctx)
2950{
2951 int ret;
2952
2953 ++*arg;
2954 if (**arg == NUL)
2955 {
2956 semsg(_(e_syntax_at), *arg - 1);
2957 return FAIL;
2958 }
2959 if (!valid_yank_reg(**arg, TRUE))
2960 {
2961 emsg_invreg(**arg);
2962 return FAIL;
2963 }
2964 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2965 ++*arg;
2966 return ret;
2967}
2968
2969/*
2970 * Apply leading '!', '-' and '+' to constant "rettv".
2971 */
2972 static int
2973apply_leader(typval_T *rettv, char_u *start, char_u *end)
2974{
2975 char_u *p = end;
2976
2977 // this works from end to start
2978 while (p > start)
2979 {
2980 --p;
2981 if (*p == '-' || *p == '+')
2982 {
2983 // only '-' has an effect, for '+' we only check the type
2984#ifdef FEAT_FLOAT
2985 if (rettv->v_type == VAR_FLOAT)
2986 {
2987 if (*p == '-')
2988 rettv->vval.v_float = -rettv->vval.v_float;
2989 }
2990 else
2991#endif
2992 {
2993 varnumber_T val;
2994 int error = FALSE;
2995
2996 // tv_get_number_chk() accepts a string, but we don't want that
2997 // here
2998 if (check_not_string(rettv) == FAIL)
2999 return FAIL;
3000 val = tv_get_number_chk(rettv, &error);
3001 clear_tv(rettv);
3002 if (error)
3003 return FAIL;
3004 if (*p == '-')
3005 val = -val;
3006 rettv->v_type = VAR_NUMBER;
3007 rettv->vval.v_number = val;
3008 }
3009 }
3010 else
3011 {
3012 int v = tv2bool(rettv);
3013
3014 // '!' is permissive in the type.
3015 clear_tv(rettv);
3016 rettv->v_type = VAR_BOOL;
3017 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3018 }
3019 }
3020 return OK;
3021}
3022
3023/*
3024 * Recognize v: variables that are constants and set "rettv".
3025 */
3026 static void
3027get_vim_constant(char_u **arg, typval_T *rettv)
3028{
3029 if (STRNCMP(*arg, "v:true", 6) == 0)
3030 {
3031 rettv->v_type = VAR_BOOL;
3032 rettv->vval.v_number = VVAL_TRUE;
3033 *arg += 6;
3034 }
3035 else if (STRNCMP(*arg, "v:false", 7) == 0)
3036 {
3037 rettv->v_type = VAR_BOOL;
3038 rettv->vval.v_number = VVAL_FALSE;
3039 *arg += 7;
3040 }
3041 else if (STRNCMP(*arg, "v:null", 6) == 0)
3042 {
3043 rettv->v_type = VAR_SPECIAL;
3044 rettv->vval.v_number = VVAL_NULL;
3045 *arg += 6;
3046 }
3047 else if (STRNCMP(*arg, "v:none", 6) == 0)
3048 {
3049 rettv->v_type = VAR_SPECIAL;
3050 rettv->vval.v_number = VVAL_NONE;
3051 *arg += 6;
3052 }
3053}
3054
3055/*
3056 * Compile code to apply '-', '+' and '!'.
3057 */
3058 static int
3059compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3060{
3061 char_u *p = end;
3062
3063 // this works from end to start
3064 while (p > start)
3065 {
3066 --p;
3067 if (*p == '-' || *p == '+')
3068 {
3069 int negate = *p == '-';
3070 isn_T *isn;
3071
3072 // TODO: check type
3073 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3074 {
3075 --p;
3076 if (*p == '-')
3077 negate = !negate;
3078 }
3079 // only '-' has an effect, for '+' we only check the type
3080 if (negate)
3081 isn = generate_instr(cctx, ISN_NEGATENR);
3082 else
3083 isn = generate_instr(cctx, ISN_CHECKNR);
3084 if (isn == NULL)
3085 return FAIL;
3086 }
3087 else
3088 {
3089 int invert = TRUE;
3090
3091 while (p > start && p[-1] == '!')
3092 {
3093 --p;
3094 invert = !invert;
3095 }
3096 if (generate_2BOOL(cctx, invert) == FAIL)
3097 return FAIL;
3098 }
3099 }
3100 return OK;
3101}
3102
3103/*
3104 * Compile whatever comes after "name" or "name()".
3105 */
3106 static int
3107compile_subscript(
3108 char_u **arg,
3109 cctx_T *cctx,
3110 char_u **start_leader,
3111 char_u *end_leader)
3112{
3113 for (;;)
3114 {
3115 if (**arg == '(')
3116 {
3117 int argcount = 0;
3118
3119 // funcref(arg)
3120 *arg = skipwhite(*arg + 1);
3121 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3122 return FAIL;
3123 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
3124 return FAIL;
3125 }
3126 else if (**arg == '-' && (*arg)[1] == '>')
3127 {
3128 char_u *p;
3129
3130 // something->method()
3131 // Apply the '!', '-' and '+' first:
3132 // -1.0->func() works like (-1.0)->func()
3133 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3134 return FAIL;
3135 *start_leader = end_leader; // don't apply again later
3136
3137 *arg = skipwhite(*arg + 2);
3138 if (**arg == '{')
3139 {
3140 // lambda call: list->{lambda}
3141 if (compile_lambda_call(arg, cctx) == FAIL)
3142 return FAIL;
3143 }
3144 else
3145 {
3146 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003147 p = *arg;
3148 if (ASCII_ISALPHA(*p) && p[1] == ':')
3149 p += 2;
3150 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003151 ;
3152 if (*p != '(')
3153 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003154 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003155 return FAIL;
3156 }
3157 // TODO: base value may not be the first argument
3158 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3159 return FAIL;
3160 }
3161 }
3162 else if (**arg == '[')
3163 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003164 garray_T *stack;
3165 type_T **typep;
3166
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003167 // list index: list[123]
3168 // TODO: more arguments
3169 // TODO: dict member dict['name']
3170 *arg = skipwhite(*arg + 1);
3171 if (compile_expr1(arg, cctx) == FAIL)
3172 return FAIL;
3173
3174 if (**arg != ']')
3175 {
3176 emsg(_(e_missbrac));
3177 return FAIL;
3178 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003179 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003180
3181 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3182 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003183 stack = &cctx->ctx_type_stack;
3184 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3185 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3186 {
3187 emsg(_(e_listreq));
3188 return FAIL;
3189 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003190 if ((*typep)->tt_type == VAR_LIST)
3191 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003192 }
3193 else if (**arg == '.' && (*arg)[1] != '.')
3194 {
3195 char_u *p;
3196
3197 ++*arg;
3198 p = *arg;
3199 // dictionary member: dict.name
3200 if (eval_isnamec1(*p))
3201 while (eval_isnamec(*p))
3202 MB_PTR_ADV(p);
3203 if (p == *arg)
3204 {
3205 semsg(_(e_syntax_at), *arg);
3206 return FAIL;
3207 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003208 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3209 return FAIL;
3210 *arg = p;
3211 }
3212 else
3213 break;
3214 }
3215
3216 // TODO - see handle_subscript():
3217 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3218 // Don't do this when "Func" is already a partial that was bound
3219 // explicitly (pt_auto is FALSE).
3220
3221 return OK;
3222}
3223
3224/*
3225 * Compile an expression at "*p" and add instructions to "instr".
3226 * "p" is advanced until after the expression, skipping white space.
3227 *
3228 * This is the equivalent of eval1(), eval2(), etc.
3229 */
3230
3231/*
3232 * number number constant
3233 * 0zFFFFFFFF Blob constant
3234 * "string" string constant
3235 * 'string' literal string constant
3236 * &option-name option value
3237 * @r register contents
3238 * identifier variable value
3239 * function() function call
3240 * $VAR environment variable
3241 * (expression) nested expression
3242 * [expr, expr] List
3243 * {key: val, key: val} Dictionary
3244 * #{key: val, key: val} Dictionary with literal keys
3245 *
3246 * Also handle:
3247 * ! in front logical NOT
3248 * - in front unary minus
3249 * + in front unary plus (ignored)
3250 * trailing (arg) funcref/partial call
3251 * trailing [] subscript in String or List
3252 * trailing .name entry in Dictionary
3253 * trailing ->name() method call
3254 */
3255 static int
3256compile_expr7(char_u **arg, cctx_T *cctx)
3257{
3258 typval_T rettv;
3259 char_u *start_leader, *end_leader;
3260 int ret = OK;
3261
3262 /*
3263 * Skip '!', '-' and '+' characters. They are handled later.
3264 */
3265 start_leader = *arg;
3266 while (**arg == '!' || **arg == '-' || **arg == '+')
3267 *arg = skipwhite(*arg + 1);
3268 end_leader = *arg;
3269
3270 rettv.v_type = VAR_UNKNOWN;
3271 switch (**arg)
3272 {
3273 /*
3274 * Number constant.
3275 */
3276 case '0': // also for blob starting with 0z
3277 case '1':
3278 case '2':
3279 case '3':
3280 case '4':
3281 case '5':
3282 case '6':
3283 case '7':
3284 case '8':
3285 case '9':
3286 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3287 return FAIL;
3288 break;
3289
3290 /*
3291 * String constant: "string".
3292 */
3293 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3294 return FAIL;
3295 break;
3296
3297 /*
3298 * Literal string constant: 'str''ing'.
3299 */
3300 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3301 return FAIL;
3302 break;
3303
3304 /*
3305 * Constant Vim variable.
3306 */
3307 case 'v': get_vim_constant(arg, &rettv);
3308 ret = NOTDONE;
3309 break;
3310
3311 /*
3312 * List: [expr, expr]
3313 */
3314 case '[': ret = compile_list(arg, cctx);
3315 break;
3316
3317 /*
3318 * Dictionary: #{key: val, key: val}
3319 */
3320 case '#': if ((*arg)[1] == '{')
3321 {
3322 ++*arg;
3323 ret = compile_dict(arg, cctx, TRUE);
3324 }
3325 else
3326 ret = NOTDONE;
3327 break;
3328
3329 /*
3330 * Lambda: {arg, arg -> expr}
3331 * Dictionary: {'key': val, 'key': val}
3332 */
3333 case '{': {
3334 char_u *start = skipwhite(*arg + 1);
3335
3336 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003337 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003338 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003339 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003340 if (ret != FAIL && *start == '>')
3341 ret = compile_lambda(arg, cctx);
3342 else
3343 ret = compile_dict(arg, cctx, FALSE);
3344 }
3345 break;
3346
3347 /*
3348 * Option value: &name
3349 */
3350 case '&': ret = compile_get_option(arg, cctx);
3351 break;
3352
3353 /*
3354 * Environment variable: $VAR.
3355 */
3356 case '$': ret = compile_get_env(arg, cctx);
3357 break;
3358
3359 /*
3360 * Register contents: @r.
3361 */
3362 case '@': ret = compile_get_register(arg, cctx);
3363 break;
3364 /*
3365 * nested expression: (expression).
3366 */
3367 case '(': *arg = skipwhite(*arg + 1);
3368 ret = compile_expr1(arg, cctx); // recursive!
3369 *arg = skipwhite(*arg);
3370 if (**arg == ')')
3371 ++*arg;
3372 else if (ret == OK)
3373 {
3374 emsg(_(e_missing_close));
3375 ret = FAIL;
3376 }
3377 break;
3378
3379 default: ret = NOTDONE;
3380 break;
3381 }
3382 if (ret == FAIL)
3383 return FAIL;
3384
3385 if (rettv.v_type != VAR_UNKNOWN)
3386 {
3387 // apply the '!', '-' and '+' before the constant
3388 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3389 {
3390 clear_tv(&rettv);
3391 return FAIL;
3392 }
3393 start_leader = end_leader; // don't apply again below
3394
3395 // push constant
3396 switch (rettv.v_type)
3397 {
3398 case VAR_BOOL:
3399 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3400 break;
3401 case VAR_SPECIAL:
3402 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3403 break;
3404 case VAR_NUMBER:
3405 generate_PUSHNR(cctx, rettv.vval.v_number);
3406 break;
3407#ifdef FEAT_FLOAT
3408 case VAR_FLOAT:
3409 generate_PUSHF(cctx, rettv.vval.v_float);
3410 break;
3411#endif
3412 case VAR_BLOB:
3413 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3414 rettv.vval.v_blob = NULL;
3415 break;
3416 case VAR_STRING:
3417 generate_PUSHS(cctx, rettv.vval.v_string);
3418 rettv.vval.v_string = NULL;
3419 break;
3420 default:
3421 iemsg("constant type missing");
3422 return FAIL;
3423 }
3424 }
3425 else if (ret == NOTDONE)
3426 {
3427 char_u *p;
3428 int r;
3429
3430 if (!eval_isnamec1(**arg))
3431 {
3432 semsg(_("E1015: Name expected: %s"), *arg);
3433 return FAIL;
3434 }
3435
3436 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003437 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003438 if (*p == '(')
3439 r = compile_call(arg, p - *arg, cctx, 0);
3440 else
3441 r = compile_load(arg, p, cctx, TRUE);
3442 if (r == FAIL)
3443 return FAIL;
3444 }
3445
3446 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3447 return FAIL;
3448
3449 // Now deal with prefixed '-', '+' and '!', if not done already.
3450 return compile_leader(cctx, start_leader, end_leader);
3451}
3452
3453/*
3454 * * number multiplication
3455 * / number division
3456 * % number modulo
3457 */
3458 static int
3459compile_expr6(char_u **arg, cctx_T *cctx)
3460{
3461 char_u *op;
3462
3463 // get the first variable
3464 if (compile_expr7(arg, cctx) == FAIL)
3465 return FAIL;
3466
3467 /*
3468 * Repeat computing, until no "*", "/" or "%" is following.
3469 */
3470 for (;;)
3471 {
3472 op = skipwhite(*arg);
3473 if (*op != '*' && *op != '/' && *op != '%')
3474 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003475 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003476 {
3477 char_u buf[3];
3478
3479 vim_strncpy(buf, op, 1);
3480 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003481 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003482 }
3483 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003484 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003485 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003486
3487 // get the second variable
3488 if (compile_expr7(arg, cctx) == FAIL)
3489 return FAIL;
3490
3491 generate_two_op(cctx, op);
3492 }
3493
3494 return OK;
3495}
3496
3497/*
3498 * + number addition
3499 * - number subtraction
3500 * .. string concatenation
3501 */
3502 static int
3503compile_expr5(char_u **arg, cctx_T *cctx)
3504{
3505 char_u *op;
3506 int oplen;
3507
3508 // get the first variable
3509 if (compile_expr6(arg, cctx) == FAIL)
3510 return FAIL;
3511
3512 /*
3513 * Repeat computing, until no "+", "-" or ".." is following.
3514 */
3515 for (;;)
3516 {
3517 op = skipwhite(*arg);
3518 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3519 break;
3520 oplen = (*op == '.' ? 2 : 1);
3521
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003522 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003523 {
3524 char_u buf[3];
3525
3526 vim_strncpy(buf, op, oplen);
3527 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003528 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003529 }
3530
3531 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003532 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003533 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003534
3535 // get the second variable
3536 if (compile_expr6(arg, cctx) == FAIL)
3537 return FAIL;
3538
3539 if (*op == '.')
3540 {
3541 if (may_generate_2STRING(-2, cctx) == FAIL
3542 || may_generate_2STRING(-1, cctx) == FAIL)
3543 return FAIL;
3544 generate_instr_drop(cctx, ISN_CONCAT, 1);
3545 }
3546 else
3547 generate_two_op(cctx, op);
3548 }
3549
3550 return OK;
3551}
3552
Bram Moolenaar080457c2020-03-03 21:53:32 +01003553 static exptype_T
3554get_compare_type(char_u *p, int *len, int *type_is)
3555{
3556 exptype_T type = EXPR_UNKNOWN;
3557 int i;
3558
3559 switch (p[0])
3560 {
3561 case '=': if (p[1] == '=')
3562 type = EXPR_EQUAL;
3563 else if (p[1] == '~')
3564 type = EXPR_MATCH;
3565 break;
3566 case '!': if (p[1] == '=')
3567 type = EXPR_NEQUAL;
3568 else if (p[1] == '~')
3569 type = EXPR_NOMATCH;
3570 break;
3571 case '>': if (p[1] != '=')
3572 {
3573 type = EXPR_GREATER;
3574 *len = 1;
3575 }
3576 else
3577 type = EXPR_GEQUAL;
3578 break;
3579 case '<': if (p[1] != '=')
3580 {
3581 type = EXPR_SMALLER;
3582 *len = 1;
3583 }
3584 else
3585 type = EXPR_SEQUAL;
3586 break;
3587 case 'i': if (p[1] == 's')
3588 {
3589 // "is" and "isnot"; but not a prefix of a name
3590 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3591 *len = 5;
3592 i = p[*len];
3593 if (!isalnum(i) && i != '_')
3594 {
3595 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3596 *type_is = TRUE;
3597 }
3598 }
3599 break;
3600 }
3601 return type;
3602}
3603
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003604/*
3605 * expr5a == expr5b
3606 * expr5a =~ expr5b
3607 * expr5a != expr5b
3608 * expr5a !~ expr5b
3609 * expr5a > expr5b
3610 * expr5a >= expr5b
3611 * expr5a < expr5b
3612 * expr5a <= expr5b
3613 * expr5a is expr5b
3614 * expr5a isnot expr5b
3615 *
3616 * Produces instructions:
3617 * EVAL expr5a Push result of "expr5a"
3618 * EVAL expr5b Push result of "expr5b"
3619 * COMPARE one of the compare instructions
3620 */
3621 static int
3622compile_expr4(char_u **arg, cctx_T *cctx)
3623{
3624 exptype_T type = EXPR_UNKNOWN;
3625 char_u *p;
3626 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003627 int type_is = FALSE;
3628
3629 // get the first variable
3630 if (compile_expr5(arg, cctx) == FAIL)
3631 return FAIL;
3632
3633 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003634 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003635
3636 /*
3637 * If there is a comparative operator, use it.
3638 */
3639 if (type != EXPR_UNKNOWN)
3640 {
3641 int ic = FALSE; // Default: do not ignore case
3642
3643 if (type_is && (p[len] == '?' || p[len] == '#'))
3644 {
3645 semsg(_(e_invexpr2), *arg);
3646 return FAIL;
3647 }
3648 // extra question mark appended: ignore case
3649 if (p[len] == '?')
3650 {
3651 ic = TRUE;
3652 ++len;
3653 }
3654 // extra '#' appended: match case (ignored)
3655 else if (p[len] == '#')
3656 ++len;
3657 // nothing appended: match case
3658
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003659 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003660 {
3661 char_u buf[7];
3662
3663 vim_strncpy(buf, p, len);
3664 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003665 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003666 }
3667
3668 // get the second variable
3669 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003670 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003671 return FAIL;
3672
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003673 if (compile_expr5(arg, cctx) == FAIL)
3674 return FAIL;
3675
3676 generate_COMPARE(cctx, type, ic);
3677 }
3678
3679 return OK;
3680}
3681
3682/*
3683 * Compile || or &&.
3684 */
3685 static int
3686compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3687{
3688 char_u *p = skipwhite(*arg);
3689 int opchar = *op;
3690
3691 if (p[0] == opchar && p[1] == opchar)
3692 {
3693 garray_T *instr = &cctx->ctx_instr;
3694 garray_T end_ga;
3695
3696 /*
3697 * Repeat until there is no following "||" or "&&"
3698 */
3699 ga_init2(&end_ga, sizeof(int), 10);
3700 while (p[0] == opchar && p[1] == opchar)
3701 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003702 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3703 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003704 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003705 return FAIL;
3706 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003707
3708 if (ga_grow(&end_ga, 1) == FAIL)
3709 {
3710 ga_clear(&end_ga);
3711 return FAIL;
3712 }
3713 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3714 ++end_ga.ga_len;
3715 generate_JUMP(cctx, opchar == '|'
3716 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3717
3718 // eval the next expression
3719 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003720 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003721 return FAIL;
3722
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003723 if ((opchar == '|' ? compile_expr3(arg, cctx)
3724 : compile_expr4(arg, cctx)) == FAIL)
3725 {
3726 ga_clear(&end_ga);
3727 return FAIL;
3728 }
3729 p = skipwhite(*arg);
3730 }
3731
3732 // Fill in the end label in all jumps.
3733 while (end_ga.ga_len > 0)
3734 {
3735 isn_T *isn;
3736
3737 --end_ga.ga_len;
3738 isn = ((isn_T *)instr->ga_data)
3739 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3740 isn->isn_arg.jump.jump_where = instr->ga_len;
3741 }
3742 ga_clear(&end_ga);
3743 }
3744
3745 return OK;
3746}
3747
3748/*
3749 * expr4a && expr4a && expr4a logical AND
3750 *
3751 * Produces instructions:
3752 * EVAL expr4a Push result of "expr4a"
3753 * JUMP_AND_KEEP_IF_FALSE end
3754 * EVAL expr4b Push result of "expr4b"
3755 * JUMP_AND_KEEP_IF_FALSE end
3756 * EVAL expr4c Push result of "expr4c"
3757 * end:
3758 */
3759 static int
3760compile_expr3(char_u **arg, cctx_T *cctx)
3761{
3762 // get the first variable
3763 if (compile_expr4(arg, cctx) == FAIL)
3764 return FAIL;
3765
3766 // || and && work almost the same
3767 return compile_and_or(arg, cctx, "&&");
3768}
3769
3770/*
3771 * expr3a || expr3b || expr3c logical OR
3772 *
3773 * Produces instructions:
3774 * EVAL expr3a Push result of "expr3a"
3775 * JUMP_AND_KEEP_IF_TRUE end
3776 * EVAL expr3b Push result of "expr3b"
3777 * JUMP_AND_KEEP_IF_TRUE end
3778 * EVAL expr3c Push result of "expr3c"
3779 * end:
3780 */
3781 static int
3782compile_expr2(char_u **arg, cctx_T *cctx)
3783{
3784 // eval the first expression
3785 if (compile_expr3(arg, cctx) == FAIL)
3786 return FAIL;
3787
3788 // || and && work almost the same
3789 return compile_and_or(arg, cctx, "||");
3790}
3791
3792/*
3793 * Toplevel expression: expr2 ? expr1a : expr1b
3794 *
3795 * Produces instructions:
3796 * EVAL expr2 Push result of "expr"
3797 * JUMP_IF_FALSE alt jump if false
3798 * EVAL expr1a
3799 * JUMP_ALWAYS end
3800 * alt: EVAL expr1b
3801 * end:
3802 */
3803 static int
3804compile_expr1(char_u **arg, cctx_T *cctx)
3805{
3806 char_u *p;
3807
3808 // evaluate the first expression
3809 if (compile_expr2(arg, cctx) == FAIL)
3810 return FAIL;
3811
3812 p = skipwhite(*arg);
3813 if (*p == '?')
3814 {
3815 garray_T *instr = &cctx->ctx_instr;
3816 garray_T *stack = &cctx->ctx_type_stack;
3817 int alt_idx = instr->ga_len;
3818 int end_idx;
3819 isn_T *isn;
3820 type_T *type1;
3821 type_T *type2;
3822
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003823 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3824 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003825 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003826 return FAIL;
3827 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003828
3829 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3830
3831 // evaluate the second expression; any type is accepted
3832 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003833 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003834 return FAIL;
3835
Bram Moolenaara6d53682020-01-28 23:04:06 +01003836 if (compile_expr1(arg, cctx) == FAIL)
3837 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003838
3839 // remember the type and drop it
3840 --stack->ga_len;
3841 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3842
3843 end_idx = instr->ga_len;
3844 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3845
3846 // jump here from JUMP_IF_FALSE
3847 isn = ((isn_T *)instr->ga_data) + alt_idx;
3848 isn->isn_arg.jump.jump_where = instr->ga_len;
3849
3850 // Check for the ":".
3851 p = skipwhite(*arg);
3852 if (*p != ':')
3853 {
3854 emsg(_(e_missing_colon));
3855 return FAIL;
3856 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003857 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3858 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003859 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003860 return FAIL;
3861 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003862
3863 // evaluate the third expression
3864 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003865 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003866 return FAIL;
3867
Bram Moolenaara6d53682020-01-28 23:04:06 +01003868 if (compile_expr1(arg, cctx) == FAIL)
3869 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003870
3871 // If the types differ, the result has a more generic type.
3872 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003873 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003874
3875 // jump here from JUMP_ALWAYS
3876 isn = ((isn_T *)instr->ga_data) + end_idx;
3877 isn->isn_arg.jump.jump_where = instr->ga_len;
3878 }
3879 return OK;
3880}
3881
3882/*
3883 * compile "return [expr]"
3884 */
3885 static char_u *
3886compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3887{
3888 char_u *p = arg;
3889 garray_T *stack = &cctx->ctx_type_stack;
3890 type_T *stack_type;
3891
3892 if (*p != NUL && *p != '|' && *p != '\n')
3893 {
3894 // compile return argument into instructions
3895 if (compile_expr1(&p, cctx) == FAIL)
3896 return NULL;
3897
3898 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3899 if (set_return_type)
3900 cctx->ctx_ufunc->uf_ret_type = stack_type;
3901 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3902 == FAIL)
3903 return NULL;
3904 }
3905 else
3906 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003907 // "set_return_type" cannot be TRUE, only used for a lambda which
3908 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003909 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3910 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003911 {
3912 emsg(_("E1003: Missing return value"));
3913 return NULL;
3914 }
3915
3916 // No argument, return zero.
3917 generate_PUSHNR(cctx, 0);
3918 }
3919
3920 if (generate_instr(cctx, ISN_RETURN) == NULL)
3921 return NULL;
3922
3923 // "return val | endif" is possible
3924 return skipwhite(p);
3925}
3926
3927/*
3928 * Return the length of an assignment operator, or zero if there isn't one.
3929 */
3930 int
3931assignment_len(char_u *p, int *heredoc)
3932{
3933 if (*p == '=')
3934 {
3935 if (p[1] == '<' && p[2] == '<')
3936 {
3937 *heredoc = TRUE;
3938 return 3;
3939 }
3940 return 1;
3941 }
3942 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3943 return 2;
3944 if (STRNCMP(p, "..=", 3) == 0)
3945 return 3;
3946 return 0;
3947}
3948
3949// words that cannot be used as a variable
3950static char *reserved[] = {
3951 "true",
3952 "false",
3953 NULL
3954};
3955
3956/*
3957 * Get a line for "=<<".
3958 * Return a pointer to the line in allocated memory.
3959 * Return NULL for end-of-file or some error.
3960 */
3961 static char_u *
3962heredoc_getline(
3963 int c UNUSED,
3964 void *cookie,
3965 int indent UNUSED,
3966 int do_concat UNUSED)
3967{
3968 cctx_T *cctx = (cctx_T *)cookie;
3969
3970 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003971 {
3972 iemsg("Heredoc got to end");
3973 return NULL;
3974 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003975 ++cctx->ctx_lnum;
3976 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3977 [cctx->ctx_lnum]);
3978}
3979
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003980typedef enum {
3981 dest_local,
3982 dest_option,
3983 dest_env,
3984 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02003985 dest_buffer,
3986 dest_window,
3987 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003988 dest_vimvar,
3989 dest_script,
3990 dest_reg,
3991} assign_dest_T;
3992
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003993/*
3994 * compile "let var [= expr]", "const var = expr" and "var = expr"
3995 * "arg" points to "var".
3996 */
3997 static char_u *
3998compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3999{
4000 char_u *p;
4001 char_u *ret = NULL;
4002 int var_count = 0;
4003 int semicolon = 0;
4004 size_t varlen;
4005 garray_T *instr = &cctx->ctx_instr;
4006 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004007 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004008 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004009 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004010 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004011 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004012 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004013 int oplen = 0;
4014 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004015 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004016 lvar_T *lvar;
4017 char_u *name;
4018 char_u *sp;
4019 int has_type = FALSE;
4020 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4021 int instr_count = -1;
4022
4023 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4024 if (p == NULL)
4025 return NULL;
4026 if (var_count > 0)
4027 {
4028 // TODO: let [var, var] = list
4029 emsg("Cannot handle a list yet");
4030 return NULL;
4031 }
4032
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004033 // "a: type" is declaring variable "a" with a type, not "a:".
4034 if (is_decl && p == arg + 2 && p[-1] == ':')
4035 --p;
4036
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004037 varlen = p - arg;
4038 name = vim_strnsave(arg, (int)varlen);
4039 if (name == NULL)
4040 return NULL;
4041
Bram Moolenaar080457c2020-03-03 21:53:32 +01004042 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004043 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004044 if (*arg == '&')
4045 {
4046 int cc;
4047 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004048
Bram Moolenaar080457c2020-03-03 21:53:32 +01004049 dest = dest_option;
4050 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004051 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004052 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004053 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004054 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004055 if (is_decl)
4056 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004057 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004058 goto theend;
4059 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004060 p = arg;
4061 p = find_option_end(&p, &opt_flags);
4062 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004063 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004064 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004065 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004066 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004067 }
4068 cc = *p;
4069 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004070 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004071 *p = cc;
4072 if (opt_type == -3)
4073 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004074 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004075 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004076 }
4077 if (opt_type == -2 || opt_type == 0)
4078 type = &t_string;
4079 else
4080 type = &t_number; // both number and boolean option
4081 }
4082 else if (*arg == '$')
4083 {
4084 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004085 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004086 if (is_decl)
4087 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004088 semsg(_("E1065: Cannot declare an environment variable: %s"),
4089 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004090 goto theend;
4091 }
4092 }
4093 else if (*arg == '@')
4094 {
4095 if (!valid_yank_reg(arg[1], TRUE))
4096 {
4097 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004098 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004099 }
4100 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004101 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004102 if (is_decl)
4103 {
4104 semsg(_("E1066: Cannot declare a register: %s"), name);
4105 goto theend;
4106 }
4107 }
4108 else if (STRNCMP(arg, "g:", 2) == 0)
4109 {
4110 dest = dest_global;
4111 if (is_decl)
4112 {
4113 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4114 goto theend;
4115 }
4116 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004117 else if (STRNCMP(arg, "b:", 2) == 0)
4118 {
4119 dest = dest_buffer;
4120 if (is_decl)
4121 {
4122 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4123 goto theend;
4124 }
4125 }
4126 else if (STRNCMP(arg, "w:", 2) == 0)
4127 {
4128 dest = dest_window;
4129 if (is_decl)
4130 {
4131 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4132 goto theend;
4133 }
4134 }
4135 else if (STRNCMP(arg, "t:", 2) == 0)
4136 {
4137 dest = dest_tab;
4138 if (is_decl)
4139 {
4140 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4141 goto theend;
4142 }
4143 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004144 else if (STRNCMP(arg, "v:", 2) == 0)
4145 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004146 typval_T *vtv;
4147 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004148
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004149 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004150 if (vimvaridx < 0)
4151 {
4152 semsg(_(e_var_notfound), arg);
4153 goto theend;
4154 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004155 // We use the current value of "sandbox" here, is that OK?
4156 if (var_check_ro(di_flags, name, FALSE))
4157 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004158 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004159 vtv = get_vim_var_tv(vimvaridx);
4160 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004161 if (is_decl)
4162 {
4163 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4164 goto theend;
4165 }
4166 }
4167 else
4168 {
4169 for (idx = 0; reserved[idx] != NULL; ++idx)
4170 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004171 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004172 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004173 goto theend;
4174 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004175
4176 idx = lookup_local(arg, varlen, cctx);
4177 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004178 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004179 if (is_decl)
4180 {
4181 semsg(_("E1017: Variable already declared: %s"), name);
4182 goto theend;
4183 }
4184 else
4185 {
4186 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4187 if (lvar->lv_const)
4188 {
4189 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4190 goto theend;
4191 }
4192 }
4193 }
4194 else if (STRNCMP(arg, "s:", 2) == 0
4195 || lookup_script(arg, varlen) == OK
4196 || find_imported(arg, varlen, cctx) != NULL)
4197 {
4198 dest = dest_script;
4199 if (is_decl)
4200 {
4201 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004202 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004203 goto theend;
4204 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004205 }
4206 }
4207 }
4208
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004209 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004210 {
4211 if (is_decl && *p == ':')
4212 {
4213 // parse optional type: "let var: type = expr"
4214 p = skipwhite(p + 1);
4215 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004216 has_type = TRUE;
4217 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004218 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004219 {
4220 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4221 type = lvar->lv_type;
4222 }
4223 }
4224
4225 sp = p;
4226 p = skipwhite(p);
4227 op = p;
4228 oplen = assignment_len(p, &heredoc);
4229 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4230 {
4231 char_u buf[4];
4232
4233 vim_strncpy(buf, op, oplen);
4234 semsg(_(e_white_both), buf);
4235 }
4236
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004237 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004238 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004239 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004240 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004241 goto theend;
4242 }
4243
Bram Moolenaar080457c2020-03-03 21:53:32 +01004244 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004245 {
4246 if (oplen > 1 && !heredoc)
4247 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004248 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004249 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4250 name);
4251 goto theend;
4252 }
4253
4254 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004255 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004256 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004257 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4258 if (idx < 0)
4259 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004260 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004261 }
4262
4263 if (heredoc)
4264 {
4265 list_T *l;
4266 listitem_T *li;
4267
4268 // [let] varname =<< [trim] {end}
4269 eap->getline = heredoc_getline;
4270 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004271 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004272
4273 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004274 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004275 {
4276 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4277 li->li_tv.vval.v_string = NULL;
4278 }
4279 generate_NEWLIST(cctx, l->lv_len);
4280 type = &t_list_string;
4281 list_free(l);
4282 p += STRLEN(p);
4283 }
4284 else if (oplen > 0)
4285 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004286 int r;
4287 type_T *stacktype;
4288 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004289
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004290 // for "+=", "*=", "..=" etc. first load the current value
4291 if (*op != '=')
4292 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004293 switch (dest)
4294 {
4295 case dest_option:
4296 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004297 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004298 break;
4299 case dest_global:
4300 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4301 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004302 case dest_buffer:
4303 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4304 break;
4305 case dest_window:
4306 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4307 break;
4308 case dest_tab:
4309 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4310 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004311 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004312 compile_load_scriptvar(cctx,
4313 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004314 break;
4315 case dest_env:
4316 // Include $ in the name here
4317 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4318 break;
4319 case dest_reg:
4320 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4321 break;
4322 case dest_vimvar:
4323 generate_LOADV(cctx, name + 2, TRUE);
4324 break;
4325 case dest_local:
4326 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4327 break;
4328 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004329 }
4330
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004331 // Compile the expression. Temporarily hide the new local variable
4332 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004333 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004334 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004335 instr_count = instr->ga_len;
4336 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004337 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004338 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004339 ++cctx->ctx_locals.ga_len;
4340 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004341 goto theend;
4342
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004343 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004344 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004345 stack = &cctx->ctx_type_stack;
4346 stacktype = stack->ga_len == 0 ? &t_void
4347 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4348 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004349 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004350 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4351 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004352 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004353 if (stacktype->tt_type == VAR_VOID)
4354 {
4355 emsg(_("E1031: Cannot use void value"));
4356 goto theend;
4357 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004358 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004359 {
4360 // An empty list or dict has a &t_void member, for a
4361 // variable that implies &t_any.
4362 if (stacktype == &t_list_empty)
4363 lvar->lv_type = &t_list_any;
4364 else if (stacktype == &t_dict_empty)
4365 lvar->lv_type = &t_dict_any;
4366 else
4367 lvar->lv_type = stacktype;
4368 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004369 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004370 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4371 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004372 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004373 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004374 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004375 }
4376 }
4377 else if (cmdidx == CMD_const)
4378 {
4379 emsg(_("E1021: const requires a value"));
4380 goto theend;
4381 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004382 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004383 {
4384 emsg(_("E1022: type or initialization required"));
4385 goto theend;
4386 }
4387 else
4388 {
4389 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004390 if (ga_grow(instr, 1) == FAIL)
4391 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004392 switch (type->tt_type)
4393 {
4394 case VAR_BOOL:
4395 generate_PUSHBOOL(cctx, VVAL_FALSE);
4396 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004397 case VAR_FLOAT:
4398#ifdef FEAT_FLOAT
4399 generate_PUSHF(cctx, 0.0);
4400#endif
4401 break;
4402 case VAR_STRING:
4403 generate_PUSHS(cctx, NULL);
4404 break;
4405 case VAR_BLOB:
4406 generate_PUSHBLOB(cctx, NULL);
4407 break;
4408 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004409 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004410 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004411 case VAR_LIST:
4412 generate_NEWLIST(cctx, 0);
4413 break;
4414 case VAR_DICT:
4415 generate_NEWDICT(cctx, 0);
4416 break;
4417 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004418 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004419 break;
4420 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004421 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004422 break;
4423 case VAR_NUMBER:
4424 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004425 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004426 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004427 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004428 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004429 generate_PUSHNR(cctx, 0);
4430 break;
4431 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004432 }
4433
4434 if (oplen > 0 && *op != '=')
4435 {
4436 type_T *expected = &t_number;
4437 garray_T *stack = &cctx->ctx_type_stack;
4438 type_T *stacktype;
4439
4440 // TODO: if type is known use float or any operation
4441
4442 if (*op == '.')
4443 expected = &t_string;
4444 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4445 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4446 goto theend;
4447
4448 if (*op == '.')
4449 generate_instr_drop(cctx, ISN_CONCAT, 1);
4450 else
4451 {
4452 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4453
4454 if (isn == NULL)
4455 goto theend;
4456 switch (*op)
4457 {
4458 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4459 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4460 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4461 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4462 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4463 }
4464 }
4465 }
4466
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004467 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004468 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004469 case dest_option:
4470 generate_STOREOPT(cctx, name + 1, opt_flags);
4471 break;
4472 case dest_global:
4473 // include g: with the name, easier to execute that way
4474 generate_STORE(cctx, ISN_STOREG, 0, name);
4475 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004476 case dest_buffer:
4477 // include b: with the name, easier to execute that way
4478 generate_STORE(cctx, ISN_STOREB, 0, name);
4479 break;
4480 case dest_window:
4481 // include w: with the name, easier to execute that way
4482 generate_STORE(cctx, ISN_STOREW, 0, name);
4483 break;
4484 case dest_tab:
4485 // include t: with the name, easier to execute that way
4486 generate_STORE(cctx, ISN_STORET, 0, name);
4487 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004488 case dest_env:
4489 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4490 break;
4491 case dest_reg:
4492 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4493 break;
4494 case dest_vimvar:
4495 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4496 break;
4497 case dest_script:
4498 {
4499 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4500 imported_T *import = NULL;
4501 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004502
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004503 if (name[1] != ':')
4504 {
4505 import = find_imported(name, 0, cctx);
4506 if (import != NULL)
4507 sid = import->imp_sid;
4508 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004509
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004510 idx = get_script_item_idx(sid, rawname, TRUE);
4511 // TODO: specific type
4512 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004513 {
4514 char_u *name_s = name;
4515
4516 // Include s: in the name for store_var()
4517 if (name[1] != ':')
4518 {
4519 int len = (int)STRLEN(name) + 3;
4520
4521 name_s = alloc(len);
4522 if (name_s == NULL)
4523 name_s = name;
4524 else
4525 vim_snprintf((char *)name_s, len, "s:%s", name);
4526 }
4527 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4528 if (name_s != name)
4529 vim_free(name_s);
4530 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004531 else
4532 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4533 sid, idx, &t_any);
4534 }
4535 break;
4536 case dest_local:
4537 {
4538 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004539
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004540 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4541 // into ISN_STORENR
4542 if (instr->ga_len == instr_count + 1
4543 && isn->isn_type == ISN_PUSHNR)
4544 {
4545 varnumber_T val = isn->isn_arg.number;
4546 garray_T *stack = &cctx->ctx_type_stack;
4547
4548 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004549 isn->isn_arg.storenr.stnr_idx = idx;
4550 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004551 if (stack->ga_len > 0)
4552 --stack->ga_len;
4553 }
4554 else
4555 generate_STORE(cctx, ISN_STORE, idx, NULL);
4556 }
4557 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004558 }
4559 ret = p;
4560
4561theend:
4562 vim_free(name);
4563 return ret;
4564}
4565
4566/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004567 * Check if "name" can be "unlet".
4568 */
4569 int
4570check_vim9_unlet(char_u *name)
4571{
4572 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
4573 {
4574 semsg(_("E1081: Cannot unlet %s"), name);
4575 return FAIL;
4576 }
4577 return OK;
4578}
4579
4580/*
4581 * Callback passed to ex_unletlock().
4582 */
4583 static int
4584compile_unlet(
4585 lval_T *lvp,
4586 char_u *name_end,
4587 exarg_T *eap,
4588 int deep UNUSED,
4589 void *coookie)
4590{
4591 cctx_T *cctx = coookie;
4592
4593 if (lvp->ll_tv == NULL)
4594 {
4595 char_u *p = lvp->ll_name;
4596 int cc = *name_end;
4597 int ret = OK;
4598
4599 // Normal name. Only supports g:, w:, t: and b: namespaces.
4600 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004601 if (*p == '$')
4602 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
4603 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004604 ret = FAIL;
4605 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004606 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004607
4608 *name_end = cc;
4609 return ret;
4610 }
4611
4612 // TODO: unlet {list}[idx]
4613 // TODO: unlet {dict}[key]
4614 emsg("Sorry, :unlet not fully implemented yet");
4615 return FAIL;
4616}
4617
4618/*
4619 * compile "unlet var", "lock var" and "unlock var"
4620 * "arg" points to "var".
4621 */
4622 static char_u *
4623compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
4624{
4625 char_u *p = arg;
4626
4627 if (eap->cmdidx != CMD_unlet)
4628 {
4629 emsg("Sorry, :lock and unlock not implemented yet");
4630 return NULL;
4631 }
4632
4633 if (*p == '!')
4634 {
4635 p = skipwhite(p + 1);
4636 eap->forceit = TRUE;
4637 }
4638
4639 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
4640 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
4641}
4642
4643/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004644 * Compile an :import command.
4645 */
4646 static char_u *
4647compile_import(char_u *arg, cctx_T *cctx)
4648{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004649 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004650}
4651
4652/*
4653 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4654 */
4655 static int
4656compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4657{
4658 garray_T *instr = &cctx->ctx_instr;
4659 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4660
4661 if (endlabel == NULL)
4662 return FAIL;
4663 endlabel->el_next = *el;
4664 *el = endlabel;
4665 endlabel->el_end_label = instr->ga_len;
4666
4667 generate_JUMP(cctx, when, 0);
4668 return OK;
4669}
4670
4671 static void
4672compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4673{
4674 garray_T *instr = &cctx->ctx_instr;
4675
4676 while (*el != NULL)
4677 {
4678 endlabel_T *cur = (*el);
4679 isn_T *isn;
4680
4681 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4682 isn->isn_arg.jump.jump_where = instr->ga_len;
4683 *el = cur->el_next;
4684 vim_free(cur);
4685 }
4686}
4687
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004688 static void
4689compile_free_jump_to_end(endlabel_T **el)
4690{
4691 while (*el != NULL)
4692 {
4693 endlabel_T *cur = (*el);
4694
4695 *el = cur->el_next;
4696 vim_free(cur);
4697 }
4698}
4699
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004700/*
4701 * Create a new scope and set up the generic items.
4702 */
4703 static scope_T *
4704new_scope(cctx_T *cctx, scopetype_T type)
4705{
4706 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4707
4708 if (scope == NULL)
4709 return NULL;
4710 scope->se_outer = cctx->ctx_scope;
4711 cctx->ctx_scope = scope;
4712 scope->se_type = type;
4713 scope->se_local_count = cctx->ctx_locals.ga_len;
4714 return scope;
4715}
4716
4717/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004718 * Free the current scope and go back to the outer scope.
4719 */
4720 static void
4721drop_scope(cctx_T *cctx)
4722{
4723 scope_T *scope = cctx->ctx_scope;
4724
4725 if (scope == NULL)
4726 {
4727 iemsg("calling drop_scope() without a scope");
4728 return;
4729 }
4730 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004731 switch (scope->se_type)
4732 {
4733 case IF_SCOPE:
4734 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4735 case FOR_SCOPE:
4736 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4737 case WHILE_SCOPE:
4738 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4739 case TRY_SCOPE:
4740 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4741 case NO_SCOPE:
4742 case BLOCK_SCOPE:
4743 break;
4744 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004745 vim_free(scope);
4746}
4747
4748/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004749 * Evaluate an expression that is a constant:
4750 * has(arg)
4751 *
4752 * Also handle:
4753 * ! in front logical NOT
4754 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004755 * Return FAIL if the expression is not a constant.
4756 */
4757 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004758evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004759{
4760 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004761 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004762 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004763
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004764 /*
4765 * Skip '!' characters. They are handled later.
4766 */
4767 start_leader = *arg;
4768 while (**arg == '!')
4769 *arg = skipwhite(*arg + 1);
4770 end_leader = *arg;
4771
4772 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004773 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004774 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004775 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4776 {
4777 tv->v_type = VAR_SPECIAL;
4778 tv->vval.v_number = VVAL_TRUE;
4779 *arg += 4;
4780 return OK;
4781 }
4782 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4783 {
4784 tv->v_type = VAR_SPECIAL;
4785 tv->vval.v_number = VVAL_FALSE;
4786 *arg += 5;
4787 return OK;
4788 }
4789
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004790 if (STRNCMP("has(", *arg, 4) == 0)
4791 {
4792 has_call = TRUE;
4793 *arg = skipwhite(*arg + 4);
4794 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004795
4796 if (**arg == '"')
4797 {
4798 if (get_string_tv(arg, tv, TRUE) == FAIL)
4799 return FAIL;
4800 }
4801 else if (**arg == '\'')
4802 {
4803 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4804 return FAIL;
4805 }
4806 else
4807 return FAIL;
4808
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004809 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004810 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004811 *arg = skipwhite(*arg);
4812 if (**arg != ')')
4813 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004814 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004815
4816 argvars[0] = *tv;
4817 argvars[1].v_type = VAR_UNKNOWN;
4818 tv->v_type = VAR_NUMBER;
4819 tv->vval.v_number = 0;
4820 f_has(argvars, tv);
4821 clear_tv(&argvars[0]);
4822
4823 while (start_leader < end_leader)
4824 {
4825 if (*start_leader == '!')
4826 tv->vval.v_number = !tv->vval.v_number;
4827 ++start_leader;
4828 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004829 }
4830
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004831 return OK;
4832}
4833
Bram Moolenaar080457c2020-03-03 21:53:32 +01004834 static int
4835evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4836{
4837 exptype_T type = EXPR_UNKNOWN;
4838 char_u *p;
4839 int len = 2;
4840 int type_is = FALSE;
4841
4842 // get the first variable
4843 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4844 return FAIL;
4845
4846 p = skipwhite(*arg);
4847 type = get_compare_type(p, &len, &type_is);
4848
4849 /*
4850 * If there is a comparative operator, use it.
4851 */
4852 if (type != EXPR_UNKNOWN)
4853 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004854 typval_T tv2;
4855 char_u *s1, *s2;
4856 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4857 int n;
4858
4859 // TODO: Only string == string is supported now
4860 if (tv->v_type != VAR_STRING)
4861 return FAIL;
4862 if (type != EXPR_EQUAL)
4863 return FAIL;
4864
4865 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004866 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004867 *arg = skipwhite(p + len);
4868 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4869 || tv2.v_type != VAR_STRING)
4870 {
4871 clear_tv(&tv2);
4872 return FAIL;
4873 }
4874 s1 = tv_get_string_buf(tv, buf1);
4875 s2 = tv_get_string_buf(&tv2, buf2);
4876 n = STRCMP(s1, s2);
4877 clear_tv(tv);
4878 clear_tv(&tv2);
4879 tv->v_type = VAR_BOOL;
4880 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004881 }
4882
4883 return OK;
4884}
4885
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004886static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4887
4888/*
4889 * Compile constant || or &&.
4890 */
4891 static int
4892evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4893{
4894 char_u *p = skipwhite(*arg);
4895 int opchar = *op;
4896
4897 if (p[0] == opchar && p[1] == opchar)
4898 {
4899 int val = tv2bool(tv);
4900
4901 /*
4902 * Repeat until there is no following "||" or "&&"
4903 */
4904 while (p[0] == opchar && p[1] == opchar)
4905 {
4906 typval_T tv2;
4907
4908 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4909 return FAIL;
4910
4911 // eval the next expression
4912 *arg = skipwhite(p + 2);
4913 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004914 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004915 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004916 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004917 {
4918 clear_tv(&tv2);
4919 return FAIL;
4920 }
4921 if ((opchar == '&') == val)
4922 {
4923 // false || tv2 or true && tv2: use tv2
4924 clear_tv(tv);
4925 *tv = tv2;
4926 val = tv2bool(tv);
4927 }
4928 else
4929 clear_tv(&tv2);
4930 p = skipwhite(*arg);
4931 }
4932 }
4933
4934 return OK;
4935}
4936
4937/*
4938 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4939 * Return FAIL if the expression is not a constant.
4940 */
4941 static int
4942evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4943{
4944 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004945 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004946 return FAIL;
4947
4948 // || and && work almost the same
4949 return evaluate_const_and_or(arg, cctx, "&&", tv);
4950}
4951
4952/*
4953 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4954 * Return FAIL if the expression is not a constant.
4955 */
4956 static int
4957evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4958{
4959 // evaluate the first expression
4960 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4961 return FAIL;
4962
4963 // || and && work almost the same
4964 return evaluate_const_and_or(arg, cctx, "||", tv);
4965}
4966
4967/*
4968 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4969 * E.g. for "has('feature')".
4970 * This does not produce error messages. "tv" should be cleared afterwards.
4971 * Return FAIL if the expression is not a constant.
4972 */
4973 static int
4974evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4975{
4976 char_u *p;
4977
4978 // evaluate the first expression
4979 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4980 return FAIL;
4981
4982 p = skipwhite(*arg);
4983 if (*p == '?')
4984 {
4985 int val = tv2bool(tv);
4986 typval_T tv2;
4987
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004988 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004989 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4990 return FAIL;
4991
4992 // evaluate the second expression; any type is accepted
4993 clear_tv(tv);
4994 *arg = skipwhite(p + 1);
4995 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
4996 return FAIL;
4997
4998 // Check for the ":".
4999 p = skipwhite(*arg);
5000 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5001 return FAIL;
5002
5003 // evaluate the third expression
5004 *arg = skipwhite(p + 1);
5005 tv2.v_type = VAR_UNKNOWN;
5006 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
5007 {
5008 clear_tv(&tv2);
5009 return FAIL;
5010 }
5011 if (val)
5012 {
5013 // use the expr after "?"
5014 clear_tv(&tv2);
5015 }
5016 else
5017 {
5018 // use the expr after ":"
5019 clear_tv(tv);
5020 *tv = tv2;
5021 }
5022 }
5023 return OK;
5024}
5025
5026/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005027 * compile "if expr"
5028 *
5029 * "if expr" Produces instructions:
5030 * EVAL expr Push result of "expr"
5031 * JUMP_IF_FALSE end
5032 * ... body ...
5033 * end:
5034 *
5035 * "if expr | else" Produces instructions:
5036 * EVAL expr Push result of "expr"
5037 * JUMP_IF_FALSE else
5038 * ... body ...
5039 * JUMP_ALWAYS end
5040 * else:
5041 * ... body ...
5042 * end:
5043 *
5044 * "if expr1 | elseif expr2 | else" Produces instructions:
5045 * EVAL expr Push result of "expr"
5046 * JUMP_IF_FALSE elseif
5047 * ... body ...
5048 * JUMP_ALWAYS end
5049 * elseif:
5050 * EVAL expr Push result of "expr"
5051 * JUMP_IF_FALSE else
5052 * ... body ...
5053 * JUMP_ALWAYS end
5054 * else:
5055 * ... body ...
5056 * end:
5057 */
5058 static char_u *
5059compile_if(char_u *arg, cctx_T *cctx)
5060{
5061 char_u *p = arg;
5062 garray_T *instr = &cctx->ctx_instr;
5063 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005064 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005065
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005066 // compile "expr"; if we know it evaluates to FALSE skip the block
5067 tv.v_type = VAR_UNKNOWN;
5068 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5069 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5070 else
5071 cctx->ctx_skip = MAYBE;
5072 clear_tv(&tv);
5073 if (cctx->ctx_skip == MAYBE)
5074 {
5075 p = arg;
5076 if (compile_expr1(&p, cctx) == FAIL)
5077 return NULL;
5078 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005079
5080 scope = new_scope(cctx, IF_SCOPE);
5081 if (scope == NULL)
5082 return NULL;
5083
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005084 if (cctx->ctx_skip == MAYBE)
5085 {
5086 // "where" is set when ":elseif", "else" or ":endif" is found
5087 scope->se_u.se_if.is_if_label = instr->ga_len;
5088 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5089 }
5090 else
5091 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005092
5093 return p;
5094}
5095
5096 static char_u *
5097compile_elseif(char_u *arg, cctx_T *cctx)
5098{
5099 char_u *p = arg;
5100 garray_T *instr = &cctx->ctx_instr;
5101 isn_T *isn;
5102 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005103 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005104
5105 if (scope == NULL || scope->se_type != IF_SCOPE)
5106 {
5107 emsg(_(e_elseif_without_if));
5108 return NULL;
5109 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005110 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005111
Bram Moolenaar158906c2020-02-06 20:39:45 +01005112 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005113 {
5114 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005115 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005116 return NULL;
5117 // previous "if" or "elseif" jumps here
5118 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5119 isn->isn_arg.jump.jump_where = instr->ga_len;
5120 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005121
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005122 // compile "expr"; if we know it evaluates to FALSE skip the block
5123 tv.v_type = VAR_UNKNOWN;
5124 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5125 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5126 else
5127 cctx->ctx_skip = MAYBE;
5128 clear_tv(&tv);
5129 if (cctx->ctx_skip == MAYBE)
5130 {
5131 p = arg;
5132 if (compile_expr1(&p, cctx) == FAIL)
5133 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005134
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005135 // "where" is set when ":elseif", "else" or ":endif" is found
5136 scope->se_u.se_if.is_if_label = instr->ga_len;
5137 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5138 }
5139 else
5140 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005141
5142 return p;
5143}
5144
5145 static char_u *
5146compile_else(char_u *arg, cctx_T *cctx)
5147{
5148 char_u *p = arg;
5149 garray_T *instr = &cctx->ctx_instr;
5150 isn_T *isn;
5151 scope_T *scope = cctx->ctx_scope;
5152
5153 if (scope == NULL || scope->se_type != IF_SCOPE)
5154 {
5155 emsg(_(e_else_without_if));
5156 return NULL;
5157 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005158 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005159
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005160 // jump from previous block to the end, unless the else block is empty
5161 if (cctx->ctx_skip == MAYBE)
5162 {
5163 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005164 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005165 return NULL;
5166 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005167
Bram Moolenaar158906c2020-02-06 20:39:45 +01005168 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005169 {
5170 if (scope->se_u.se_if.is_if_label >= 0)
5171 {
5172 // previous "if" or "elseif" jumps here
5173 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5174 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005175 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005176 }
5177 }
5178
5179 if (cctx->ctx_skip != MAYBE)
5180 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005181
5182 return p;
5183}
5184
5185 static char_u *
5186compile_endif(char_u *arg, cctx_T *cctx)
5187{
5188 scope_T *scope = cctx->ctx_scope;
5189 ifscope_T *ifscope;
5190 garray_T *instr = &cctx->ctx_instr;
5191 isn_T *isn;
5192
5193 if (scope == NULL || scope->se_type != IF_SCOPE)
5194 {
5195 emsg(_(e_endif_without_if));
5196 return NULL;
5197 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005198 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005199 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005200
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005201 if (scope->se_u.se_if.is_if_label >= 0)
5202 {
5203 // previous "if" or "elseif" jumps here
5204 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5205 isn->isn_arg.jump.jump_where = instr->ga_len;
5206 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005207 // Fill in the "end" label in jumps at the end of the blocks.
5208 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005209 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005210
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005211 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005212 return arg;
5213}
5214
5215/*
5216 * compile "for var in expr"
5217 *
5218 * Produces instructions:
5219 * PUSHNR -1
5220 * STORE loop-idx Set index to -1
5221 * EVAL expr Push result of "expr"
5222 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5223 * - if beyond end, jump to "end"
5224 * - otherwise get item from list and push it
5225 * STORE var Store item in "var"
5226 * ... body ...
5227 * JUMP top Jump back to repeat
5228 * end: DROP Drop the result of "expr"
5229 *
5230 */
5231 static char_u *
5232compile_for(char_u *arg, cctx_T *cctx)
5233{
5234 char_u *p;
5235 size_t varlen;
5236 garray_T *instr = &cctx->ctx_instr;
5237 garray_T *stack = &cctx->ctx_type_stack;
5238 scope_T *scope;
5239 int loop_idx; // index of loop iteration variable
5240 int var_idx; // index of "var"
5241 type_T *vartype;
5242
5243 // TODO: list of variables: "for [key, value] in dict"
5244 // parse "var"
5245 for (p = arg; eval_isnamec1(*p); ++p)
5246 ;
5247 varlen = p - arg;
5248 var_idx = lookup_local(arg, varlen, cctx);
5249 if (var_idx >= 0)
5250 {
5251 semsg(_("E1023: variable already defined: %s"), arg);
5252 return NULL;
5253 }
5254
5255 // consume "in"
5256 p = skipwhite(p);
5257 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5258 {
5259 emsg(_(e_missing_in));
5260 return NULL;
5261 }
5262 p = skipwhite(p + 2);
5263
5264
5265 scope = new_scope(cctx, FOR_SCOPE);
5266 if (scope == NULL)
5267 return NULL;
5268
5269 // Reserve a variable to store the loop iteration counter.
5270 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5271 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005272 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005273 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005274 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005275 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005276 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005277
5278 // Reserve a variable to store "var"
5279 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5280 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005281 {
5282 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005283 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005284 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005285
5286 generate_STORENR(cctx, loop_idx, -1);
5287
5288 // compile "expr", it remains on the stack until "endfor"
5289 arg = p;
5290 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005291 {
5292 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005293 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005294 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005295
5296 // now we know the type of "var"
5297 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5298 if (vartype->tt_type != VAR_LIST)
5299 {
5300 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005301 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005302 return NULL;
5303 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005304 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005305 {
5306 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
5307
5308 lvar->lv_type = vartype->tt_member;
5309 }
5310
5311 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005312 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005313
5314 generate_FOR(cctx, loop_idx);
5315 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
5316
5317 return arg;
5318}
5319
5320/*
5321 * compile "endfor"
5322 */
5323 static char_u *
5324compile_endfor(char_u *arg, cctx_T *cctx)
5325{
5326 garray_T *instr = &cctx->ctx_instr;
5327 scope_T *scope = cctx->ctx_scope;
5328 forscope_T *forscope;
5329 isn_T *isn;
5330
5331 if (scope == NULL || scope->se_type != FOR_SCOPE)
5332 {
5333 emsg(_(e_for));
5334 return NULL;
5335 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005336 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005337 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005338 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005339
5340 // At end of ":for" scope jump back to the FOR instruction.
5341 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5342
5343 // Fill in the "end" label in the FOR statement so it can jump here
5344 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5345 isn->isn_arg.forloop.for_end = instr->ga_len;
5346
5347 // Fill in the "end" label any BREAK statements
5348 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5349
5350 // Below the ":for" scope drop the "expr" list from the stack.
5351 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5352 return NULL;
5353
5354 vim_free(scope);
5355
5356 return arg;
5357}
5358
5359/*
5360 * compile "while expr"
5361 *
5362 * Produces instructions:
5363 * top: EVAL expr Push result of "expr"
5364 * JUMP_IF_FALSE end jump if false
5365 * ... body ...
5366 * JUMP top Jump back to repeat
5367 * end:
5368 *
5369 */
5370 static char_u *
5371compile_while(char_u *arg, cctx_T *cctx)
5372{
5373 char_u *p = arg;
5374 garray_T *instr = &cctx->ctx_instr;
5375 scope_T *scope;
5376
5377 scope = new_scope(cctx, WHILE_SCOPE);
5378 if (scope == NULL)
5379 return NULL;
5380
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005381 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005382
5383 // compile "expr"
5384 if (compile_expr1(&p, cctx) == FAIL)
5385 return NULL;
5386
5387 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005388 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005389 JUMP_IF_FALSE, cctx) == FAIL)
5390 return FAIL;
5391
5392 return p;
5393}
5394
5395/*
5396 * compile "endwhile"
5397 */
5398 static char_u *
5399compile_endwhile(char_u *arg, cctx_T *cctx)
5400{
5401 scope_T *scope = cctx->ctx_scope;
5402
5403 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5404 {
5405 emsg(_(e_while));
5406 return NULL;
5407 }
5408 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005409 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005410
5411 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005412 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005413
5414 // Fill in the "end" label in the WHILE statement so it can jump here.
5415 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005416 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005417
5418 vim_free(scope);
5419
5420 return arg;
5421}
5422
5423/*
5424 * compile "continue"
5425 */
5426 static char_u *
5427compile_continue(char_u *arg, cctx_T *cctx)
5428{
5429 scope_T *scope = cctx->ctx_scope;
5430
5431 for (;;)
5432 {
5433 if (scope == NULL)
5434 {
5435 emsg(_(e_continue));
5436 return NULL;
5437 }
5438 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5439 break;
5440 scope = scope->se_outer;
5441 }
5442
5443 // Jump back to the FOR or WHILE instruction.
5444 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005445 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5446 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005447 return arg;
5448}
5449
5450/*
5451 * compile "break"
5452 */
5453 static char_u *
5454compile_break(char_u *arg, cctx_T *cctx)
5455{
5456 scope_T *scope = cctx->ctx_scope;
5457 endlabel_T **el;
5458
5459 for (;;)
5460 {
5461 if (scope == NULL)
5462 {
5463 emsg(_(e_break));
5464 return NULL;
5465 }
5466 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5467 break;
5468 scope = scope->se_outer;
5469 }
5470
5471 // Jump to the end of the FOR or WHILE loop.
5472 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005473 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005474 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005475 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005476 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5477 return FAIL;
5478
5479 return arg;
5480}
5481
5482/*
5483 * compile "{" start of block
5484 */
5485 static char_u *
5486compile_block(char_u *arg, cctx_T *cctx)
5487{
5488 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5489 return NULL;
5490 return skipwhite(arg + 1);
5491}
5492
5493/*
5494 * compile end of block: drop one scope
5495 */
5496 static void
5497compile_endblock(cctx_T *cctx)
5498{
5499 scope_T *scope = cctx->ctx_scope;
5500
5501 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005502 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005503 vim_free(scope);
5504}
5505
5506/*
5507 * compile "try"
5508 * Creates a new scope for the try-endtry, pointing to the first catch and
5509 * finally.
5510 * Creates another scope for the "try" block itself.
5511 * TRY instruction sets up exception handling at runtime.
5512 *
5513 * "try"
5514 * TRY -> catch1, -> finally push trystack entry
5515 * ... try block
5516 * "throw {exception}"
5517 * EVAL {exception}
5518 * THROW create exception
5519 * ... try block
5520 * " catch {expr}"
5521 * JUMP -> finally
5522 * catch1: PUSH exeception
5523 * EVAL {expr}
5524 * MATCH
5525 * JUMP nomatch -> catch2
5526 * CATCH remove exception
5527 * ... catch block
5528 * " catch"
5529 * JUMP -> finally
5530 * catch2: CATCH remove exception
5531 * ... catch block
5532 * " finally"
5533 * finally:
5534 * ... finally block
5535 * " endtry"
5536 * ENDTRY pop trystack entry, may rethrow
5537 */
5538 static char_u *
5539compile_try(char_u *arg, cctx_T *cctx)
5540{
5541 garray_T *instr = &cctx->ctx_instr;
5542 scope_T *try_scope;
5543 scope_T *scope;
5544
5545 // scope that holds the jumps that go to catch/finally/endtry
5546 try_scope = new_scope(cctx, TRY_SCOPE);
5547 if (try_scope == NULL)
5548 return NULL;
5549
5550 // "catch" is set when the first ":catch" is found.
5551 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005552 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005553 if (generate_instr(cctx, ISN_TRY) == NULL)
5554 return NULL;
5555
5556 // scope for the try block itself
5557 scope = new_scope(cctx, BLOCK_SCOPE);
5558 if (scope == NULL)
5559 return NULL;
5560
5561 return arg;
5562}
5563
5564/*
5565 * compile "catch {expr}"
5566 */
5567 static char_u *
5568compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5569{
5570 scope_T *scope = cctx->ctx_scope;
5571 garray_T *instr = &cctx->ctx_instr;
5572 char_u *p;
5573 isn_T *isn;
5574
5575 // end block scope from :try or :catch
5576 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5577 compile_endblock(cctx);
5578 scope = cctx->ctx_scope;
5579
5580 // Error if not in a :try scope
5581 if (scope == NULL || scope->se_type != TRY_SCOPE)
5582 {
5583 emsg(_(e_catch));
5584 return NULL;
5585 }
5586
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005587 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005588 {
5589 emsg(_("E1033: catch unreachable after catch-all"));
5590 return NULL;
5591 }
5592
5593 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005594 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005595 JUMP_ALWAYS, cctx) == FAIL)
5596 return NULL;
5597
5598 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005599 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005600 if (isn->isn_arg.try.try_catch == 0)
5601 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005602 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005603 {
5604 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005605 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005606 isn->isn_arg.jump.jump_where = instr->ga_len;
5607 }
5608
5609 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005610 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005611 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005612 scope->se_u.se_try.ts_caught_all = TRUE;
5613 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005614 }
5615 else
5616 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005617 char_u *end;
5618 char_u *pat;
5619 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005620 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005621 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005622
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005623 // Push v:exception, push {expr} and MATCH
5624 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5625
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005626 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005627 if (*end != *p)
5628 {
5629 semsg(_("E1067: Separator mismatch: %s"), p);
5630 vim_free(tofree);
5631 return FAIL;
5632 }
5633 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005634 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005635 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005636 len = (int)(end - tofree);
5637 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005638 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005639 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005640 if (pat == NULL)
5641 return FAIL;
5642 if (generate_PUSHS(cctx, pat) == FAIL)
5643 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005644
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005645 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5646 return NULL;
5647
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005648 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005649 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5650 return NULL;
5651 }
5652
5653 if (generate_instr(cctx, ISN_CATCH) == NULL)
5654 return NULL;
5655
5656 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5657 return NULL;
5658 return p;
5659}
5660
5661 static char_u *
5662compile_finally(char_u *arg, cctx_T *cctx)
5663{
5664 scope_T *scope = cctx->ctx_scope;
5665 garray_T *instr = &cctx->ctx_instr;
5666 isn_T *isn;
5667
5668 // end block scope from :try or :catch
5669 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5670 compile_endblock(cctx);
5671 scope = cctx->ctx_scope;
5672
5673 // Error if not in a :try scope
5674 if (scope == NULL || scope->se_type != TRY_SCOPE)
5675 {
5676 emsg(_(e_finally));
5677 return NULL;
5678 }
5679
5680 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005681 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005682 if (isn->isn_arg.try.try_finally != 0)
5683 {
5684 emsg(_(e_finally_dup));
5685 return NULL;
5686 }
5687
5688 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005689 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005690
Bram Moolenaar585fea72020-04-02 22:33:21 +02005691 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005692 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005693 {
5694 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005695 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005696 isn->isn_arg.jump.jump_where = instr->ga_len;
5697 }
5698
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005699 // TODO: set index in ts_finally_label jumps
5700
5701 return arg;
5702}
5703
5704 static char_u *
5705compile_endtry(char_u *arg, cctx_T *cctx)
5706{
5707 scope_T *scope = cctx->ctx_scope;
5708 garray_T *instr = &cctx->ctx_instr;
5709 isn_T *isn;
5710
5711 // end block scope from :catch or :finally
5712 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5713 compile_endblock(cctx);
5714 scope = cctx->ctx_scope;
5715
5716 // Error if not in a :try scope
5717 if (scope == NULL || scope->se_type != TRY_SCOPE)
5718 {
5719 if (scope == NULL)
5720 emsg(_(e_no_endtry));
5721 else if (scope->se_type == WHILE_SCOPE)
5722 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005723 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005724 emsg(_(e_endfor));
5725 else
5726 emsg(_(e_endif));
5727 return NULL;
5728 }
5729
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005730 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005731 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5732 {
5733 emsg(_("E1032: missing :catch or :finally"));
5734 return NULL;
5735 }
5736
5737 // Fill in the "end" label in jumps at the end of the blocks, if not done
5738 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005739 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005740
5741 // End :catch or :finally scope: set value in ISN_TRY instruction
5742 if (isn->isn_arg.try.try_finally == 0)
5743 isn->isn_arg.try.try_finally = instr->ga_len;
5744 compile_endblock(cctx);
5745
5746 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5747 return NULL;
5748 return arg;
5749}
5750
5751/*
5752 * compile "throw {expr}"
5753 */
5754 static char_u *
5755compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5756{
5757 char_u *p = skipwhite(arg);
5758
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005759 if (compile_expr1(&p, cctx) == FAIL)
5760 return NULL;
5761 if (may_generate_2STRING(-1, cctx) == FAIL)
5762 return NULL;
5763 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5764 return NULL;
5765
5766 return p;
5767}
5768
5769/*
5770 * compile "echo expr"
5771 */
5772 static char_u *
5773compile_echo(char_u *arg, int with_white, cctx_T *cctx)
5774{
5775 char_u *p = arg;
5776 int count = 0;
5777
Bram Moolenaarad39c092020-02-26 18:23:43 +01005778 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005779 {
5780 if (compile_expr1(&p, cctx) == FAIL)
5781 return NULL;
5782 ++count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005783 p = skipwhite(p);
5784 if (ends_excmd(*p))
5785 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005786 }
5787
5788 generate_ECHO(cctx, with_white, count);
Bram Moolenaarad39c092020-02-26 18:23:43 +01005789 return p;
5790}
5791
5792/*
5793 * compile "execute expr"
5794 */
5795 static char_u *
5796compile_execute(char_u *arg, cctx_T *cctx)
5797{
5798 char_u *p = arg;
5799 int count = 0;
5800
5801 for (;;)
5802 {
5803 if (compile_expr1(&p, cctx) == FAIL)
5804 return NULL;
5805 ++count;
5806 p = skipwhite(p);
5807 if (ends_excmd(*p))
5808 break;
5809 }
5810
5811 generate_EXECUTE(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005812
5813 return p;
5814}
5815
5816/*
5817 * After ex_function() has collected all the function lines: parse and compile
5818 * the lines into instructions.
5819 * Adds the function to "def_functions".
5820 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5821 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005822 * This can be used recursively through compile_lambda(), which may reallocate
5823 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005824 */
5825 void
5826compile_def_function(ufunc_T *ufunc, int set_return_type)
5827{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005828 char_u *line = NULL;
5829 char_u *p;
5830 exarg_T ea;
5831 char *errormsg = NULL; // error message
5832 int had_return = FALSE;
5833 cctx_T cctx;
5834 garray_T *instr;
5835 int called_emsg_before = called_emsg;
5836 int ret = FAIL;
5837 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005838 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005839
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005840 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005841 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005842
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005843 if (ufunc->uf_dfunc_idx >= 0)
5844 {
5845 // Redefining a function that was compiled before.
5846 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5847
5848 // Free old instructions.
5849 delete_def_function_contents(dfunc);
5850 }
5851 else
5852 {
5853 // Add the function to "def_functions".
5854 if (ga_grow(&def_functions, 1) == FAIL)
5855 return;
5856 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005857 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005858 dfunc->df_idx = def_functions.ga_len;
5859 ufunc->uf_dfunc_idx = dfunc->df_idx;
5860 dfunc->df_ufunc = ufunc;
5861 ++def_functions.ga_len;
5862 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005863 }
5864
Bram Moolenaara80faa82020-04-12 19:37:17 +02005865 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005866 cctx.ctx_ufunc = ufunc;
5867 cctx.ctx_lnum = -1;
5868 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5869 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5870 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5871 cctx.ctx_type_list = &ufunc->uf_type_list;
5872 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5873 instr = &cctx.ctx_instr;
5874
5875 // Most modern script version.
5876 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5877
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005878 if (ufunc->uf_def_args.ga_len > 0)
5879 {
5880 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005881 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005882 int i;
5883 char_u *arg;
5884 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5885
5886 // Produce instructions for the default values of optional arguments.
5887 // Store the instruction index in uf_def_arg_idx[] so that we know
5888 // where to start when the function is called, depending on the number
5889 // of arguments.
5890 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5891 if (ufunc->uf_def_arg_idx == NULL)
5892 goto erret;
5893 for (i = 0; i < count; ++i)
5894 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005895 garray_T *stack = &cctx.ctx_type_stack;
5896 type_T *val_type;
5897 int arg_idx = first_def_arg + i;
5898
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005899 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5900 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005901 if (compile_expr1(&arg, &cctx) == FAIL)
5902 goto erret;
5903
5904 // If no type specified use the type of the default value.
5905 // Otherwise check that the default value type matches the
5906 // specified type.
5907 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5908 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
5909 ufunc->uf_arg_types[arg_idx] = val_type;
5910 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
5911 == FAIL)
5912 {
5913 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
5914 arg_idx + 1);
5915 goto erret;
5916 }
5917
5918 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005919 goto erret;
5920 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005921 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5922 }
5923
5924 /*
5925 * Loop over all the lines of the function and generate instructions.
5926 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005927 for (;;)
5928 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005929 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005930
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005931 // Bail out on the first error to avoid a flood of errors and report
5932 // the right line number when inside try/catch.
5933 if (emsg_before != called_emsg)
5934 goto erret;
5935
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005936 if (line != NULL && *line == '|')
5937 // the line continues after a '|'
5938 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02005939 else if (line != NULL && *line != NUL
5940 && !(*line == '#' && (line == cctx.ctx_line_start
5941 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005942 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005943 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005944 goto erret;
5945 }
5946 else
5947 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02005948 line = next_line_from_context(&cctx);
5949 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005950 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005951 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005952 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005953 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005954
5955 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005956 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005957 ea.cmdlinep = &line;
5958 ea.cmd = skipwhite(line);
5959
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005960 // Some things can be recognized by the first character.
5961 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005962 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005963 case '#':
5964 // "#" starts a comment, but not "#{".
5965 if (ea.cmd[1] != '{')
5966 {
5967 line = (char_u *)"";
5968 continue;
5969 }
5970 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005971
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005972 case '}':
5973 {
5974 // "}" ends a block scope
5975 scopetype_T stype = cctx.ctx_scope == NULL
5976 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005977
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005978 if (stype == BLOCK_SCOPE)
5979 {
5980 compile_endblock(&cctx);
5981 line = ea.cmd;
5982 }
5983 else
5984 {
5985 emsg(_("E1025: using } outside of a block scope"));
5986 goto erret;
5987 }
5988 if (line != NULL)
5989 line = skipwhite(ea.cmd + 1);
5990 continue;
5991 }
5992
5993 case '{':
5994 // "{" starts a block scope
5995 // "{'a': 1}->func() is something else
5996 if (ends_excmd(*skipwhite(ea.cmd + 1)))
5997 {
5998 line = compile_block(ea.cmd, &cctx);
5999 continue;
6000 }
6001 break;
6002
6003 case ':':
6004 is_ex_command = TRUE;
6005 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006006 }
6007
6008 /*
6009 * COMMAND MODIFIERS
6010 */
6011 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6012 {
6013 if (errormsg != NULL)
6014 goto erret;
6015 // empty line or comment
6016 line = (char_u *)"";
6017 continue;
6018 }
6019
6020 // Skip ":call" to get to the function name.
6021 if (checkforcmd(&ea.cmd, "call", 3))
6022 ea.cmd = skipwhite(ea.cmd);
6023
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006024 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006025 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006026 // Assuming the command starts with a variable or function name,
6027 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6028 // val".
6029 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6030 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006031 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006032 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006033 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006034 int oplen;
6035 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006036
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006037 oplen = assignment_len(skipwhite(p), &heredoc);
6038 if (oplen > 0)
6039 {
6040 // Recognize an assignment if we recognize the variable
6041 // name:
6042 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006043 // "local = expr" where "local" is a local var.
6044 // "script = expr" where "script" is a script-local var.
6045 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006046 // "&opt = expr"
6047 // "$ENV = expr"
6048 // "@r = expr"
6049 if (*ea.cmd == '&'
6050 || *ea.cmd == '$'
6051 || *ea.cmd == '@'
6052 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
6053 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
6054 || lookup_script(ea.cmd, p - ea.cmd) == OK
6055 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6056 {
6057 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6058 if (line == NULL)
6059 goto erret;
6060 continue;
6061 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006062 }
6063 }
6064 }
6065
6066 /*
6067 * COMMAND after range
6068 */
6069 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006070 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
6071 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006072
6073 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6074 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006075 if (cctx.ctx_skip == TRUE)
6076 {
6077 line += STRLEN(line);
6078 continue;
6079 }
6080
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006081 // Expression or function call.
6082 if (ea.cmdidx == CMD_eval)
6083 {
6084 p = ea.cmd;
6085 if (compile_expr1(&p, &cctx) == FAIL)
6086 goto erret;
6087
6088 // drop the return value
6089 generate_instr_drop(&cctx, ISN_DROP, 1);
6090 line = p;
6091 continue;
6092 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006093 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006094 iemsg("Command from find_ex_command() not handled");
6095 goto erret;
6096 }
6097
6098 p = skipwhite(p);
6099
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006100 if (cctx.ctx_skip == TRUE
6101 && ea.cmdidx != CMD_elseif
6102 && ea.cmdidx != CMD_else
6103 && ea.cmdidx != CMD_endif)
6104 {
6105 line += STRLEN(line);
6106 continue;
6107 }
6108
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006109 switch (ea.cmdidx)
6110 {
6111 case CMD_def:
6112 case CMD_function:
6113 // TODO: Nested function
6114 emsg("Nested function not implemented yet");
6115 goto erret;
6116
6117 case CMD_return:
6118 line = compile_return(p, set_return_type, &cctx);
6119 had_return = TRUE;
6120 break;
6121
6122 case CMD_let:
6123 case CMD_const:
6124 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6125 break;
6126
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006127 case CMD_unlet:
6128 case CMD_unlockvar:
6129 case CMD_lockvar:
6130 line = compile_unletlock(p, &ea, &cctx);
6131 break;
6132
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006133 case CMD_import:
6134 line = compile_import(p, &cctx);
6135 break;
6136
6137 case CMD_if:
6138 line = compile_if(p, &cctx);
6139 break;
6140 case CMD_elseif:
6141 line = compile_elseif(p, &cctx);
6142 break;
6143 case CMD_else:
6144 line = compile_else(p, &cctx);
6145 break;
6146 case CMD_endif:
6147 line = compile_endif(p, &cctx);
6148 break;
6149
6150 case CMD_while:
6151 line = compile_while(p, &cctx);
6152 break;
6153 case CMD_endwhile:
6154 line = compile_endwhile(p, &cctx);
6155 break;
6156
6157 case CMD_for:
6158 line = compile_for(p, &cctx);
6159 break;
6160 case CMD_endfor:
6161 line = compile_endfor(p, &cctx);
6162 break;
6163 case CMD_continue:
6164 line = compile_continue(p, &cctx);
6165 break;
6166 case CMD_break:
6167 line = compile_break(p, &cctx);
6168 break;
6169
6170 case CMD_try:
6171 line = compile_try(p, &cctx);
6172 break;
6173 case CMD_catch:
6174 line = compile_catch(p, &cctx);
6175 break;
6176 case CMD_finally:
6177 line = compile_finally(p, &cctx);
6178 break;
6179 case CMD_endtry:
6180 line = compile_endtry(p, &cctx);
6181 break;
6182 case CMD_throw:
6183 line = compile_throw(p, &cctx);
6184 break;
6185
6186 case CMD_echo:
6187 line = compile_echo(p, TRUE, &cctx);
6188 break;
6189 case CMD_echon:
6190 line = compile_echo(p, FALSE, &cctx);
6191 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01006192 case CMD_execute:
6193 line = compile_execute(p, &cctx);
6194 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006195
6196 default:
6197 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01006198 // TODO:
6199 // CMD_echomsg
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01006200 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006201 generate_EXEC(&cctx, line);
6202 line = (char_u *)"";
6203 break;
6204 }
6205 if (line == NULL)
6206 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006207 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006208
6209 if (cctx.ctx_type_stack.ga_len < 0)
6210 {
6211 iemsg("Type stack underflow");
6212 goto erret;
6213 }
6214 }
6215
6216 if (cctx.ctx_scope != NULL)
6217 {
6218 if (cctx.ctx_scope->se_type == IF_SCOPE)
6219 emsg(_(e_endif));
6220 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6221 emsg(_(e_endwhile));
6222 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6223 emsg(_(e_endfor));
6224 else
6225 emsg(_("E1026: Missing }"));
6226 goto erret;
6227 }
6228
6229 if (!had_return)
6230 {
6231 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6232 {
6233 emsg(_("E1027: Missing return statement"));
6234 goto erret;
6235 }
6236
6237 // Return zero if there is no return at the end.
6238 generate_PUSHNR(&cctx, 0);
6239 generate_instr(&cctx, ISN_RETURN);
6240 }
6241
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006242 {
6243 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6244 + ufunc->uf_dfunc_idx;
6245 dfunc->df_deleted = FALSE;
6246 dfunc->df_instr = instr->ga_data;
6247 dfunc->df_instr_count = instr->ga_len;
6248 dfunc->df_varcount = cctx.ctx_max_local;
6249 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006250
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006251 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006252 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006253 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006254
6255 // Create a type for the function, with the return type and any
6256 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006257 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6258 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006259 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006260 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006261 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6262 argcount, &ufunc->uf_type_list);
6263 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006264 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006265 argcount + varargs,
6266 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006267 {
6268 ret = FAIL;
6269 goto erret;
6270 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006271 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6272 ufunc->uf_func_type->tt_min_argcount =
6273 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006274 if (ufunc->uf_arg_types == NULL)
6275 {
6276 int i;
6277
6278 // lambda does not have argument types.
6279 for (i = 0; i < argcount; ++i)
6280 ufunc->uf_func_type->tt_args[i] = &t_any;
6281 }
6282 else
6283 mch_memmove(ufunc->uf_func_type->tt_args,
6284 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006285 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006286 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006287 ufunc->uf_func_type->tt_args[argcount] =
6288 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006289 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6290 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006291 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006292 else
6293 // No arguments, can use a predefined type.
6294 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6295 argcount, &ufunc->uf_type_list);
6296
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006297 }
6298
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006299 ret = OK;
6300
6301erret:
6302 if (ret == FAIL)
6303 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006304 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006305 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6306 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006307
6308 for (idx = 0; idx < instr->ga_len; ++idx)
6309 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006310 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006311
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006312 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006313 if (!dfunc->df_deleted)
6314 --def_functions.ga_len;
6315
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006316 while (cctx.ctx_scope != NULL)
6317 drop_scope(&cctx);
6318
Bram Moolenaar20431c92020-03-20 18:39:46 +01006319 // Don't execute this function body.
6320 ga_clear_strings(&ufunc->uf_lines);
6321
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006322 if (errormsg != NULL)
6323 emsg(errormsg);
6324 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006325 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006326 }
6327
6328 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006329 free_imported(&cctx);
6330 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006331 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006332}
6333
6334/*
6335 * Delete an instruction, free what it contains.
6336 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006337 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006338delete_instr(isn_T *isn)
6339{
6340 switch (isn->isn_type)
6341 {
6342 case ISN_EXEC:
6343 case ISN_LOADENV:
6344 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006345 case ISN_LOADB:
6346 case ISN_LOADW:
6347 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006348 case ISN_LOADOPT:
6349 case ISN_MEMBER:
6350 case ISN_PUSHEXC:
6351 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006352 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006353 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006354 case ISN_STOREB:
6355 case ISN_STOREW:
6356 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006357 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006358 vim_free(isn->isn_arg.string);
6359 break;
6360
6361 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006362 case ISN_STORES:
6363 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006364 break;
6365
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006366 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006367 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006368 vim_free(isn->isn_arg.unlet.ul_name);
6369 break;
6370
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006371 case ISN_STOREOPT:
6372 vim_free(isn->isn_arg.storeopt.so_name);
6373 break;
6374
6375 case ISN_PUSHBLOB: // push blob isn_arg.blob
6376 blob_unref(isn->isn_arg.blob);
6377 break;
6378
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006379 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006380#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006381 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006382#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006383 break;
6384
6385 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006386#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006387 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006388#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006389 break;
6390
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006391 case ISN_UCALL:
6392 vim_free(isn->isn_arg.ufunc.cuf_name);
6393 break;
6394
6395 case ISN_2BOOL:
6396 case ISN_2STRING:
6397 case ISN_ADDBLOB:
6398 case ISN_ADDLIST:
6399 case ISN_BCALL:
6400 case ISN_CATCH:
6401 case ISN_CHECKNR:
6402 case ISN_CHECKTYPE:
6403 case ISN_COMPAREANY:
6404 case ISN_COMPAREBLOB:
6405 case ISN_COMPAREBOOL:
6406 case ISN_COMPAREDICT:
6407 case ISN_COMPAREFLOAT:
6408 case ISN_COMPAREFUNC:
6409 case ISN_COMPARELIST:
6410 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006411 case ISN_COMPARESPECIAL:
6412 case ISN_COMPARESTRING:
6413 case ISN_CONCAT:
6414 case ISN_DCALL:
6415 case ISN_DROP:
6416 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006417 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006418 case ISN_ENDTRY:
6419 case ISN_FOR:
6420 case ISN_FUNCREF:
6421 case ISN_INDEX:
6422 case ISN_JUMP:
6423 case ISN_LOAD:
6424 case ISN_LOADSCRIPT:
6425 case ISN_LOADREG:
6426 case ISN_LOADV:
6427 case ISN_NEGATENR:
6428 case ISN_NEWDICT:
6429 case ISN_NEWLIST:
6430 case ISN_OPNR:
6431 case ISN_OPFLOAT:
6432 case ISN_OPANY:
6433 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006434 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006435 case ISN_PUSHF:
6436 case ISN_PUSHNR:
6437 case ISN_PUSHBOOL:
6438 case ISN_PUSHSPEC:
6439 case ISN_RETURN:
6440 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006441 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006442 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006443 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006444 case ISN_STORESCRIPT:
6445 case ISN_THROW:
6446 case ISN_TRY:
6447 // nothing allocated
6448 break;
6449 }
6450}
6451
6452/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006453 * Free all instructions for "dfunc".
6454 */
6455 static void
6456delete_def_function_contents(dfunc_T *dfunc)
6457{
6458 int idx;
6459
6460 ga_clear(&dfunc->df_def_args_isn);
6461
6462 if (dfunc->df_instr != NULL)
6463 {
6464 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6465 delete_instr(dfunc->df_instr + idx);
6466 VIM_CLEAR(dfunc->df_instr);
6467 }
6468
6469 dfunc->df_deleted = TRUE;
6470}
6471
6472/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006473 * When a user function is deleted, delete any associated def function.
6474 */
6475 void
6476delete_def_function(ufunc_T *ufunc)
6477{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006478 if (ufunc->uf_dfunc_idx >= 0)
6479 {
6480 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6481 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006482
Bram Moolenaar20431c92020-03-20 18:39:46 +01006483 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006484 }
6485}
6486
6487#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006488/*
6489 * Free all functions defined with ":def".
6490 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006491 void
6492free_def_functions(void)
6493{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006494 int idx;
6495
6496 for (idx = 0; idx < def_functions.ga_len; ++idx)
6497 {
6498 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6499
6500 delete_def_function_contents(dfunc);
6501 }
6502
6503 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006504}
6505#endif
6506
6507
6508#endif // FEAT_EVAL