blob: 4d1e3acc6451212838bd82238f3fc769053256ea [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/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001404 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001405 */
1406 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001407generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001408{
1409 isn_T *isn;
1410
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001411 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001412 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
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001430/*
1431 * Reserve space for a local variable.
1432 * Return the index or -1 if it failed.
1433 */
1434 static int
1435reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1436{
1437 int idx;
1438 lvar_T *lvar;
1439
1440 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1441 {
1442 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1443 return -1;
1444 }
1445
1446 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1447 return -1;
1448 idx = cctx->ctx_locals.ga_len;
1449 if (cctx->ctx_max_local < idx + 1)
1450 cctx->ctx_max_local = idx + 1;
1451 ++cctx->ctx_locals.ga_len;
1452
1453 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1454 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1455 lvar->lv_const = isConst;
1456 lvar->lv_type = type;
1457
1458 return idx;
1459}
1460
1461/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001462 * Remove local variables above "new_top".
1463 */
1464 static void
1465unwind_locals(cctx_T *cctx, int new_top)
1466{
1467 if (cctx->ctx_locals.ga_len > new_top)
1468 {
1469 int idx;
1470 lvar_T *lvar;
1471
1472 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1473 {
1474 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1475 vim_free(lvar->lv_name);
1476 }
1477 }
1478 cctx->ctx_locals.ga_len = new_top;
1479}
1480
1481/*
1482 * Free all local variables.
1483 */
1484 static void
1485free_local(cctx_T *cctx)
1486{
1487 unwind_locals(cctx, 0);
1488 ga_clear(&cctx->ctx_locals);
1489}
1490
1491/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001492 * Skip over a type definition and return a pointer to just after it.
1493 */
1494 char_u *
1495skip_type(char_u *start)
1496{
1497 char_u *p = start;
1498
1499 while (ASCII_ISALNUM(*p) || *p == '_')
1500 ++p;
1501
1502 // Skip over "<type>"; this is permissive about white space.
1503 if (*skipwhite(p) == '<')
1504 {
1505 p = skipwhite(p);
1506 p = skip_type(skipwhite(p + 1));
1507 p = skipwhite(p);
1508 if (*p == '>')
1509 ++p;
1510 }
1511 return p;
1512}
1513
1514/*
1515 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001516 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001517 * Returns NULL in case of failure.
1518 */
1519 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001520parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001521{
1522 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001523 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001524
1525 if (**arg != '<')
1526 {
1527 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001528 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001529 else
1530 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001531 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001532 }
1533 *arg = skipwhite(*arg + 1);
1534
Bram Moolenaard77a8522020-04-03 21:59:57 +02001535 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001536
1537 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001538 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001539 {
1540 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001541 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001542 }
1543 ++*arg;
1544
1545 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001546 return get_list_type(member_type, type_gap);
1547 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001548}
1549
1550/*
1551 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001552 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001553 */
1554 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001555parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001556{
1557 char_u *p = *arg;
1558 size_t len;
1559
1560 // skip over the first word
1561 while (ASCII_ISALNUM(*p) || *p == '_')
1562 ++p;
1563 len = p - *arg;
1564
1565 switch (**arg)
1566 {
1567 case 'a':
1568 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1569 {
1570 *arg += len;
1571 return &t_any;
1572 }
1573 break;
1574 case 'b':
1575 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1576 {
1577 *arg += len;
1578 return &t_bool;
1579 }
1580 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1581 {
1582 *arg += len;
1583 return &t_blob;
1584 }
1585 break;
1586 case 'c':
1587 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1588 {
1589 *arg += len;
1590 return &t_channel;
1591 }
1592 break;
1593 case 'd':
1594 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1595 {
1596 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001597 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001598 }
1599 break;
1600 case 'f':
1601 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1602 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001603#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001604 *arg += len;
1605 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001606#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001607 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001608 return &t_any;
1609#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001610 }
1611 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1612 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001613 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001614 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001615 int argcount = -1;
1616 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001617 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001618 type_T *arg_type[MAX_FUNC_ARGS + 1];
1619
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001620 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001621 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001622 if (**arg == '(')
1623 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001624 // "func" may or may not return a value, "func()" does
1625 // not return a value.
1626 ret_type = &t_void;
1627
Bram Moolenaard77a8522020-04-03 21:59:57 +02001628 p = ++*arg;
1629 argcount = 0;
1630 while (*p != NUL && *p != ')')
1631 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001632 if (*p == '?')
1633 {
1634 if (first_optional == -1)
1635 first_optional = argcount;
1636 ++p;
1637 }
1638 else if (first_optional != -1)
1639 {
1640 emsg(_("E1007: mandatory argument after optional argument"));
1641 return &t_any;
1642 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001643 else if (STRNCMP(p, "...", 3) == 0)
1644 {
1645 flags |= TTFLAG_VARARGS;
1646 p += 3;
1647 }
1648
1649 arg_type[argcount++] = parse_type(&p, type_gap);
1650
1651 // Nothing comes after "...{type}".
1652 if (flags & TTFLAG_VARARGS)
1653 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001654
Bram Moolenaard77a8522020-04-03 21:59:57 +02001655 if (*p != ',' && *skipwhite(p) == ',')
1656 {
1657 semsg(_(e_no_white_before), ",");
1658 return &t_any;
1659 }
1660 if (*p == ',')
1661 {
1662 ++p;
1663 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001664 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001665 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001666 return &t_any;
1667 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001668 }
1669 p = skipwhite(p);
1670 if (argcount == MAX_FUNC_ARGS)
1671 {
1672 emsg(_("E740: Too many argument types"));
1673 return &t_any;
1674 }
1675 }
1676
1677 p = skipwhite(p);
1678 if (*p != ')')
1679 {
1680 emsg(_(e_missing_close));
1681 return &t_any;
1682 }
1683 *arg = p + 1;
1684 }
1685 if (**arg == ':')
1686 {
1687 // parse return type
1688 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001689 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001690 semsg(_(e_white_after), ":");
1691 *arg = skipwhite(*arg);
1692 ret_type = parse_type(arg, type_gap);
1693 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001694 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001695 type = get_func_type(ret_type, argcount, type_gap);
1696 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001697 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001698 type = alloc_func_type(ret_type, argcount, type_gap);
1699 type->tt_flags = flags;
1700 if (argcount > 0)
1701 {
1702 type->tt_argcount = argcount;
1703 type->tt_min_argcount = first_optional == -1
1704 ? argcount : first_optional;
1705 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001706 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001707 return &t_any;
1708 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001709 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001710 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001711 }
1712 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001713 }
1714 break;
1715 case 'j':
1716 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1717 {
1718 *arg += len;
1719 return &t_job;
1720 }
1721 break;
1722 case 'l':
1723 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1724 {
1725 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001726 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001727 }
1728 break;
1729 case 'n':
1730 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1731 {
1732 *arg += len;
1733 return &t_number;
1734 }
1735 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001736 case 's':
1737 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1738 {
1739 *arg += len;
1740 return &t_string;
1741 }
1742 break;
1743 case 'v':
1744 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1745 {
1746 *arg += len;
1747 return &t_void;
1748 }
1749 break;
1750 }
1751
1752 semsg(_("E1010: Type not recognized: %s"), *arg);
1753 return &t_any;
1754}
1755
1756/*
1757 * Check if "type1" and "type2" are exactly the same.
1758 */
1759 static int
1760equal_type(type_T *type1, type_T *type2)
1761{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001762 int i;
1763
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001764 if (type1->tt_type != type2->tt_type)
1765 return FALSE;
1766 switch (type1->tt_type)
1767 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001768 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001769 case VAR_ANY:
1770 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001771 case VAR_SPECIAL:
1772 case VAR_BOOL:
1773 case VAR_NUMBER:
1774 case VAR_FLOAT:
1775 case VAR_STRING:
1776 case VAR_BLOB:
1777 case VAR_JOB:
1778 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001779 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001780 case VAR_LIST:
1781 case VAR_DICT:
1782 return equal_type(type1->tt_member, type2->tt_member);
1783 case VAR_FUNC:
1784 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001785 if (!equal_type(type1->tt_member, type2->tt_member)
1786 || type1->tt_argcount != type2->tt_argcount)
1787 return FALSE;
1788 if (type1->tt_argcount < 0
1789 || type1->tt_args == NULL || type2->tt_args == NULL)
1790 return TRUE;
1791 for (i = 0; i < type1->tt_argcount; ++i)
1792 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1793 return FALSE;
1794 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001795 }
1796 return TRUE;
1797}
1798
1799/*
1800 * Find the common type of "type1" and "type2" and put it in "dest".
1801 * "type2" and "dest" may be the same.
1802 */
1803 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001804common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001805{
1806 if (equal_type(type1, type2))
1807 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001808 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001809 return;
1810 }
1811
1812 if (type1->tt_type == type2->tt_type)
1813 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001814 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1815 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001816 type_T *common;
1817
Bram Moolenaard77a8522020-04-03 21:59:57 +02001818 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001819 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001820 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001821 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001822 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001823 return;
1824 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001825 if (type1->tt_type == VAR_FUNC)
1826 {
1827 type_T *common;
1828
1829 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1830 if (type1->tt_argcount == type2->tt_argcount
1831 && type1->tt_argcount >= 0)
1832 {
1833 int argcount = type1->tt_argcount;
1834 int i;
1835
1836 *dest = alloc_func_type(common, argcount, type_gap);
1837 if (type1->tt_args != NULL && type2->tt_args != NULL)
1838 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001839 if (func_type_add_arg_types(*dest, argcount,
1840 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001841 for (i = 0; i < argcount; ++i)
1842 common_type(type1->tt_args[i], type2->tt_args[i],
1843 &(*dest)->tt_args[i], type_gap);
1844 }
1845 }
1846 else
1847 *dest = alloc_func_type(common, -1, type_gap);
1848 return;
1849 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001850 }
1851
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001852 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001853}
1854
1855 char *
1856vartype_name(vartype_T type)
1857{
1858 switch (type)
1859 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001860 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001861 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001862 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001863 case VAR_SPECIAL: return "special";
1864 case VAR_BOOL: return "bool";
1865 case VAR_NUMBER: return "number";
1866 case VAR_FLOAT: return "float";
1867 case VAR_STRING: return "string";
1868 case VAR_BLOB: return "blob";
1869 case VAR_JOB: return "job";
1870 case VAR_CHANNEL: return "channel";
1871 case VAR_LIST: return "list";
1872 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001873
1874 case VAR_FUNC:
1875 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001876 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001877 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001878}
1879
1880/*
1881 * Return the name of a type.
1882 * The result may be in allocated memory, in which case "tofree" is set.
1883 */
1884 char *
1885type_name(type_T *type, char **tofree)
1886{
1887 char *name = vartype_name(type->tt_type);
1888
1889 *tofree = NULL;
1890 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1891 {
1892 char *member_free;
1893 char *member_name = type_name(type->tt_member, &member_free);
1894 size_t len;
1895
1896 len = STRLEN(name) + STRLEN(member_name) + 3;
1897 *tofree = alloc(len);
1898 if (*tofree != NULL)
1899 {
1900 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1901 vim_free(member_free);
1902 return *tofree;
1903 }
1904 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001905 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001906 {
1907 garray_T ga;
1908 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001909 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001910
1911 ga_init2(&ga, 1, 100);
1912 if (ga_grow(&ga, 20) == FAIL)
1913 return "[unknown]";
1914 *tofree = ga.ga_data;
1915 STRCPY(ga.ga_data, "func(");
1916 ga.ga_len += 5;
1917
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001918 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001919 {
1920 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001921 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001922 int len;
1923
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001924 if (type->tt_args == NULL)
1925 arg_type = "[unknown]";
1926 else
1927 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001928 if (i > 0)
1929 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001930 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001931 ga.ga_len += 2;
1932 }
1933 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001934 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001935 {
1936 vim_free(arg_free);
1937 return "[unknown]";
1938 }
1939 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001940 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001941 {
1942 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1943 ga.ga_len += 3;
1944 }
1945 else if (i >= type->tt_min_argcount)
1946 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001947 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001948 ga.ga_len += len;
1949 vim_free(arg_free);
1950 }
1951
1952 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001953 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001954 else
1955 {
1956 char *ret_free;
1957 char *ret_name = type_name(type->tt_member, &ret_free);
1958 int len;
1959
1960 len = (int)STRLEN(ret_name) + 4;
1961 if (ga_grow(&ga, len) == FAIL)
1962 {
1963 vim_free(ret_free);
1964 return "[unknown]";
1965 }
1966 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001967 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1968 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001969 vim_free(ret_free);
1970 }
1971 return ga.ga_data;
1972 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001973
1974 return name;
1975}
1976
1977/*
1978 * Find "name" in script-local items of script "sid".
1979 * Returns the index in "sn_var_vals" if found.
1980 * If found but not in "sn_var_vals" returns -1.
1981 * If not found returns -2.
1982 */
1983 int
1984get_script_item_idx(int sid, char_u *name, int check_writable)
1985{
1986 hashtab_T *ht;
1987 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001988 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001989 int idx;
1990
1991 // First look the name up in the hashtable.
1992 if (sid <= 0 || sid > script_items.ga_len)
1993 return -1;
1994 ht = &SCRIPT_VARS(sid);
1995 di = find_var_in_ht(ht, 0, name, TRUE);
1996 if (di == NULL)
1997 return -2;
1998
1999 // Now find the svar_T index in sn_var_vals.
2000 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2001 {
2002 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2003
2004 if (sv->sv_tv == &di->di_tv)
2005 {
2006 if (check_writable && sv->sv_const)
2007 semsg(_(e_readonlyvar), name);
2008 return idx;
2009 }
2010 }
2011 return -1;
2012}
2013
2014/*
2015 * Find "name" in imported items of the current script/
2016 */
2017 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002018find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002019{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002020 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002021 int idx;
2022
2023 if (cctx != NULL)
2024 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2025 {
2026 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2027 + idx;
2028
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002029 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2030 : STRLEN(import->imp_name) == len
2031 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002032 return import;
2033 }
2034
2035 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2036 {
2037 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2038
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002039 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2040 : STRLEN(import->imp_name) == len
2041 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002042 return import;
2043 }
2044 return NULL;
2045}
2046
2047/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002048 * Free all imported variables.
2049 */
2050 static void
2051free_imported(cctx_T *cctx)
2052{
2053 int idx;
2054
2055 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2056 {
2057 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2058
2059 vim_free(import->imp_name);
2060 }
2061 ga_clear(&cctx->ctx_imports);
2062}
2063
2064/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002065 * Get the next line of the function from "cctx".
2066 * Returns NULL when at the end.
2067 */
2068 static char_u *
2069next_line_from_context(cctx_T *cctx)
2070{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002071 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002072
2073 do
2074 {
2075 ++cctx->ctx_lnum;
2076 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002077 {
2078 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002079 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002080 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002081 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002082 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002083 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2084 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002085 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002086 return line;
2087}
2088
2089/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002090 * Return TRUE if "p" points at a "#" but not at "#{".
2091 */
2092 static int
2093comment_start(char_u *p)
2094{
2095 return p[0] == '#' && p[1] != '{';
2096}
2097
2098/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002099 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002100 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002101 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2102 */
2103 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002104may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002105{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002106 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002107 {
2108 char_u *next = next_line_from_context(cctx);
2109
2110 if (next == NULL)
2111 return FAIL;
2112 *arg = skipwhite(next);
2113 }
2114 return OK;
2115}
2116
2117/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002118 * Generate an instruction to load script-local variable "name", without the
2119 * leading "s:".
2120 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002121 */
2122 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002123compile_load_scriptvar(
2124 cctx_T *cctx,
2125 char_u *name, // variable NUL terminated
2126 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002127 char_u **end, // end of variable
2128 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002129{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002130 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002131 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2132 imported_T *import;
2133
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002134 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002135 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002136 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002137 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2138 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002139 }
2140 if (idx >= 0)
2141 {
2142 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2143
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002144 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002145 current_sctx.sc_sid, idx, sv->sv_type);
2146 return OK;
2147 }
2148
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002149 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002150 if (import != NULL)
2151 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002152 if (import->imp_all)
2153 {
2154 char_u *p = skipwhite(*end);
2155 int name_len;
2156 ufunc_T *ufunc;
2157 type_T *type;
2158
2159 // Used "import * as Name", need to lookup the member.
2160 if (*p != '.')
2161 {
2162 semsg(_("E1060: expected dot after name: %s"), start);
2163 return FAIL;
2164 }
2165 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002166 if (VIM_ISWHITE(*p))
2167 {
2168 emsg(_("E1074: no white space allowed after dot"));
2169 return FAIL;
2170 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002171
2172 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2173 // TODO: what if it is a function?
2174 if (idx < 0)
2175 return FAIL;
2176 *end = p;
2177
2178 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2179 import->imp_sid,
2180 idx,
2181 type);
2182 }
2183 else
2184 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002185 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002186 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2187 import->imp_sid,
2188 import->imp_var_vals_idx,
2189 import->imp_type);
2190 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002191 return OK;
2192 }
2193
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002194 if (error)
2195 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002196 return FAIL;
2197}
2198
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002199 static int
2200generate_funcref(cctx_T *cctx, char_u *name)
2201{
2202 ufunc_T *ufunc = find_func(name, cctx);
2203
2204 if (ufunc == NULL)
2205 return FAIL;
2206
2207 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2208}
2209
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002210/*
2211 * Compile a variable name into a load instruction.
2212 * "end" points to just after the name.
2213 * When "error" is FALSE do not give an error when not found.
2214 */
2215 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002216compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002217{
2218 type_T *type;
2219 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002220 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002221 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002222 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002223
2224 if (*(*arg + 1) == ':')
2225 {
2226 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002227 if (end <= *arg + 2)
2228 name = vim_strsave((char_u *)"[empty]");
2229 else
2230 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002231 if (name == NULL)
2232 return FAIL;
2233
2234 if (**arg == 'v')
2235 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002236 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002237 }
2238 else if (**arg == 'g')
2239 {
2240 // Global variables can be defined later, thus we don't check if it
2241 // exists, give error at runtime.
2242 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2243 }
2244 else if (**arg == 's')
2245 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002246 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002247 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002248 else if (**arg == 'b')
2249 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002250 // Buffer-local variables can be defined later, thus we don't check
2251 // if it exists, give error at runtime.
2252 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002253 }
2254 else if (**arg == 'w')
2255 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002256 // Window-local variables can be defined later, thus we don't check
2257 // if it exists, give error at runtime.
2258 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002259 }
2260 else if (**arg == 't')
2261 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002262 // Tabpage-local variables can be defined later, thus we don't
2263 // check if it exists, give error at runtime.
2264 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002265 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002266 else
2267 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002268 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002269 goto theend;
2270 }
2271 }
2272 else
2273 {
2274 size_t len = end - *arg;
2275 int idx;
2276 int gen_load = FALSE;
2277
2278 name = vim_strnsave(*arg, end - *arg);
2279 if (name == NULL)
2280 return FAIL;
2281
2282 idx = lookup_arg(*arg, len, cctx);
2283 if (idx >= 0)
2284 {
2285 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2286 type = cctx->ctx_ufunc->uf_arg_types[idx];
2287 else
2288 type = &t_any;
2289
2290 // Arguments are located above the frame pointer.
2291 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2292 if (cctx->ctx_ufunc->uf_va_name != NULL)
2293 --idx;
2294 gen_load = TRUE;
2295 }
2296 else if (lookup_vararg(*arg, len, cctx))
2297 {
2298 // varargs is always the last argument
2299 idx = -STACK_FRAME_SIZE - 1;
2300 type = cctx->ctx_ufunc->uf_va_type;
2301 gen_load = TRUE;
2302 }
2303 else
2304 {
2305 idx = lookup_local(*arg, len, cctx);
2306 if (idx >= 0)
2307 {
2308 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2309 gen_load = TRUE;
2310 }
2311 else
2312 {
2313 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2314 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2315 res = generate_PUSHBOOL(cctx, **arg == 't'
2316 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002317 else
2318 {
2319 // "var" can be script-local even without using "s:" if it
2320 // already exists.
2321 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2322 == SCRIPT_VERSION_VIM9
2323 || lookup_script(*arg, len) == OK)
2324 res = compile_load_scriptvar(cctx, name, *arg, &end,
2325 FALSE);
2326
2327 // When the name starts with an uppercase letter or "x:" it
2328 // can be a user defined function.
2329 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2330 res = generate_funcref(cctx, name);
2331 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002332 }
2333 }
2334 if (gen_load)
2335 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2336 }
2337
2338 *arg = end;
2339
2340theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002341 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002342 semsg(_(e_var_notfound), name);
2343 vim_free(name);
2344 return res;
2345}
2346
2347/*
2348 * Compile the argument expressions.
2349 * "arg" points to just after the "(" and is advanced to after the ")"
2350 */
2351 static int
2352compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2353{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002354 char_u *p = *arg;
2355 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002356
Bram Moolenaare6085c52020-04-12 20:19:16 +02002357 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002358 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002359 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002360 {
2361 p = next_line_from_context(cctx);
2362 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002363 goto failret;
2364 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002365 p = skipwhite(p);
2366 }
2367 if (*p == ')')
2368 {
2369 *arg = p + 1;
2370 return OK;
2371 }
2372
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002373 if (compile_expr1(&p, cctx) == FAIL)
2374 return FAIL;
2375 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002376
2377 if (*p != ',' && *skipwhite(p) == ',')
2378 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002379 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002380 p = skipwhite(p);
2381 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002382 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002383 {
2384 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002385 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002386 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002387 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002388 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002389 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002390 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002391failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002392 emsg(_(e_missing_close));
2393 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002394}
2395
2396/*
2397 * Compile a function call: name(arg1, arg2)
2398 * "arg" points to "name", "arg + varlen" to the "(".
2399 * "argcount_init" is 1 for "value->method()"
2400 * Instructions:
2401 * EVAL arg1
2402 * EVAL arg2
2403 * BCALL / DCALL / UCALL
2404 */
2405 static int
2406compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2407{
2408 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002409 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002410 int argcount = argcount_init;
2411 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002412 char_u fname_buf[FLEN_FIXED + 1];
2413 char_u *tofree = NULL;
2414 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002415 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002416 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002417
2418 if (varlen >= sizeof(namebuf))
2419 {
2420 semsg(_("E1011: name too long: %s"), name);
2421 return FAIL;
2422 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002423 vim_strncpy(namebuf, *arg, varlen);
2424 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002425
2426 *arg = skipwhite(*arg + varlen + 1);
2427 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002428 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002429
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002430 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002431 {
2432 int idx;
2433
2434 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002435 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002436 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002437 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002438 else
2439 semsg(_(e_unknownfunc), namebuf);
2440 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002441 }
2442
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002443 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002444 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002445 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002446 {
2447 res = generate_CALL(cctx, ufunc, argcount);
2448 goto theend;
2449 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002450
2451 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002452 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002453 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002454 if (STRNCMP(namebuf, "g:", 2) != 0
2455 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002456 {
2457 res = generate_PCALL(cctx, argcount, FALSE);
2458 goto theend;
2459 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002460
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002461 // A global function may be defined only later. Need to figure out at
2462 // runtime.
2463 if (STRNCMP(namebuf, "g:", 2) == 0)
2464 res = generate_UCALL(cctx, name, argcount);
2465 else
2466 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002467
2468theend:
2469 vim_free(tofree);
2470 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002471}
2472
2473// like NAMESPACE_CHAR but with 'a' and 'l'.
2474#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2475
2476/*
2477 * Find the end of a variable or function name. Unlike find_name_end() this
2478 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002479 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002480 * Return a pointer to just after the name. Equal to "arg" if there is no
2481 * valid name.
2482 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002483 static char_u *
2484to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002485{
2486 char_u *p;
2487
2488 // Quick check for valid starting character.
2489 if (!eval_isnamec1(*arg))
2490 return arg;
2491
2492 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2493 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2494 // and can be used in slice "[n:]".
2495 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002496 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002497 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2498 break;
2499 return p;
2500}
2501
2502/*
2503 * Like to_name_end() but also skip over a list or dict constant.
2504 */
2505 char_u *
2506to_name_const_end(char_u *arg)
2507{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002508 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002509 typval_T rettv;
2510
2511 if (p == arg && *arg == '[')
2512 {
2513
2514 // Can be "[1, 2, 3]->Func()".
2515 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2516 p = arg;
2517 }
2518 else if (p == arg && *arg == '#' && arg[1] == '{')
2519 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002520 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002521 ++p;
2522 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2523 p = arg;
2524 }
2525 else if (p == arg && *arg == '{')
2526 {
2527 int ret = get_lambda_tv(&p, &rettv, FALSE);
2528
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002529 // Can be "{x -> ret}()".
2530 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002531 if (ret == NOTDONE)
2532 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2533 if (ret != OK)
2534 p = arg;
2535 }
2536
2537 return p;
2538}
2539
2540 static void
2541type_mismatch(type_T *expected, type_T *actual)
2542{
2543 char *tofree1, *tofree2;
2544
2545 semsg(_("E1013: type mismatch, expected %s but got %s"),
2546 type_name(expected, &tofree1), type_name(actual, &tofree2));
2547 vim_free(tofree1);
2548 vim_free(tofree2);
2549}
2550
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002551 static void
2552arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2553{
2554 char *tofree1, *tofree2;
2555
2556 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2557 argidx,
2558 type_name(expected, &tofree1), type_name(actual, &tofree2));
2559 vim_free(tofree1);
2560 vim_free(tofree2);
2561}
2562
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002563/*
2564 * Check if the expected and actual types match.
2565 */
2566 static int
2567check_type(type_T *expected, type_T *actual, int give_msg)
2568{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002569 int ret = OK;
2570
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002571 // When expected is "unknown" we accept any actual type.
2572 // When expected is "any" we accept any actual type except "void".
2573 if (expected->tt_type != VAR_UNKNOWN
2574 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002575 {
2576 if (expected->tt_type != actual->tt_type)
2577 {
2578 if (give_msg)
2579 type_mismatch(expected, actual);
2580 return FAIL;
2581 }
2582 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2583 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002584 // "unknown" is used for an empty list or dict
2585 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002586 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002587 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002588 else if (expected->tt_type == VAR_FUNC)
2589 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002590 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002591 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2592 if (ret == OK && expected->tt_argcount != -1
2593 && (actual->tt_argcount < expected->tt_min_argcount
2594 || actual->tt_argcount > expected->tt_argcount))
2595 ret = FAIL;
2596 }
2597 if (ret == FAIL && give_msg)
2598 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002599 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002600 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002601}
2602
2603/*
2604 * Check that
2605 * - "actual" is "expected" type or
2606 * - "actual" is a type that can be "expected" type: add a runtime check; or
2607 * - return FAIL.
2608 */
2609 static int
2610need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2611{
Bram Moolenaar89228602020-04-05 22:14:54 +02002612 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002613 return OK;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002614 if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002615 {
2616 type_mismatch(expected, actual);
2617 return FAIL;
2618 }
2619 generate_TYPECHECK(cctx, expected, offset);
2620 return OK;
2621}
2622
2623/*
2624 * parse a list: [expr, expr]
2625 * "*arg" points to the '['.
2626 */
2627 static int
2628compile_list(char_u **arg, cctx_T *cctx)
2629{
2630 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002631 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002632 int count = 0;
2633
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002634 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002635 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002636 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002637 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002638 p = next_line_from_context(cctx);
2639 if (p == NULL)
2640 {
2641 semsg(_(e_list_end), *arg);
2642 return FAIL;
2643 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002644 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002645 p = skipwhite(p);
2646 }
2647 if (*p == ']')
2648 {
2649 ++p;
2650 // Allow for following comment, after at least one space.
2651 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2652 p += STRLEN(p);
2653 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002654 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002655 if (compile_expr1(&p, cctx) == FAIL)
2656 break;
2657 ++count;
2658 if (*p == ',')
2659 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002660 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002661 p = skipwhite(p);
2662 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002663 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002664
2665 generate_NEWLIST(cctx, count);
2666 return OK;
2667}
2668
2669/*
2670 * parse a lambda: {arg, arg -> expr}
2671 * "*arg" points to the '{'.
2672 */
2673 static int
2674compile_lambda(char_u **arg, cctx_T *cctx)
2675{
2676 garray_T *instr = &cctx->ctx_instr;
2677 typval_T rettv;
2678 ufunc_T *ufunc;
2679
2680 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002681 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002682 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002683
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002684 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002685 ++ufunc->uf_refcount;
2686 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002687 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002688
2689 // The function will have one line: "return {expr}".
2690 // Compile it into instructions.
2691 compile_def_function(ufunc, TRUE);
2692
2693 if (ufunc->uf_dfunc_idx >= 0)
2694 {
2695 if (ga_grow(instr, 1) == FAIL)
2696 return FAIL;
2697 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2698 return OK;
2699 }
2700 return FAIL;
2701}
2702
2703/*
2704 * Compile a lamda call: expr->{lambda}(args)
2705 * "arg" points to the "{".
2706 */
2707 static int
2708compile_lambda_call(char_u **arg, cctx_T *cctx)
2709{
2710 ufunc_T *ufunc;
2711 typval_T rettv;
2712 int argcount = 1;
2713 int ret = FAIL;
2714
2715 // Get the funcref in "rettv".
2716 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2717 return FAIL;
2718
2719 if (**arg != '(')
2720 {
2721 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002722 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002723 else
2724 semsg(_(e_missing_paren), "lambda");
2725 clear_tv(&rettv);
2726 return FAIL;
2727 }
2728
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002729 ufunc = rettv.vval.v_partial->pt_func;
2730 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002731 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002732 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002733
2734 // The function will have one line: "return {expr}".
2735 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002736 compile_def_function(ufunc, TRUE);
2737
2738 // compile the arguments
2739 *arg = skipwhite(*arg + 1);
2740 if (compile_arguments(arg, cctx, &argcount) == OK)
2741 // call the compiled function
2742 ret = generate_CALL(cctx, ufunc, argcount);
2743
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002744 return ret;
2745}
2746
2747/*
2748 * parse a dict: {'key': val} or #{key: val}
2749 * "*arg" points to the '{'.
2750 */
2751 static int
2752compile_dict(char_u **arg, cctx_T *cctx, int literal)
2753{
2754 garray_T *instr = &cctx->ctx_instr;
2755 int count = 0;
2756 dict_T *d = dict_alloc();
2757 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002758 char_u *whitep = *arg;
2759 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002760
2761 if (d == NULL)
2762 return FAIL;
2763 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002764 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002765 {
2766 char_u *key = NULL;
2767
Bram Moolenaar2c330432020-04-13 14:41:35 +02002768 while (**arg == NUL || (literal && **arg == '"')
2769 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002770 {
2771 *arg = next_line_from_context(cctx);
2772 if (*arg == NULL)
2773 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002774 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002775 *arg = skipwhite(*arg);
2776 }
2777
2778 if (**arg == '}')
2779 break;
2780
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002781 if (literal)
2782 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002783 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002784
Bram Moolenaar2c330432020-04-13 14:41:35 +02002785 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002786 {
2787 semsg(_("E1014: Invalid key: %s"), *arg);
2788 return FAIL;
2789 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002790 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002791 if (generate_PUSHS(cctx, key) == FAIL)
2792 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002793 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002794 }
2795 else
2796 {
2797 isn_T *isn;
2798
2799 if (compile_expr1(arg, cctx) == FAIL)
2800 return FAIL;
2801 // TODO: check type is string
2802 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2803 if (isn->isn_type == ISN_PUSHS)
2804 key = isn->isn_arg.string;
2805 }
2806
2807 // Check for duplicate keys, if using string keys.
2808 if (key != NULL)
2809 {
2810 item = dict_find(d, key, -1);
2811 if (item != NULL)
2812 {
2813 semsg(_(e_duplicate_key), key);
2814 goto failret;
2815 }
2816 item = dictitem_alloc(key);
2817 if (item != NULL)
2818 {
2819 item->di_tv.v_type = VAR_UNKNOWN;
2820 item->di_tv.v_lock = 0;
2821 if (dict_add(d, item) == FAIL)
2822 dictitem_free(item);
2823 }
2824 }
2825
2826 *arg = skipwhite(*arg);
2827 if (**arg != ':')
2828 {
2829 semsg(_(e_missing_dict_colon), *arg);
2830 return FAIL;
2831 }
2832
Bram Moolenaar2c330432020-04-13 14:41:35 +02002833 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002834 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002835 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002836 {
2837 *arg = next_line_from_context(cctx);
2838 if (*arg == NULL)
2839 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002840 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002841 *arg = skipwhite(*arg);
2842 }
2843
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002844 if (compile_expr1(arg, cctx) == FAIL)
2845 return FAIL;
2846 ++count;
2847
Bram Moolenaar2c330432020-04-13 14:41:35 +02002848 whitep = *arg;
2849 p = skipwhite(*arg);
2850 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002851 {
2852 *arg = next_line_from_context(cctx);
2853 if (*arg == NULL)
2854 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002855 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002856 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002857 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002858 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002859 if (**arg == '}')
2860 break;
2861 if (**arg != ',')
2862 {
2863 semsg(_(e_missing_dict_comma), *arg);
2864 goto failret;
2865 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002866 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002867 *arg = skipwhite(*arg + 1);
2868 }
2869
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002870 *arg = *arg + 1;
2871
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002872 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002873 p = skipwhite(*arg);
2874 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002875 *arg += STRLEN(*arg);
2876
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002877 dict_unref(d);
2878 return generate_NEWDICT(cctx, count);
2879
2880failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002881 if (*arg == NULL)
2882 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002883 dict_unref(d);
2884 return FAIL;
2885}
2886
2887/*
2888 * Compile "&option".
2889 */
2890 static int
2891compile_get_option(char_u **arg, cctx_T *cctx)
2892{
2893 typval_T rettv;
2894 char_u *start = *arg;
2895 int ret;
2896
2897 // parse the option and get the current value to get the type.
2898 rettv.v_type = VAR_UNKNOWN;
2899 ret = get_option_tv(arg, &rettv, TRUE);
2900 if (ret == OK)
2901 {
2902 // include the '&' in the name, get_option_tv() expects it.
2903 char_u *name = vim_strnsave(start, *arg - start);
2904 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2905
2906 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2907 vim_free(name);
2908 }
2909 clear_tv(&rettv);
2910
2911 return ret;
2912}
2913
2914/*
2915 * Compile "$VAR".
2916 */
2917 static int
2918compile_get_env(char_u **arg, cctx_T *cctx)
2919{
2920 char_u *start = *arg;
2921 int len;
2922 int ret;
2923 char_u *name;
2924
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002925 ++*arg;
2926 len = get_env_len(arg);
2927 if (len == 0)
2928 {
2929 semsg(_(e_syntax_at), start - 1);
2930 return FAIL;
2931 }
2932
2933 // include the '$' in the name, get_env_tv() expects it.
2934 name = vim_strnsave(start, len + 1);
2935 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2936 vim_free(name);
2937 return ret;
2938}
2939
2940/*
2941 * Compile "@r".
2942 */
2943 static int
2944compile_get_register(char_u **arg, cctx_T *cctx)
2945{
2946 int ret;
2947
2948 ++*arg;
2949 if (**arg == NUL)
2950 {
2951 semsg(_(e_syntax_at), *arg - 1);
2952 return FAIL;
2953 }
2954 if (!valid_yank_reg(**arg, TRUE))
2955 {
2956 emsg_invreg(**arg);
2957 return FAIL;
2958 }
2959 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2960 ++*arg;
2961 return ret;
2962}
2963
2964/*
2965 * Apply leading '!', '-' and '+' to constant "rettv".
2966 */
2967 static int
2968apply_leader(typval_T *rettv, char_u *start, char_u *end)
2969{
2970 char_u *p = end;
2971
2972 // this works from end to start
2973 while (p > start)
2974 {
2975 --p;
2976 if (*p == '-' || *p == '+')
2977 {
2978 // only '-' has an effect, for '+' we only check the type
2979#ifdef FEAT_FLOAT
2980 if (rettv->v_type == VAR_FLOAT)
2981 {
2982 if (*p == '-')
2983 rettv->vval.v_float = -rettv->vval.v_float;
2984 }
2985 else
2986#endif
2987 {
2988 varnumber_T val;
2989 int error = FALSE;
2990
2991 // tv_get_number_chk() accepts a string, but we don't want that
2992 // here
2993 if (check_not_string(rettv) == FAIL)
2994 return FAIL;
2995 val = tv_get_number_chk(rettv, &error);
2996 clear_tv(rettv);
2997 if (error)
2998 return FAIL;
2999 if (*p == '-')
3000 val = -val;
3001 rettv->v_type = VAR_NUMBER;
3002 rettv->vval.v_number = val;
3003 }
3004 }
3005 else
3006 {
3007 int v = tv2bool(rettv);
3008
3009 // '!' is permissive in the type.
3010 clear_tv(rettv);
3011 rettv->v_type = VAR_BOOL;
3012 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3013 }
3014 }
3015 return OK;
3016}
3017
3018/*
3019 * Recognize v: variables that are constants and set "rettv".
3020 */
3021 static void
3022get_vim_constant(char_u **arg, typval_T *rettv)
3023{
3024 if (STRNCMP(*arg, "v:true", 6) == 0)
3025 {
3026 rettv->v_type = VAR_BOOL;
3027 rettv->vval.v_number = VVAL_TRUE;
3028 *arg += 6;
3029 }
3030 else if (STRNCMP(*arg, "v:false", 7) == 0)
3031 {
3032 rettv->v_type = VAR_BOOL;
3033 rettv->vval.v_number = VVAL_FALSE;
3034 *arg += 7;
3035 }
3036 else if (STRNCMP(*arg, "v:null", 6) == 0)
3037 {
3038 rettv->v_type = VAR_SPECIAL;
3039 rettv->vval.v_number = VVAL_NULL;
3040 *arg += 6;
3041 }
3042 else if (STRNCMP(*arg, "v:none", 6) == 0)
3043 {
3044 rettv->v_type = VAR_SPECIAL;
3045 rettv->vval.v_number = VVAL_NONE;
3046 *arg += 6;
3047 }
3048}
3049
3050/*
3051 * Compile code to apply '-', '+' and '!'.
3052 */
3053 static int
3054compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3055{
3056 char_u *p = end;
3057
3058 // this works from end to start
3059 while (p > start)
3060 {
3061 --p;
3062 if (*p == '-' || *p == '+')
3063 {
3064 int negate = *p == '-';
3065 isn_T *isn;
3066
3067 // TODO: check type
3068 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3069 {
3070 --p;
3071 if (*p == '-')
3072 negate = !negate;
3073 }
3074 // only '-' has an effect, for '+' we only check the type
3075 if (negate)
3076 isn = generate_instr(cctx, ISN_NEGATENR);
3077 else
3078 isn = generate_instr(cctx, ISN_CHECKNR);
3079 if (isn == NULL)
3080 return FAIL;
3081 }
3082 else
3083 {
3084 int invert = TRUE;
3085
3086 while (p > start && p[-1] == '!')
3087 {
3088 --p;
3089 invert = !invert;
3090 }
3091 if (generate_2BOOL(cctx, invert) == FAIL)
3092 return FAIL;
3093 }
3094 }
3095 return OK;
3096}
3097
3098/*
3099 * Compile whatever comes after "name" or "name()".
3100 */
3101 static int
3102compile_subscript(
3103 char_u **arg,
3104 cctx_T *cctx,
3105 char_u **start_leader,
3106 char_u *end_leader)
3107{
3108 for (;;)
3109 {
3110 if (**arg == '(')
3111 {
3112 int argcount = 0;
3113
3114 // funcref(arg)
3115 *arg = skipwhite(*arg + 1);
3116 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3117 return FAIL;
3118 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
3119 return FAIL;
3120 }
3121 else if (**arg == '-' && (*arg)[1] == '>')
3122 {
3123 char_u *p;
3124
3125 // something->method()
3126 // Apply the '!', '-' and '+' first:
3127 // -1.0->func() works like (-1.0)->func()
3128 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3129 return FAIL;
3130 *start_leader = end_leader; // don't apply again later
3131
3132 *arg = skipwhite(*arg + 2);
3133 if (**arg == '{')
3134 {
3135 // lambda call: list->{lambda}
3136 if (compile_lambda_call(arg, cctx) == FAIL)
3137 return FAIL;
3138 }
3139 else
3140 {
3141 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003142 p = *arg;
3143 if (ASCII_ISALPHA(*p) && p[1] == ':')
3144 p += 2;
3145 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003146 ;
3147 if (*p != '(')
3148 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003149 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003150 return FAIL;
3151 }
3152 // TODO: base value may not be the first argument
3153 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3154 return FAIL;
3155 }
3156 }
3157 else if (**arg == '[')
3158 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003159 garray_T *stack;
3160 type_T **typep;
3161
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003162 // list index: list[123]
3163 // TODO: more arguments
3164 // TODO: dict member dict['name']
3165 *arg = skipwhite(*arg + 1);
3166 if (compile_expr1(arg, cctx) == FAIL)
3167 return FAIL;
3168
3169 if (**arg != ']')
3170 {
3171 emsg(_(e_missbrac));
3172 return FAIL;
3173 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003174 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003175
3176 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3177 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003178 stack = &cctx->ctx_type_stack;
3179 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3180 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3181 {
3182 emsg(_(e_listreq));
3183 return FAIL;
3184 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003185 if ((*typep)->tt_type == VAR_LIST)
3186 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003187 }
3188 else if (**arg == '.' && (*arg)[1] != '.')
3189 {
3190 char_u *p;
3191
3192 ++*arg;
3193 p = *arg;
3194 // dictionary member: dict.name
3195 if (eval_isnamec1(*p))
3196 while (eval_isnamec(*p))
3197 MB_PTR_ADV(p);
3198 if (p == *arg)
3199 {
3200 semsg(_(e_syntax_at), *arg);
3201 return FAIL;
3202 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003203 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3204 return FAIL;
3205 *arg = p;
3206 }
3207 else
3208 break;
3209 }
3210
3211 // TODO - see handle_subscript():
3212 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3213 // Don't do this when "Func" is already a partial that was bound
3214 // explicitly (pt_auto is FALSE).
3215
3216 return OK;
3217}
3218
3219/*
3220 * Compile an expression at "*p" and add instructions to "instr".
3221 * "p" is advanced until after the expression, skipping white space.
3222 *
3223 * This is the equivalent of eval1(), eval2(), etc.
3224 */
3225
3226/*
3227 * number number constant
3228 * 0zFFFFFFFF Blob constant
3229 * "string" string constant
3230 * 'string' literal string constant
3231 * &option-name option value
3232 * @r register contents
3233 * identifier variable value
3234 * function() function call
3235 * $VAR environment variable
3236 * (expression) nested expression
3237 * [expr, expr] List
3238 * {key: val, key: val} Dictionary
3239 * #{key: val, key: val} Dictionary with literal keys
3240 *
3241 * Also handle:
3242 * ! in front logical NOT
3243 * - in front unary minus
3244 * + in front unary plus (ignored)
3245 * trailing (arg) funcref/partial call
3246 * trailing [] subscript in String or List
3247 * trailing .name entry in Dictionary
3248 * trailing ->name() method call
3249 */
3250 static int
3251compile_expr7(char_u **arg, cctx_T *cctx)
3252{
3253 typval_T rettv;
3254 char_u *start_leader, *end_leader;
3255 int ret = OK;
3256
3257 /*
3258 * Skip '!', '-' and '+' characters. They are handled later.
3259 */
3260 start_leader = *arg;
3261 while (**arg == '!' || **arg == '-' || **arg == '+')
3262 *arg = skipwhite(*arg + 1);
3263 end_leader = *arg;
3264
3265 rettv.v_type = VAR_UNKNOWN;
3266 switch (**arg)
3267 {
3268 /*
3269 * Number constant.
3270 */
3271 case '0': // also for blob starting with 0z
3272 case '1':
3273 case '2':
3274 case '3':
3275 case '4':
3276 case '5':
3277 case '6':
3278 case '7':
3279 case '8':
3280 case '9':
3281 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3282 return FAIL;
3283 break;
3284
3285 /*
3286 * String constant: "string".
3287 */
3288 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3289 return FAIL;
3290 break;
3291
3292 /*
3293 * Literal string constant: 'str''ing'.
3294 */
3295 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3296 return FAIL;
3297 break;
3298
3299 /*
3300 * Constant Vim variable.
3301 */
3302 case 'v': get_vim_constant(arg, &rettv);
3303 ret = NOTDONE;
3304 break;
3305
3306 /*
3307 * List: [expr, expr]
3308 */
3309 case '[': ret = compile_list(arg, cctx);
3310 break;
3311
3312 /*
3313 * Dictionary: #{key: val, key: val}
3314 */
3315 case '#': if ((*arg)[1] == '{')
3316 {
3317 ++*arg;
3318 ret = compile_dict(arg, cctx, TRUE);
3319 }
3320 else
3321 ret = NOTDONE;
3322 break;
3323
3324 /*
3325 * Lambda: {arg, arg -> expr}
3326 * Dictionary: {'key': val, 'key': val}
3327 */
3328 case '{': {
3329 char_u *start = skipwhite(*arg + 1);
3330
3331 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003332 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003333 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003334 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003335 if (ret != FAIL && *start == '>')
3336 ret = compile_lambda(arg, cctx);
3337 else
3338 ret = compile_dict(arg, cctx, FALSE);
3339 }
3340 break;
3341
3342 /*
3343 * Option value: &name
3344 */
3345 case '&': ret = compile_get_option(arg, cctx);
3346 break;
3347
3348 /*
3349 * Environment variable: $VAR.
3350 */
3351 case '$': ret = compile_get_env(arg, cctx);
3352 break;
3353
3354 /*
3355 * Register contents: @r.
3356 */
3357 case '@': ret = compile_get_register(arg, cctx);
3358 break;
3359 /*
3360 * nested expression: (expression).
3361 */
3362 case '(': *arg = skipwhite(*arg + 1);
3363 ret = compile_expr1(arg, cctx); // recursive!
3364 *arg = skipwhite(*arg);
3365 if (**arg == ')')
3366 ++*arg;
3367 else if (ret == OK)
3368 {
3369 emsg(_(e_missing_close));
3370 ret = FAIL;
3371 }
3372 break;
3373
3374 default: ret = NOTDONE;
3375 break;
3376 }
3377 if (ret == FAIL)
3378 return FAIL;
3379
3380 if (rettv.v_type != VAR_UNKNOWN)
3381 {
3382 // apply the '!', '-' and '+' before the constant
3383 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3384 {
3385 clear_tv(&rettv);
3386 return FAIL;
3387 }
3388 start_leader = end_leader; // don't apply again below
3389
3390 // push constant
3391 switch (rettv.v_type)
3392 {
3393 case VAR_BOOL:
3394 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3395 break;
3396 case VAR_SPECIAL:
3397 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3398 break;
3399 case VAR_NUMBER:
3400 generate_PUSHNR(cctx, rettv.vval.v_number);
3401 break;
3402#ifdef FEAT_FLOAT
3403 case VAR_FLOAT:
3404 generate_PUSHF(cctx, rettv.vval.v_float);
3405 break;
3406#endif
3407 case VAR_BLOB:
3408 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3409 rettv.vval.v_blob = NULL;
3410 break;
3411 case VAR_STRING:
3412 generate_PUSHS(cctx, rettv.vval.v_string);
3413 rettv.vval.v_string = NULL;
3414 break;
3415 default:
3416 iemsg("constant type missing");
3417 return FAIL;
3418 }
3419 }
3420 else if (ret == NOTDONE)
3421 {
3422 char_u *p;
3423 int r;
3424
3425 if (!eval_isnamec1(**arg))
3426 {
3427 semsg(_("E1015: Name expected: %s"), *arg);
3428 return FAIL;
3429 }
3430
3431 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003432 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003433 if (*p == '(')
3434 r = compile_call(arg, p - *arg, cctx, 0);
3435 else
3436 r = compile_load(arg, p, cctx, TRUE);
3437 if (r == FAIL)
3438 return FAIL;
3439 }
3440
3441 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3442 return FAIL;
3443
3444 // Now deal with prefixed '-', '+' and '!', if not done already.
3445 return compile_leader(cctx, start_leader, end_leader);
3446}
3447
3448/*
3449 * * number multiplication
3450 * / number division
3451 * % number modulo
3452 */
3453 static int
3454compile_expr6(char_u **arg, cctx_T *cctx)
3455{
3456 char_u *op;
3457
3458 // get the first variable
3459 if (compile_expr7(arg, cctx) == FAIL)
3460 return FAIL;
3461
3462 /*
3463 * Repeat computing, until no "*", "/" or "%" is following.
3464 */
3465 for (;;)
3466 {
3467 op = skipwhite(*arg);
3468 if (*op != '*' && *op != '/' && *op != '%')
3469 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003470 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003471 {
3472 char_u buf[3];
3473
3474 vim_strncpy(buf, op, 1);
3475 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003476 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003477 }
3478 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003479 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003480 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003481
3482 // get the second variable
3483 if (compile_expr7(arg, cctx) == FAIL)
3484 return FAIL;
3485
3486 generate_two_op(cctx, op);
3487 }
3488
3489 return OK;
3490}
3491
3492/*
3493 * + number addition
3494 * - number subtraction
3495 * .. string concatenation
3496 */
3497 static int
3498compile_expr5(char_u **arg, cctx_T *cctx)
3499{
3500 char_u *op;
3501 int oplen;
3502
3503 // get the first variable
3504 if (compile_expr6(arg, cctx) == FAIL)
3505 return FAIL;
3506
3507 /*
3508 * Repeat computing, until no "+", "-" or ".." is following.
3509 */
3510 for (;;)
3511 {
3512 op = skipwhite(*arg);
3513 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3514 break;
3515 oplen = (*op == '.' ? 2 : 1);
3516
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003517 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003518 {
3519 char_u buf[3];
3520
3521 vim_strncpy(buf, op, oplen);
3522 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003523 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003524 }
3525
3526 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003527 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003528 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003529
3530 // get the second variable
3531 if (compile_expr6(arg, cctx) == FAIL)
3532 return FAIL;
3533
3534 if (*op == '.')
3535 {
3536 if (may_generate_2STRING(-2, cctx) == FAIL
3537 || may_generate_2STRING(-1, cctx) == FAIL)
3538 return FAIL;
3539 generate_instr_drop(cctx, ISN_CONCAT, 1);
3540 }
3541 else
3542 generate_two_op(cctx, op);
3543 }
3544
3545 return OK;
3546}
3547
Bram Moolenaar080457c2020-03-03 21:53:32 +01003548 static exptype_T
3549get_compare_type(char_u *p, int *len, int *type_is)
3550{
3551 exptype_T type = EXPR_UNKNOWN;
3552 int i;
3553
3554 switch (p[0])
3555 {
3556 case '=': if (p[1] == '=')
3557 type = EXPR_EQUAL;
3558 else if (p[1] == '~')
3559 type = EXPR_MATCH;
3560 break;
3561 case '!': if (p[1] == '=')
3562 type = EXPR_NEQUAL;
3563 else if (p[1] == '~')
3564 type = EXPR_NOMATCH;
3565 break;
3566 case '>': if (p[1] != '=')
3567 {
3568 type = EXPR_GREATER;
3569 *len = 1;
3570 }
3571 else
3572 type = EXPR_GEQUAL;
3573 break;
3574 case '<': if (p[1] != '=')
3575 {
3576 type = EXPR_SMALLER;
3577 *len = 1;
3578 }
3579 else
3580 type = EXPR_SEQUAL;
3581 break;
3582 case 'i': if (p[1] == 's')
3583 {
3584 // "is" and "isnot"; but not a prefix of a name
3585 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3586 *len = 5;
3587 i = p[*len];
3588 if (!isalnum(i) && i != '_')
3589 {
3590 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3591 *type_is = TRUE;
3592 }
3593 }
3594 break;
3595 }
3596 return type;
3597}
3598
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003599/*
3600 * expr5a == expr5b
3601 * expr5a =~ expr5b
3602 * expr5a != expr5b
3603 * expr5a !~ expr5b
3604 * expr5a > expr5b
3605 * expr5a >= expr5b
3606 * expr5a < expr5b
3607 * expr5a <= expr5b
3608 * expr5a is expr5b
3609 * expr5a isnot expr5b
3610 *
3611 * Produces instructions:
3612 * EVAL expr5a Push result of "expr5a"
3613 * EVAL expr5b Push result of "expr5b"
3614 * COMPARE one of the compare instructions
3615 */
3616 static int
3617compile_expr4(char_u **arg, cctx_T *cctx)
3618{
3619 exptype_T type = EXPR_UNKNOWN;
3620 char_u *p;
3621 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003622 int type_is = FALSE;
3623
3624 // get the first variable
3625 if (compile_expr5(arg, cctx) == FAIL)
3626 return FAIL;
3627
3628 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003629 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003630
3631 /*
3632 * If there is a comparative operator, use it.
3633 */
3634 if (type != EXPR_UNKNOWN)
3635 {
3636 int ic = FALSE; // Default: do not ignore case
3637
3638 if (type_is && (p[len] == '?' || p[len] == '#'))
3639 {
3640 semsg(_(e_invexpr2), *arg);
3641 return FAIL;
3642 }
3643 // extra question mark appended: ignore case
3644 if (p[len] == '?')
3645 {
3646 ic = TRUE;
3647 ++len;
3648 }
3649 // extra '#' appended: match case (ignored)
3650 else if (p[len] == '#')
3651 ++len;
3652 // nothing appended: match case
3653
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003654 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003655 {
3656 char_u buf[7];
3657
3658 vim_strncpy(buf, p, len);
3659 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003660 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003661 }
3662
3663 // get the second variable
3664 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003665 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003666 return FAIL;
3667
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003668 if (compile_expr5(arg, cctx) == FAIL)
3669 return FAIL;
3670
3671 generate_COMPARE(cctx, type, ic);
3672 }
3673
3674 return OK;
3675}
3676
3677/*
3678 * Compile || or &&.
3679 */
3680 static int
3681compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3682{
3683 char_u *p = skipwhite(*arg);
3684 int opchar = *op;
3685
3686 if (p[0] == opchar && p[1] == opchar)
3687 {
3688 garray_T *instr = &cctx->ctx_instr;
3689 garray_T end_ga;
3690
3691 /*
3692 * Repeat until there is no following "||" or "&&"
3693 */
3694 ga_init2(&end_ga, sizeof(int), 10);
3695 while (p[0] == opchar && p[1] == opchar)
3696 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003697 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3698 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003699 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003700 return FAIL;
3701 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003702
3703 if (ga_grow(&end_ga, 1) == FAIL)
3704 {
3705 ga_clear(&end_ga);
3706 return FAIL;
3707 }
3708 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3709 ++end_ga.ga_len;
3710 generate_JUMP(cctx, opchar == '|'
3711 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3712
3713 // eval the next expression
3714 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003715 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003716 return FAIL;
3717
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003718 if ((opchar == '|' ? compile_expr3(arg, cctx)
3719 : compile_expr4(arg, cctx)) == FAIL)
3720 {
3721 ga_clear(&end_ga);
3722 return FAIL;
3723 }
3724 p = skipwhite(*arg);
3725 }
3726
3727 // Fill in the end label in all jumps.
3728 while (end_ga.ga_len > 0)
3729 {
3730 isn_T *isn;
3731
3732 --end_ga.ga_len;
3733 isn = ((isn_T *)instr->ga_data)
3734 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3735 isn->isn_arg.jump.jump_where = instr->ga_len;
3736 }
3737 ga_clear(&end_ga);
3738 }
3739
3740 return OK;
3741}
3742
3743/*
3744 * expr4a && expr4a && expr4a logical AND
3745 *
3746 * Produces instructions:
3747 * EVAL expr4a Push result of "expr4a"
3748 * JUMP_AND_KEEP_IF_FALSE end
3749 * EVAL expr4b Push result of "expr4b"
3750 * JUMP_AND_KEEP_IF_FALSE end
3751 * EVAL expr4c Push result of "expr4c"
3752 * end:
3753 */
3754 static int
3755compile_expr3(char_u **arg, cctx_T *cctx)
3756{
3757 // get the first variable
3758 if (compile_expr4(arg, cctx) == FAIL)
3759 return FAIL;
3760
3761 // || and && work almost the same
3762 return compile_and_or(arg, cctx, "&&");
3763}
3764
3765/*
3766 * expr3a || expr3b || expr3c logical OR
3767 *
3768 * Produces instructions:
3769 * EVAL expr3a Push result of "expr3a"
3770 * JUMP_AND_KEEP_IF_TRUE end
3771 * EVAL expr3b Push result of "expr3b"
3772 * JUMP_AND_KEEP_IF_TRUE end
3773 * EVAL expr3c Push result of "expr3c"
3774 * end:
3775 */
3776 static int
3777compile_expr2(char_u **arg, cctx_T *cctx)
3778{
3779 // eval the first expression
3780 if (compile_expr3(arg, cctx) == FAIL)
3781 return FAIL;
3782
3783 // || and && work almost the same
3784 return compile_and_or(arg, cctx, "||");
3785}
3786
3787/*
3788 * Toplevel expression: expr2 ? expr1a : expr1b
3789 *
3790 * Produces instructions:
3791 * EVAL expr2 Push result of "expr"
3792 * JUMP_IF_FALSE alt jump if false
3793 * EVAL expr1a
3794 * JUMP_ALWAYS end
3795 * alt: EVAL expr1b
3796 * end:
3797 */
3798 static int
3799compile_expr1(char_u **arg, cctx_T *cctx)
3800{
3801 char_u *p;
3802
3803 // evaluate the first expression
3804 if (compile_expr2(arg, cctx) == FAIL)
3805 return FAIL;
3806
3807 p = skipwhite(*arg);
3808 if (*p == '?')
3809 {
3810 garray_T *instr = &cctx->ctx_instr;
3811 garray_T *stack = &cctx->ctx_type_stack;
3812 int alt_idx = instr->ga_len;
3813 int end_idx;
3814 isn_T *isn;
3815 type_T *type1;
3816 type_T *type2;
3817
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003818 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3819 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003820 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003821 return FAIL;
3822 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003823
3824 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3825
3826 // evaluate the second expression; any type is accepted
3827 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003828 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003829 return FAIL;
3830
Bram Moolenaara6d53682020-01-28 23:04:06 +01003831 if (compile_expr1(arg, cctx) == FAIL)
3832 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003833
3834 // remember the type and drop it
3835 --stack->ga_len;
3836 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3837
3838 end_idx = instr->ga_len;
3839 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3840
3841 // jump here from JUMP_IF_FALSE
3842 isn = ((isn_T *)instr->ga_data) + alt_idx;
3843 isn->isn_arg.jump.jump_where = instr->ga_len;
3844
3845 // Check for the ":".
3846 p = skipwhite(*arg);
3847 if (*p != ':')
3848 {
3849 emsg(_(e_missing_colon));
3850 return FAIL;
3851 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003852 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3853 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003854 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003855 return FAIL;
3856 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003857
3858 // evaluate the third expression
3859 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003860 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003861 return FAIL;
3862
Bram Moolenaara6d53682020-01-28 23:04:06 +01003863 if (compile_expr1(arg, cctx) == FAIL)
3864 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003865
3866 // If the types differ, the result has a more generic type.
3867 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003868 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003869
3870 // jump here from JUMP_ALWAYS
3871 isn = ((isn_T *)instr->ga_data) + end_idx;
3872 isn->isn_arg.jump.jump_where = instr->ga_len;
3873 }
3874 return OK;
3875}
3876
3877/*
3878 * compile "return [expr]"
3879 */
3880 static char_u *
3881compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3882{
3883 char_u *p = arg;
3884 garray_T *stack = &cctx->ctx_type_stack;
3885 type_T *stack_type;
3886
3887 if (*p != NUL && *p != '|' && *p != '\n')
3888 {
3889 // compile return argument into instructions
3890 if (compile_expr1(&p, cctx) == FAIL)
3891 return NULL;
3892
3893 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3894 if (set_return_type)
3895 cctx->ctx_ufunc->uf_ret_type = stack_type;
3896 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3897 == FAIL)
3898 return NULL;
3899 }
3900 else
3901 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003902 // "set_return_type" cannot be TRUE, only used for a lambda which
3903 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003904 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3905 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003906 {
3907 emsg(_("E1003: Missing return value"));
3908 return NULL;
3909 }
3910
3911 // No argument, return zero.
3912 generate_PUSHNR(cctx, 0);
3913 }
3914
3915 if (generate_instr(cctx, ISN_RETURN) == NULL)
3916 return NULL;
3917
3918 // "return val | endif" is possible
3919 return skipwhite(p);
3920}
3921
3922/*
3923 * Return the length of an assignment operator, or zero if there isn't one.
3924 */
3925 int
3926assignment_len(char_u *p, int *heredoc)
3927{
3928 if (*p == '=')
3929 {
3930 if (p[1] == '<' && p[2] == '<')
3931 {
3932 *heredoc = TRUE;
3933 return 3;
3934 }
3935 return 1;
3936 }
3937 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3938 return 2;
3939 if (STRNCMP(p, "..=", 3) == 0)
3940 return 3;
3941 return 0;
3942}
3943
3944// words that cannot be used as a variable
3945static char *reserved[] = {
3946 "true",
3947 "false",
3948 NULL
3949};
3950
3951/*
3952 * Get a line for "=<<".
3953 * Return a pointer to the line in allocated memory.
3954 * Return NULL for end-of-file or some error.
3955 */
3956 static char_u *
3957heredoc_getline(
3958 int c UNUSED,
3959 void *cookie,
3960 int indent UNUSED,
3961 int do_concat UNUSED)
3962{
3963 cctx_T *cctx = (cctx_T *)cookie;
3964
3965 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003966 {
3967 iemsg("Heredoc got to end");
3968 return NULL;
3969 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003970 ++cctx->ctx_lnum;
3971 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3972 [cctx->ctx_lnum]);
3973}
3974
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003975typedef enum {
3976 dest_local,
3977 dest_option,
3978 dest_env,
3979 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02003980 dest_buffer,
3981 dest_window,
3982 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003983 dest_vimvar,
3984 dest_script,
3985 dest_reg,
3986} assign_dest_T;
3987
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003988/*
3989 * compile "let var [= expr]", "const var = expr" and "var = expr"
3990 * "arg" points to "var".
3991 */
3992 static char_u *
3993compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3994{
3995 char_u *p;
3996 char_u *ret = NULL;
3997 int var_count = 0;
3998 int semicolon = 0;
3999 size_t varlen;
4000 garray_T *instr = &cctx->ctx_instr;
4001 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004002 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004003 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004004 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004005 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004006 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004007 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004008 int oplen = 0;
4009 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004010 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004011 lvar_T *lvar;
4012 char_u *name;
4013 char_u *sp;
4014 int has_type = FALSE;
4015 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4016 int instr_count = -1;
4017
4018 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4019 if (p == NULL)
4020 return NULL;
4021 if (var_count > 0)
4022 {
4023 // TODO: let [var, var] = list
4024 emsg("Cannot handle a list yet");
4025 return NULL;
4026 }
4027
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004028 // "a: type" is declaring variable "a" with a type, not "a:".
4029 if (is_decl && p == arg + 2 && p[-1] == ':')
4030 --p;
4031
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004032 varlen = p - arg;
4033 name = vim_strnsave(arg, (int)varlen);
4034 if (name == NULL)
4035 return NULL;
4036
Bram Moolenaar080457c2020-03-03 21:53:32 +01004037 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004038 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004039 if (*arg == '&')
4040 {
4041 int cc;
4042 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004043
Bram Moolenaar080457c2020-03-03 21:53:32 +01004044 dest = dest_option;
4045 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004046 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004047 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004048 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004049 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004050 if (is_decl)
4051 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004052 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004053 goto theend;
4054 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004055 p = arg;
4056 p = find_option_end(&p, &opt_flags);
4057 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004058 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004059 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004060 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004061 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004062 }
4063 cc = *p;
4064 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004065 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004066 *p = cc;
4067 if (opt_type == -3)
4068 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004069 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004070 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004071 }
4072 if (opt_type == -2 || opt_type == 0)
4073 type = &t_string;
4074 else
4075 type = &t_number; // both number and boolean option
4076 }
4077 else if (*arg == '$')
4078 {
4079 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004080 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004081 if (is_decl)
4082 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004083 semsg(_("E1065: Cannot declare an environment variable: %s"),
4084 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004085 goto theend;
4086 }
4087 }
4088 else if (*arg == '@')
4089 {
4090 if (!valid_yank_reg(arg[1], TRUE))
4091 {
4092 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004093 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004094 }
4095 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004096 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004097 if (is_decl)
4098 {
4099 semsg(_("E1066: Cannot declare a register: %s"), name);
4100 goto theend;
4101 }
4102 }
4103 else if (STRNCMP(arg, "g:", 2) == 0)
4104 {
4105 dest = dest_global;
4106 if (is_decl)
4107 {
4108 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4109 goto theend;
4110 }
4111 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004112 else if (STRNCMP(arg, "b:", 2) == 0)
4113 {
4114 dest = dest_buffer;
4115 if (is_decl)
4116 {
4117 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4118 goto theend;
4119 }
4120 }
4121 else if (STRNCMP(arg, "w:", 2) == 0)
4122 {
4123 dest = dest_window;
4124 if (is_decl)
4125 {
4126 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4127 goto theend;
4128 }
4129 }
4130 else if (STRNCMP(arg, "t:", 2) == 0)
4131 {
4132 dest = dest_tab;
4133 if (is_decl)
4134 {
4135 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4136 goto theend;
4137 }
4138 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004139 else if (STRNCMP(arg, "v:", 2) == 0)
4140 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004141 typval_T *vtv;
4142 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004143
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004144 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004145 if (vimvaridx < 0)
4146 {
4147 semsg(_(e_var_notfound), arg);
4148 goto theend;
4149 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004150 // We use the current value of "sandbox" here, is that OK?
4151 if (var_check_ro(di_flags, name, FALSE))
4152 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004153 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004154 vtv = get_vim_var_tv(vimvaridx);
4155 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004156 if (is_decl)
4157 {
4158 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4159 goto theend;
4160 }
4161 }
4162 else
4163 {
4164 for (idx = 0; reserved[idx] != NULL; ++idx)
4165 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004166 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004167 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004168 goto theend;
4169 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004170
4171 idx = lookup_local(arg, varlen, cctx);
4172 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004173 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004174 if (is_decl)
4175 {
4176 semsg(_("E1017: Variable already declared: %s"), name);
4177 goto theend;
4178 }
4179 else
4180 {
4181 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4182 if (lvar->lv_const)
4183 {
4184 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4185 goto theend;
4186 }
4187 }
4188 }
4189 else if (STRNCMP(arg, "s:", 2) == 0
4190 || lookup_script(arg, varlen) == OK
4191 || find_imported(arg, varlen, cctx) != NULL)
4192 {
4193 dest = dest_script;
4194 if (is_decl)
4195 {
4196 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004197 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004198 goto theend;
4199 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004200 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004201 else if (name[1] == ':' && name[2] != NUL)
4202 {
4203 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4204 goto theend;
4205 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004206 }
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"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004214 if (!VIM_ISWHITE(p[1]))
4215 {
4216 semsg(_(e_white_after), ":");
4217 goto theend;
4218 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004219 p = skipwhite(p + 1);
4220 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004221 has_type = TRUE;
4222 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004223 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004224 {
4225 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4226 type = lvar->lv_type;
4227 }
4228 }
4229
4230 sp = p;
4231 p = skipwhite(p);
4232 op = p;
4233 oplen = assignment_len(p, &heredoc);
4234 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4235 {
4236 char_u buf[4];
4237
4238 vim_strncpy(buf, op, oplen);
4239 semsg(_(e_white_both), buf);
4240 }
4241
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004242 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004243 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004244 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004245 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004246 goto theend;
4247 }
4248
Bram Moolenaar080457c2020-03-03 21:53:32 +01004249 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004250 {
4251 if (oplen > 1 && !heredoc)
4252 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004253 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004254 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4255 name);
4256 goto theend;
4257 }
4258
4259 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004260 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004261 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004262 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4263 if (idx < 0)
4264 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004265 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004266 }
4267
4268 if (heredoc)
4269 {
4270 list_T *l;
4271 listitem_T *li;
4272
4273 // [let] varname =<< [trim] {end}
4274 eap->getline = heredoc_getline;
4275 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004276 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004277
4278 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004279 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004280 {
4281 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4282 li->li_tv.vval.v_string = NULL;
4283 }
4284 generate_NEWLIST(cctx, l->lv_len);
4285 type = &t_list_string;
4286 list_free(l);
4287 p += STRLEN(p);
4288 }
4289 else if (oplen > 0)
4290 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004291 int r;
4292 type_T *stacktype;
4293 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004294
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004295 // for "+=", "*=", "..=" etc. first load the current value
4296 if (*op != '=')
4297 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004298 switch (dest)
4299 {
4300 case dest_option:
4301 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004302 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004303 break;
4304 case dest_global:
4305 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4306 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004307 case dest_buffer:
4308 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4309 break;
4310 case dest_window:
4311 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4312 break;
4313 case dest_tab:
4314 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4315 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004316 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004317 compile_load_scriptvar(cctx,
4318 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004319 break;
4320 case dest_env:
4321 // Include $ in the name here
4322 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4323 break;
4324 case dest_reg:
4325 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4326 break;
4327 case dest_vimvar:
4328 generate_LOADV(cctx, name + 2, TRUE);
4329 break;
4330 case dest_local:
4331 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4332 break;
4333 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004334 }
4335
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004336 // Compile the expression. Temporarily hide the new local variable
4337 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004338 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004339 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004340 instr_count = instr->ga_len;
4341 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004342 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004343 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004344 ++cctx->ctx_locals.ga_len;
4345 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004346 goto theend;
4347
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004348 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004349 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004350 stack = &cctx->ctx_type_stack;
4351 stacktype = stack->ga_len == 0 ? &t_void
4352 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4353 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004354 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004355 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4356 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004357 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004358 if (stacktype->tt_type == VAR_VOID)
4359 {
4360 emsg(_("E1031: Cannot use void value"));
4361 goto theend;
4362 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004363 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004364 {
4365 // An empty list or dict has a &t_void member, for a
4366 // variable that implies &t_any.
4367 if (stacktype == &t_list_empty)
4368 lvar->lv_type = &t_list_any;
4369 else if (stacktype == &t_dict_empty)
4370 lvar->lv_type = &t_dict_any;
4371 else
4372 lvar->lv_type = stacktype;
4373 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004374 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004375 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4376 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004377 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004378 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004379 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004380 }
4381 }
4382 else if (cmdidx == CMD_const)
4383 {
4384 emsg(_("E1021: const requires a value"));
4385 goto theend;
4386 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004387 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004388 {
4389 emsg(_("E1022: type or initialization required"));
4390 goto theend;
4391 }
4392 else
4393 {
4394 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004395 if (ga_grow(instr, 1) == FAIL)
4396 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004397 switch (type->tt_type)
4398 {
4399 case VAR_BOOL:
4400 generate_PUSHBOOL(cctx, VVAL_FALSE);
4401 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004402 case VAR_FLOAT:
4403#ifdef FEAT_FLOAT
4404 generate_PUSHF(cctx, 0.0);
4405#endif
4406 break;
4407 case VAR_STRING:
4408 generate_PUSHS(cctx, NULL);
4409 break;
4410 case VAR_BLOB:
4411 generate_PUSHBLOB(cctx, NULL);
4412 break;
4413 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004414 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004415 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004416 case VAR_LIST:
4417 generate_NEWLIST(cctx, 0);
4418 break;
4419 case VAR_DICT:
4420 generate_NEWDICT(cctx, 0);
4421 break;
4422 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004423 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004424 break;
4425 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004426 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004427 break;
4428 case VAR_NUMBER:
4429 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004430 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004431 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004432 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004433 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004434 generate_PUSHNR(cctx, 0);
4435 break;
4436 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004437 }
4438
4439 if (oplen > 0 && *op != '=')
4440 {
4441 type_T *expected = &t_number;
4442 garray_T *stack = &cctx->ctx_type_stack;
4443 type_T *stacktype;
4444
4445 // TODO: if type is known use float or any operation
4446
4447 if (*op == '.')
4448 expected = &t_string;
4449 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4450 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4451 goto theend;
4452
4453 if (*op == '.')
4454 generate_instr_drop(cctx, ISN_CONCAT, 1);
4455 else
4456 {
4457 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4458
4459 if (isn == NULL)
4460 goto theend;
4461 switch (*op)
4462 {
4463 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4464 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4465 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4466 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4467 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4468 }
4469 }
4470 }
4471
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004472 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004473 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004474 case dest_option:
4475 generate_STOREOPT(cctx, name + 1, opt_flags);
4476 break;
4477 case dest_global:
4478 // include g: with the name, easier to execute that way
4479 generate_STORE(cctx, ISN_STOREG, 0, name);
4480 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004481 case dest_buffer:
4482 // include b: with the name, easier to execute that way
4483 generate_STORE(cctx, ISN_STOREB, 0, name);
4484 break;
4485 case dest_window:
4486 // include w: with the name, easier to execute that way
4487 generate_STORE(cctx, ISN_STOREW, 0, name);
4488 break;
4489 case dest_tab:
4490 // include t: with the name, easier to execute that way
4491 generate_STORE(cctx, ISN_STORET, 0, name);
4492 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004493 case dest_env:
4494 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4495 break;
4496 case dest_reg:
4497 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4498 break;
4499 case dest_vimvar:
4500 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4501 break;
4502 case dest_script:
4503 {
4504 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4505 imported_T *import = NULL;
4506 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004507
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004508 if (name[1] != ':')
4509 {
4510 import = find_imported(name, 0, cctx);
4511 if (import != NULL)
4512 sid = import->imp_sid;
4513 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004514
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004515 idx = get_script_item_idx(sid, rawname, TRUE);
4516 // TODO: specific type
4517 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004518 {
4519 char_u *name_s = name;
4520
4521 // Include s: in the name for store_var()
4522 if (name[1] != ':')
4523 {
4524 int len = (int)STRLEN(name) + 3;
4525
4526 name_s = alloc(len);
4527 if (name_s == NULL)
4528 name_s = name;
4529 else
4530 vim_snprintf((char *)name_s, len, "s:%s", name);
4531 }
4532 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4533 if (name_s != name)
4534 vim_free(name_s);
4535 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004536 else
4537 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4538 sid, idx, &t_any);
4539 }
4540 break;
4541 case dest_local:
4542 {
4543 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004544
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004545 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4546 // into ISN_STORENR
4547 if (instr->ga_len == instr_count + 1
4548 && isn->isn_type == ISN_PUSHNR)
4549 {
4550 varnumber_T val = isn->isn_arg.number;
4551 garray_T *stack = &cctx->ctx_type_stack;
4552
4553 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004554 isn->isn_arg.storenr.stnr_idx = idx;
4555 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004556 if (stack->ga_len > 0)
4557 --stack->ga_len;
4558 }
4559 else
4560 generate_STORE(cctx, ISN_STORE, idx, NULL);
4561 }
4562 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004563 }
4564 ret = p;
4565
4566theend:
4567 vim_free(name);
4568 return ret;
4569}
4570
4571/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004572 * Check if "name" can be "unlet".
4573 */
4574 int
4575check_vim9_unlet(char_u *name)
4576{
4577 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
4578 {
4579 semsg(_("E1081: Cannot unlet %s"), name);
4580 return FAIL;
4581 }
4582 return OK;
4583}
4584
4585/*
4586 * Callback passed to ex_unletlock().
4587 */
4588 static int
4589compile_unlet(
4590 lval_T *lvp,
4591 char_u *name_end,
4592 exarg_T *eap,
4593 int deep UNUSED,
4594 void *coookie)
4595{
4596 cctx_T *cctx = coookie;
4597
4598 if (lvp->ll_tv == NULL)
4599 {
4600 char_u *p = lvp->ll_name;
4601 int cc = *name_end;
4602 int ret = OK;
4603
4604 // Normal name. Only supports g:, w:, t: and b: namespaces.
4605 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004606 if (*p == '$')
4607 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
4608 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004609 ret = FAIL;
4610 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004611 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004612
4613 *name_end = cc;
4614 return ret;
4615 }
4616
4617 // TODO: unlet {list}[idx]
4618 // TODO: unlet {dict}[key]
4619 emsg("Sorry, :unlet not fully implemented yet");
4620 return FAIL;
4621}
4622
4623/*
4624 * compile "unlet var", "lock var" and "unlock var"
4625 * "arg" points to "var".
4626 */
4627 static char_u *
4628compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
4629{
4630 char_u *p = arg;
4631
4632 if (eap->cmdidx != CMD_unlet)
4633 {
4634 emsg("Sorry, :lock and unlock not implemented yet");
4635 return NULL;
4636 }
4637
4638 if (*p == '!')
4639 {
4640 p = skipwhite(p + 1);
4641 eap->forceit = TRUE;
4642 }
4643
4644 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
4645 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
4646}
4647
4648/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004649 * Compile an :import command.
4650 */
4651 static char_u *
4652compile_import(char_u *arg, cctx_T *cctx)
4653{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004654 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004655}
4656
4657/*
4658 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4659 */
4660 static int
4661compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4662{
4663 garray_T *instr = &cctx->ctx_instr;
4664 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4665
4666 if (endlabel == NULL)
4667 return FAIL;
4668 endlabel->el_next = *el;
4669 *el = endlabel;
4670 endlabel->el_end_label = instr->ga_len;
4671
4672 generate_JUMP(cctx, when, 0);
4673 return OK;
4674}
4675
4676 static void
4677compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4678{
4679 garray_T *instr = &cctx->ctx_instr;
4680
4681 while (*el != NULL)
4682 {
4683 endlabel_T *cur = (*el);
4684 isn_T *isn;
4685
4686 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4687 isn->isn_arg.jump.jump_where = instr->ga_len;
4688 *el = cur->el_next;
4689 vim_free(cur);
4690 }
4691}
4692
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004693 static void
4694compile_free_jump_to_end(endlabel_T **el)
4695{
4696 while (*el != NULL)
4697 {
4698 endlabel_T *cur = (*el);
4699
4700 *el = cur->el_next;
4701 vim_free(cur);
4702 }
4703}
4704
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004705/*
4706 * Create a new scope and set up the generic items.
4707 */
4708 static scope_T *
4709new_scope(cctx_T *cctx, scopetype_T type)
4710{
4711 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4712
4713 if (scope == NULL)
4714 return NULL;
4715 scope->se_outer = cctx->ctx_scope;
4716 cctx->ctx_scope = scope;
4717 scope->se_type = type;
4718 scope->se_local_count = cctx->ctx_locals.ga_len;
4719 return scope;
4720}
4721
4722/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004723 * Free the current scope and go back to the outer scope.
4724 */
4725 static void
4726drop_scope(cctx_T *cctx)
4727{
4728 scope_T *scope = cctx->ctx_scope;
4729
4730 if (scope == NULL)
4731 {
4732 iemsg("calling drop_scope() without a scope");
4733 return;
4734 }
4735 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004736 switch (scope->se_type)
4737 {
4738 case IF_SCOPE:
4739 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4740 case FOR_SCOPE:
4741 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4742 case WHILE_SCOPE:
4743 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4744 case TRY_SCOPE:
4745 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4746 case NO_SCOPE:
4747 case BLOCK_SCOPE:
4748 break;
4749 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004750 vim_free(scope);
4751}
4752
4753/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004754 * Evaluate an expression that is a constant:
4755 * has(arg)
4756 *
4757 * Also handle:
4758 * ! in front logical NOT
4759 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004760 * Return FAIL if the expression is not a constant.
4761 */
4762 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004763evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004764{
4765 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004766 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004767 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004768
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004769 /*
4770 * Skip '!' characters. They are handled later.
4771 */
4772 start_leader = *arg;
4773 while (**arg == '!')
4774 *arg = skipwhite(*arg + 1);
4775 end_leader = *arg;
4776
4777 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004778 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004779 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004780 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4781 {
4782 tv->v_type = VAR_SPECIAL;
4783 tv->vval.v_number = VVAL_TRUE;
4784 *arg += 4;
4785 return OK;
4786 }
4787 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4788 {
4789 tv->v_type = VAR_SPECIAL;
4790 tv->vval.v_number = VVAL_FALSE;
4791 *arg += 5;
4792 return OK;
4793 }
4794
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004795 if (STRNCMP("has(", *arg, 4) == 0)
4796 {
4797 has_call = TRUE;
4798 *arg = skipwhite(*arg + 4);
4799 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004800
4801 if (**arg == '"')
4802 {
4803 if (get_string_tv(arg, tv, TRUE) == FAIL)
4804 return FAIL;
4805 }
4806 else if (**arg == '\'')
4807 {
4808 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4809 return FAIL;
4810 }
4811 else
4812 return FAIL;
4813
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004814 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004815 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004816 *arg = skipwhite(*arg);
4817 if (**arg != ')')
4818 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004819 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004820
4821 argvars[0] = *tv;
4822 argvars[1].v_type = VAR_UNKNOWN;
4823 tv->v_type = VAR_NUMBER;
4824 tv->vval.v_number = 0;
4825 f_has(argvars, tv);
4826 clear_tv(&argvars[0]);
4827
4828 while (start_leader < end_leader)
4829 {
4830 if (*start_leader == '!')
4831 tv->vval.v_number = !tv->vval.v_number;
4832 ++start_leader;
4833 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004834 }
4835
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004836 return OK;
4837}
4838
Bram Moolenaar080457c2020-03-03 21:53:32 +01004839 static int
4840evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4841{
4842 exptype_T type = EXPR_UNKNOWN;
4843 char_u *p;
4844 int len = 2;
4845 int type_is = FALSE;
4846
4847 // get the first variable
4848 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4849 return FAIL;
4850
4851 p = skipwhite(*arg);
4852 type = get_compare_type(p, &len, &type_is);
4853
4854 /*
4855 * If there is a comparative operator, use it.
4856 */
4857 if (type != EXPR_UNKNOWN)
4858 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004859 typval_T tv2;
4860 char_u *s1, *s2;
4861 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4862 int n;
4863
4864 // TODO: Only string == string is supported now
4865 if (tv->v_type != VAR_STRING)
4866 return FAIL;
4867 if (type != EXPR_EQUAL)
4868 return FAIL;
4869
4870 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004871 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004872 *arg = skipwhite(p + len);
4873 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4874 || tv2.v_type != VAR_STRING)
4875 {
4876 clear_tv(&tv2);
4877 return FAIL;
4878 }
4879 s1 = tv_get_string_buf(tv, buf1);
4880 s2 = tv_get_string_buf(&tv2, buf2);
4881 n = STRCMP(s1, s2);
4882 clear_tv(tv);
4883 clear_tv(&tv2);
4884 tv->v_type = VAR_BOOL;
4885 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004886 }
4887
4888 return OK;
4889}
4890
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004891static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4892
4893/*
4894 * Compile constant || or &&.
4895 */
4896 static int
4897evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4898{
4899 char_u *p = skipwhite(*arg);
4900 int opchar = *op;
4901
4902 if (p[0] == opchar && p[1] == opchar)
4903 {
4904 int val = tv2bool(tv);
4905
4906 /*
4907 * Repeat until there is no following "||" or "&&"
4908 */
4909 while (p[0] == opchar && p[1] == opchar)
4910 {
4911 typval_T tv2;
4912
4913 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4914 return FAIL;
4915
4916 // eval the next expression
4917 *arg = skipwhite(p + 2);
4918 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004919 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004920 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004921 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004922 {
4923 clear_tv(&tv2);
4924 return FAIL;
4925 }
4926 if ((opchar == '&') == val)
4927 {
4928 // false || tv2 or true && tv2: use tv2
4929 clear_tv(tv);
4930 *tv = tv2;
4931 val = tv2bool(tv);
4932 }
4933 else
4934 clear_tv(&tv2);
4935 p = skipwhite(*arg);
4936 }
4937 }
4938
4939 return OK;
4940}
4941
4942/*
4943 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4944 * Return FAIL if the expression is not a constant.
4945 */
4946 static int
4947evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4948{
4949 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004950 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004951 return FAIL;
4952
4953 // || and && work almost the same
4954 return evaluate_const_and_or(arg, cctx, "&&", tv);
4955}
4956
4957/*
4958 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4959 * Return FAIL if the expression is not a constant.
4960 */
4961 static int
4962evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4963{
4964 // evaluate the first expression
4965 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4966 return FAIL;
4967
4968 // || and && work almost the same
4969 return evaluate_const_and_or(arg, cctx, "||", tv);
4970}
4971
4972/*
4973 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4974 * E.g. for "has('feature')".
4975 * This does not produce error messages. "tv" should be cleared afterwards.
4976 * Return FAIL if the expression is not a constant.
4977 */
4978 static int
4979evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4980{
4981 char_u *p;
4982
4983 // evaluate the first expression
4984 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4985 return FAIL;
4986
4987 p = skipwhite(*arg);
4988 if (*p == '?')
4989 {
4990 int val = tv2bool(tv);
4991 typval_T tv2;
4992
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004993 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004994 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4995 return FAIL;
4996
4997 // evaluate the second expression; any type is accepted
4998 clear_tv(tv);
4999 *arg = skipwhite(p + 1);
5000 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
5001 return FAIL;
5002
5003 // Check for the ":".
5004 p = skipwhite(*arg);
5005 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5006 return FAIL;
5007
5008 // evaluate the third expression
5009 *arg = skipwhite(p + 1);
5010 tv2.v_type = VAR_UNKNOWN;
5011 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
5012 {
5013 clear_tv(&tv2);
5014 return FAIL;
5015 }
5016 if (val)
5017 {
5018 // use the expr after "?"
5019 clear_tv(&tv2);
5020 }
5021 else
5022 {
5023 // use the expr after ":"
5024 clear_tv(tv);
5025 *tv = tv2;
5026 }
5027 }
5028 return OK;
5029}
5030
5031/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005032 * compile "if expr"
5033 *
5034 * "if expr" Produces instructions:
5035 * EVAL expr Push result of "expr"
5036 * JUMP_IF_FALSE end
5037 * ... body ...
5038 * end:
5039 *
5040 * "if expr | else" Produces instructions:
5041 * EVAL expr Push result of "expr"
5042 * JUMP_IF_FALSE else
5043 * ... body ...
5044 * JUMP_ALWAYS end
5045 * else:
5046 * ... body ...
5047 * end:
5048 *
5049 * "if expr1 | elseif expr2 | else" Produces instructions:
5050 * EVAL expr Push result of "expr"
5051 * JUMP_IF_FALSE elseif
5052 * ... body ...
5053 * JUMP_ALWAYS end
5054 * elseif:
5055 * EVAL expr Push result of "expr"
5056 * JUMP_IF_FALSE else
5057 * ... body ...
5058 * JUMP_ALWAYS end
5059 * else:
5060 * ... body ...
5061 * end:
5062 */
5063 static char_u *
5064compile_if(char_u *arg, cctx_T *cctx)
5065{
5066 char_u *p = arg;
5067 garray_T *instr = &cctx->ctx_instr;
5068 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005069 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005070
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005071 // compile "expr"; if we know it evaluates to FALSE skip the block
5072 tv.v_type = VAR_UNKNOWN;
5073 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5074 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5075 else
5076 cctx->ctx_skip = MAYBE;
5077 clear_tv(&tv);
5078 if (cctx->ctx_skip == MAYBE)
5079 {
5080 p = arg;
5081 if (compile_expr1(&p, cctx) == FAIL)
5082 return NULL;
5083 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005084
5085 scope = new_scope(cctx, IF_SCOPE);
5086 if (scope == NULL)
5087 return NULL;
5088
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005089 if (cctx->ctx_skip == MAYBE)
5090 {
5091 // "where" is set when ":elseif", "else" or ":endif" is found
5092 scope->se_u.se_if.is_if_label = instr->ga_len;
5093 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5094 }
5095 else
5096 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005097
5098 return p;
5099}
5100
5101 static char_u *
5102compile_elseif(char_u *arg, cctx_T *cctx)
5103{
5104 char_u *p = arg;
5105 garray_T *instr = &cctx->ctx_instr;
5106 isn_T *isn;
5107 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005108 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005109
5110 if (scope == NULL || scope->se_type != IF_SCOPE)
5111 {
5112 emsg(_(e_elseif_without_if));
5113 return NULL;
5114 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005115 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005116
Bram Moolenaar158906c2020-02-06 20:39:45 +01005117 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005118 {
5119 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005120 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005121 return NULL;
5122 // previous "if" or "elseif" jumps here
5123 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5124 isn->isn_arg.jump.jump_where = instr->ga_len;
5125 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005126
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005127 // compile "expr"; if we know it evaluates to FALSE skip the block
5128 tv.v_type = VAR_UNKNOWN;
5129 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5130 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5131 else
5132 cctx->ctx_skip = MAYBE;
5133 clear_tv(&tv);
5134 if (cctx->ctx_skip == MAYBE)
5135 {
5136 p = arg;
5137 if (compile_expr1(&p, cctx) == FAIL)
5138 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005139
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005140 // "where" is set when ":elseif", "else" or ":endif" is found
5141 scope->se_u.se_if.is_if_label = instr->ga_len;
5142 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5143 }
5144 else
5145 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005146
5147 return p;
5148}
5149
5150 static char_u *
5151compile_else(char_u *arg, cctx_T *cctx)
5152{
5153 char_u *p = arg;
5154 garray_T *instr = &cctx->ctx_instr;
5155 isn_T *isn;
5156 scope_T *scope = cctx->ctx_scope;
5157
5158 if (scope == NULL || scope->se_type != IF_SCOPE)
5159 {
5160 emsg(_(e_else_without_if));
5161 return NULL;
5162 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005163 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005164
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005165 // jump from previous block to the end, unless the else block is empty
5166 if (cctx->ctx_skip == MAYBE)
5167 {
5168 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005169 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005170 return NULL;
5171 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005172
Bram Moolenaar158906c2020-02-06 20:39:45 +01005173 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005174 {
5175 if (scope->se_u.se_if.is_if_label >= 0)
5176 {
5177 // previous "if" or "elseif" jumps here
5178 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5179 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005180 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005181 }
5182 }
5183
5184 if (cctx->ctx_skip != MAYBE)
5185 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005186
5187 return p;
5188}
5189
5190 static char_u *
5191compile_endif(char_u *arg, cctx_T *cctx)
5192{
5193 scope_T *scope = cctx->ctx_scope;
5194 ifscope_T *ifscope;
5195 garray_T *instr = &cctx->ctx_instr;
5196 isn_T *isn;
5197
5198 if (scope == NULL || scope->se_type != IF_SCOPE)
5199 {
5200 emsg(_(e_endif_without_if));
5201 return NULL;
5202 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005203 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005204 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005205
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005206 if (scope->se_u.se_if.is_if_label >= 0)
5207 {
5208 // previous "if" or "elseif" jumps here
5209 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5210 isn->isn_arg.jump.jump_where = instr->ga_len;
5211 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005212 // Fill in the "end" label in jumps at the end of the blocks.
5213 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005214 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005215
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005216 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005217 return arg;
5218}
5219
5220/*
5221 * compile "for var in expr"
5222 *
5223 * Produces instructions:
5224 * PUSHNR -1
5225 * STORE loop-idx Set index to -1
5226 * EVAL expr Push result of "expr"
5227 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5228 * - if beyond end, jump to "end"
5229 * - otherwise get item from list and push it
5230 * STORE var Store item in "var"
5231 * ... body ...
5232 * JUMP top Jump back to repeat
5233 * end: DROP Drop the result of "expr"
5234 *
5235 */
5236 static char_u *
5237compile_for(char_u *arg, cctx_T *cctx)
5238{
5239 char_u *p;
5240 size_t varlen;
5241 garray_T *instr = &cctx->ctx_instr;
5242 garray_T *stack = &cctx->ctx_type_stack;
5243 scope_T *scope;
5244 int loop_idx; // index of loop iteration variable
5245 int var_idx; // index of "var"
5246 type_T *vartype;
5247
5248 // TODO: list of variables: "for [key, value] in dict"
5249 // parse "var"
5250 for (p = arg; eval_isnamec1(*p); ++p)
5251 ;
5252 varlen = p - arg;
5253 var_idx = lookup_local(arg, varlen, cctx);
5254 if (var_idx >= 0)
5255 {
5256 semsg(_("E1023: variable already defined: %s"), arg);
5257 return NULL;
5258 }
5259
5260 // consume "in"
5261 p = skipwhite(p);
5262 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5263 {
5264 emsg(_(e_missing_in));
5265 return NULL;
5266 }
5267 p = skipwhite(p + 2);
5268
5269
5270 scope = new_scope(cctx, FOR_SCOPE);
5271 if (scope == NULL)
5272 return NULL;
5273
5274 // Reserve a variable to store the loop iteration counter.
5275 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5276 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005277 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005278 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005279 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005280 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005281 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005282
5283 // Reserve a variable to store "var"
5284 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5285 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005286 {
5287 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005288 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005289 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005290
5291 generate_STORENR(cctx, loop_idx, -1);
5292
5293 // compile "expr", it remains on the stack until "endfor"
5294 arg = p;
5295 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005296 {
5297 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005298 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005299 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005300
5301 // now we know the type of "var"
5302 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5303 if (vartype->tt_type != VAR_LIST)
5304 {
5305 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005306 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005307 return NULL;
5308 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005309 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005310 {
5311 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
5312
5313 lvar->lv_type = vartype->tt_member;
5314 }
5315
5316 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005317 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005318
5319 generate_FOR(cctx, loop_idx);
5320 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
5321
5322 return arg;
5323}
5324
5325/*
5326 * compile "endfor"
5327 */
5328 static char_u *
5329compile_endfor(char_u *arg, cctx_T *cctx)
5330{
5331 garray_T *instr = &cctx->ctx_instr;
5332 scope_T *scope = cctx->ctx_scope;
5333 forscope_T *forscope;
5334 isn_T *isn;
5335
5336 if (scope == NULL || scope->se_type != FOR_SCOPE)
5337 {
5338 emsg(_(e_for));
5339 return NULL;
5340 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005341 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005342 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005343 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005344
5345 // At end of ":for" scope jump back to the FOR instruction.
5346 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5347
5348 // Fill in the "end" label in the FOR statement so it can jump here
5349 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5350 isn->isn_arg.forloop.for_end = instr->ga_len;
5351
5352 // Fill in the "end" label any BREAK statements
5353 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5354
5355 // Below the ":for" scope drop the "expr" list from the stack.
5356 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5357 return NULL;
5358
5359 vim_free(scope);
5360
5361 return arg;
5362}
5363
5364/*
5365 * compile "while expr"
5366 *
5367 * Produces instructions:
5368 * top: EVAL expr Push result of "expr"
5369 * JUMP_IF_FALSE end jump if false
5370 * ... body ...
5371 * JUMP top Jump back to repeat
5372 * end:
5373 *
5374 */
5375 static char_u *
5376compile_while(char_u *arg, cctx_T *cctx)
5377{
5378 char_u *p = arg;
5379 garray_T *instr = &cctx->ctx_instr;
5380 scope_T *scope;
5381
5382 scope = new_scope(cctx, WHILE_SCOPE);
5383 if (scope == NULL)
5384 return NULL;
5385
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005386 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005387
5388 // compile "expr"
5389 if (compile_expr1(&p, cctx) == FAIL)
5390 return NULL;
5391
5392 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005393 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005394 JUMP_IF_FALSE, cctx) == FAIL)
5395 return FAIL;
5396
5397 return p;
5398}
5399
5400/*
5401 * compile "endwhile"
5402 */
5403 static char_u *
5404compile_endwhile(char_u *arg, cctx_T *cctx)
5405{
5406 scope_T *scope = cctx->ctx_scope;
5407
5408 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5409 {
5410 emsg(_(e_while));
5411 return NULL;
5412 }
5413 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005414 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005415
5416 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005417 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005418
5419 // Fill in the "end" label in the WHILE statement so it can jump here.
5420 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005421 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005422
5423 vim_free(scope);
5424
5425 return arg;
5426}
5427
5428/*
5429 * compile "continue"
5430 */
5431 static char_u *
5432compile_continue(char_u *arg, cctx_T *cctx)
5433{
5434 scope_T *scope = cctx->ctx_scope;
5435
5436 for (;;)
5437 {
5438 if (scope == NULL)
5439 {
5440 emsg(_(e_continue));
5441 return NULL;
5442 }
5443 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5444 break;
5445 scope = scope->se_outer;
5446 }
5447
5448 // Jump back to the FOR or WHILE instruction.
5449 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005450 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5451 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005452 return arg;
5453}
5454
5455/*
5456 * compile "break"
5457 */
5458 static char_u *
5459compile_break(char_u *arg, cctx_T *cctx)
5460{
5461 scope_T *scope = cctx->ctx_scope;
5462 endlabel_T **el;
5463
5464 for (;;)
5465 {
5466 if (scope == NULL)
5467 {
5468 emsg(_(e_break));
5469 return NULL;
5470 }
5471 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5472 break;
5473 scope = scope->se_outer;
5474 }
5475
5476 // Jump to the end of the FOR or WHILE loop.
5477 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005478 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005479 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005480 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005481 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5482 return FAIL;
5483
5484 return arg;
5485}
5486
5487/*
5488 * compile "{" start of block
5489 */
5490 static char_u *
5491compile_block(char_u *arg, cctx_T *cctx)
5492{
5493 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5494 return NULL;
5495 return skipwhite(arg + 1);
5496}
5497
5498/*
5499 * compile end of block: drop one scope
5500 */
5501 static void
5502compile_endblock(cctx_T *cctx)
5503{
5504 scope_T *scope = cctx->ctx_scope;
5505
5506 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005507 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005508 vim_free(scope);
5509}
5510
5511/*
5512 * compile "try"
5513 * Creates a new scope for the try-endtry, pointing to the first catch and
5514 * finally.
5515 * Creates another scope for the "try" block itself.
5516 * TRY instruction sets up exception handling at runtime.
5517 *
5518 * "try"
5519 * TRY -> catch1, -> finally push trystack entry
5520 * ... try block
5521 * "throw {exception}"
5522 * EVAL {exception}
5523 * THROW create exception
5524 * ... try block
5525 * " catch {expr}"
5526 * JUMP -> finally
5527 * catch1: PUSH exeception
5528 * EVAL {expr}
5529 * MATCH
5530 * JUMP nomatch -> catch2
5531 * CATCH remove exception
5532 * ... catch block
5533 * " catch"
5534 * JUMP -> finally
5535 * catch2: CATCH remove exception
5536 * ... catch block
5537 * " finally"
5538 * finally:
5539 * ... finally block
5540 * " endtry"
5541 * ENDTRY pop trystack entry, may rethrow
5542 */
5543 static char_u *
5544compile_try(char_u *arg, cctx_T *cctx)
5545{
5546 garray_T *instr = &cctx->ctx_instr;
5547 scope_T *try_scope;
5548 scope_T *scope;
5549
5550 // scope that holds the jumps that go to catch/finally/endtry
5551 try_scope = new_scope(cctx, TRY_SCOPE);
5552 if (try_scope == NULL)
5553 return NULL;
5554
5555 // "catch" is set when the first ":catch" is found.
5556 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005557 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005558 if (generate_instr(cctx, ISN_TRY) == NULL)
5559 return NULL;
5560
5561 // scope for the try block itself
5562 scope = new_scope(cctx, BLOCK_SCOPE);
5563 if (scope == NULL)
5564 return NULL;
5565
5566 return arg;
5567}
5568
5569/*
5570 * compile "catch {expr}"
5571 */
5572 static char_u *
5573compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5574{
5575 scope_T *scope = cctx->ctx_scope;
5576 garray_T *instr = &cctx->ctx_instr;
5577 char_u *p;
5578 isn_T *isn;
5579
5580 // end block scope from :try or :catch
5581 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5582 compile_endblock(cctx);
5583 scope = cctx->ctx_scope;
5584
5585 // Error if not in a :try scope
5586 if (scope == NULL || scope->se_type != TRY_SCOPE)
5587 {
5588 emsg(_(e_catch));
5589 return NULL;
5590 }
5591
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005592 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005593 {
5594 emsg(_("E1033: catch unreachable after catch-all"));
5595 return NULL;
5596 }
5597
5598 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005599 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005600 JUMP_ALWAYS, cctx) == FAIL)
5601 return NULL;
5602
5603 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005604 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005605 if (isn->isn_arg.try.try_catch == 0)
5606 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005607 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005608 {
5609 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005610 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005611 isn->isn_arg.jump.jump_where = instr->ga_len;
5612 }
5613
5614 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005615 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005616 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005617 scope->se_u.se_try.ts_caught_all = TRUE;
5618 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005619 }
5620 else
5621 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005622 char_u *end;
5623 char_u *pat;
5624 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005625 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005626 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005627
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005628 // Push v:exception, push {expr} and MATCH
5629 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5630
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005631 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005632 if (*end != *p)
5633 {
5634 semsg(_("E1067: Separator mismatch: %s"), p);
5635 vim_free(tofree);
5636 return FAIL;
5637 }
5638 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005639 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005640 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005641 len = (int)(end - tofree);
5642 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005643 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005644 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005645 if (pat == NULL)
5646 return FAIL;
5647 if (generate_PUSHS(cctx, pat) == FAIL)
5648 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005649
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005650 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5651 return NULL;
5652
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005653 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005654 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5655 return NULL;
5656 }
5657
5658 if (generate_instr(cctx, ISN_CATCH) == NULL)
5659 return NULL;
5660
5661 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5662 return NULL;
5663 return p;
5664}
5665
5666 static char_u *
5667compile_finally(char_u *arg, cctx_T *cctx)
5668{
5669 scope_T *scope = cctx->ctx_scope;
5670 garray_T *instr = &cctx->ctx_instr;
5671 isn_T *isn;
5672
5673 // end block scope from :try or :catch
5674 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5675 compile_endblock(cctx);
5676 scope = cctx->ctx_scope;
5677
5678 // Error if not in a :try scope
5679 if (scope == NULL || scope->se_type != TRY_SCOPE)
5680 {
5681 emsg(_(e_finally));
5682 return NULL;
5683 }
5684
5685 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005686 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005687 if (isn->isn_arg.try.try_finally != 0)
5688 {
5689 emsg(_(e_finally_dup));
5690 return NULL;
5691 }
5692
5693 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005694 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005695
Bram Moolenaar585fea72020-04-02 22:33:21 +02005696 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005697 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005698 {
5699 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005700 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005701 isn->isn_arg.jump.jump_where = instr->ga_len;
5702 }
5703
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005704 // TODO: set index in ts_finally_label jumps
5705
5706 return arg;
5707}
5708
5709 static char_u *
5710compile_endtry(char_u *arg, cctx_T *cctx)
5711{
5712 scope_T *scope = cctx->ctx_scope;
5713 garray_T *instr = &cctx->ctx_instr;
5714 isn_T *isn;
5715
5716 // end block scope from :catch or :finally
5717 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5718 compile_endblock(cctx);
5719 scope = cctx->ctx_scope;
5720
5721 // Error if not in a :try scope
5722 if (scope == NULL || scope->se_type != TRY_SCOPE)
5723 {
5724 if (scope == NULL)
5725 emsg(_(e_no_endtry));
5726 else if (scope->se_type == WHILE_SCOPE)
5727 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005728 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005729 emsg(_(e_endfor));
5730 else
5731 emsg(_(e_endif));
5732 return NULL;
5733 }
5734
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005735 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005736 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5737 {
5738 emsg(_("E1032: missing :catch or :finally"));
5739 return NULL;
5740 }
5741
5742 // Fill in the "end" label in jumps at the end of the blocks, if not done
5743 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005744 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005745
5746 // End :catch or :finally scope: set value in ISN_TRY instruction
5747 if (isn->isn_arg.try.try_finally == 0)
5748 isn->isn_arg.try.try_finally = instr->ga_len;
5749 compile_endblock(cctx);
5750
5751 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5752 return NULL;
5753 return arg;
5754}
5755
5756/*
5757 * compile "throw {expr}"
5758 */
5759 static char_u *
5760compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5761{
5762 char_u *p = skipwhite(arg);
5763
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005764 if (compile_expr1(&p, cctx) == FAIL)
5765 return NULL;
5766 if (may_generate_2STRING(-1, cctx) == FAIL)
5767 return NULL;
5768 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5769 return NULL;
5770
5771 return p;
5772}
5773
5774/*
5775 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005776 * compile "echomsg expr"
5777 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01005778 * compile "execute expr"
5779 */
5780 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005781compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01005782{
5783 char_u *p = arg;
5784 int count = 0;
5785
5786 for (;;)
5787 {
5788 if (compile_expr1(&p, cctx) == FAIL)
5789 return NULL;
5790 ++count;
5791 p = skipwhite(p);
5792 if (ends_excmd(*p))
5793 break;
5794 }
5795
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005796 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
5797 generate_ECHO(cctx, cmdidx == CMD_echo, count);
5798 else if (cmdidx == CMD_execute)
5799 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
5800 else if (cmdidx == CMD_echomsg)
5801 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
5802 else
5803 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005804 return p;
5805}
5806
5807/*
5808 * After ex_function() has collected all the function lines: parse and compile
5809 * the lines into instructions.
5810 * Adds the function to "def_functions".
5811 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5812 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005813 * This can be used recursively through compile_lambda(), which may reallocate
5814 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005815 */
5816 void
5817compile_def_function(ufunc_T *ufunc, int set_return_type)
5818{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005819 char_u *line = NULL;
5820 char_u *p;
5821 exarg_T ea;
5822 char *errormsg = NULL; // error message
5823 int had_return = FALSE;
5824 cctx_T cctx;
5825 garray_T *instr;
5826 int called_emsg_before = called_emsg;
5827 int ret = FAIL;
5828 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005829 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005830
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005831 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005832 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005833
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005834 if (ufunc->uf_dfunc_idx >= 0)
5835 {
5836 // Redefining a function that was compiled before.
5837 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5838
5839 // Free old instructions.
5840 delete_def_function_contents(dfunc);
5841 }
5842 else
5843 {
5844 // Add the function to "def_functions".
5845 if (ga_grow(&def_functions, 1) == FAIL)
5846 return;
5847 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005848 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005849 dfunc->df_idx = def_functions.ga_len;
5850 ufunc->uf_dfunc_idx = dfunc->df_idx;
5851 dfunc->df_ufunc = ufunc;
5852 ++def_functions.ga_len;
5853 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005854 }
5855
Bram Moolenaara80faa82020-04-12 19:37:17 +02005856 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005857 cctx.ctx_ufunc = ufunc;
5858 cctx.ctx_lnum = -1;
5859 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5860 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5861 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5862 cctx.ctx_type_list = &ufunc->uf_type_list;
5863 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5864 instr = &cctx.ctx_instr;
5865
5866 // Most modern script version.
5867 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5868
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005869 if (ufunc->uf_def_args.ga_len > 0)
5870 {
5871 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005872 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005873 int i;
5874 char_u *arg;
5875 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5876
5877 // Produce instructions for the default values of optional arguments.
5878 // Store the instruction index in uf_def_arg_idx[] so that we know
5879 // where to start when the function is called, depending on the number
5880 // of arguments.
5881 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5882 if (ufunc->uf_def_arg_idx == NULL)
5883 goto erret;
5884 for (i = 0; i < count; ++i)
5885 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005886 garray_T *stack = &cctx.ctx_type_stack;
5887 type_T *val_type;
5888 int arg_idx = first_def_arg + i;
5889
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005890 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5891 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005892 if (compile_expr1(&arg, &cctx) == FAIL)
5893 goto erret;
5894
5895 // If no type specified use the type of the default value.
5896 // Otherwise check that the default value type matches the
5897 // specified type.
5898 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5899 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
5900 ufunc->uf_arg_types[arg_idx] = val_type;
5901 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
5902 == FAIL)
5903 {
5904 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
5905 arg_idx + 1);
5906 goto erret;
5907 }
5908
5909 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005910 goto erret;
5911 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005912 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5913 }
5914
5915 /*
5916 * Loop over all the lines of the function and generate instructions.
5917 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005918 for (;;)
5919 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005920 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005921
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005922 // Bail out on the first error to avoid a flood of errors and report
5923 // the right line number when inside try/catch.
5924 if (emsg_before != called_emsg)
5925 goto erret;
5926
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005927 if (line != NULL && *line == '|')
5928 // the line continues after a '|'
5929 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02005930 else if (line != NULL && *line != NUL
5931 && !(*line == '#' && (line == cctx.ctx_line_start
5932 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005933 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005934 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005935 goto erret;
5936 }
5937 else
5938 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02005939 line = next_line_from_context(&cctx);
5940 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005941 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005942 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005943 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005944 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005945
5946 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005947 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005948 ea.cmdlinep = &line;
5949 ea.cmd = skipwhite(line);
5950
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005951 // Some things can be recognized by the first character.
5952 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005953 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005954 case '#':
5955 // "#" starts a comment, but not "#{".
5956 if (ea.cmd[1] != '{')
5957 {
5958 line = (char_u *)"";
5959 continue;
5960 }
5961 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005962
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005963 case '}':
5964 {
5965 // "}" ends a block scope
5966 scopetype_T stype = cctx.ctx_scope == NULL
5967 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005968
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005969 if (stype == BLOCK_SCOPE)
5970 {
5971 compile_endblock(&cctx);
5972 line = ea.cmd;
5973 }
5974 else
5975 {
5976 emsg(_("E1025: using } outside of a block scope"));
5977 goto erret;
5978 }
5979 if (line != NULL)
5980 line = skipwhite(ea.cmd + 1);
5981 continue;
5982 }
5983
5984 case '{':
5985 // "{" starts a block scope
5986 // "{'a': 1}->func() is something else
5987 if (ends_excmd(*skipwhite(ea.cmd + 1)))
5988 {
5989 line = compile_block(ea.cmd, &cctx);
5990 continue;
5991 }
5992 break;
5993
5994 case ':':
5995 is_ex_command = TRUE;
5996 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005997 }
5998
5999 /*
6000 * COMMAND MODIFIERS
6001 */
6002 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6003 {
6004 if (errormsg != NULL)
6005 goto erret;
6006 // empty line or comment
6007 line = (char_u *)"";
6008 continue;
6009 }
6010
6011 // Skip ":call" to get to the function name.
6012 if (checkforcmd(&ea.cmd, "call", 3))
6013 ea.cmd = skipwhite(ea.cmd);
6014
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006015 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006016 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006017 // Assuming the command starts with a variable or function name,
6018 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6019 // val".
6020 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6021 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006022 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006023 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006024 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006025 int oplen;
6026 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006027
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006028 oplen = assignment_len(skipwhite(p), &heredoc);
6029 if (oplen > 0)
6030 {
6031 // Recognize an assignment if we recognize the variable
6032 // name:
6033 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006034 // "local = expr" where "local" is a local var.
6035 // "script = expr" where "script" is a script-local var.
6036 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006037 // "&opt = expr"
6038 // "$ENV = expr"
6039 // "@r = expr"
6040 if (*ea.cmd == '&'
6041 || *ea.cmd == '$'
6042 || *ea.cmd == '@'
6043 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
6044 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
6045 || lookup_script(ea.cmd, p - ea.cmd) == OK
6046 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6047 {
6048 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6049 if (line == NULL)
6050 goto erret;
6051 continue;
6052 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006053 }
6054 }
6055 }
6056
6057 /*
6058 * COMMAND after range
6059 */
6060 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006061 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
6062 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006063
6064 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6065 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006066 if (cctx.ctx_skip == TRUE)
6067 {
6068 line += STRLEN(line);
6069 continue;
6070 }
6071
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006072 // Expression or function call.
6073 if (ea.cmdidx == CMD_eval)
6074 {
6075 p = ea.cmd;
6076 if (compile_expr1(&p, &cctx) == FAIL)
6077 goto erret;
6078
6079 // drop the return value
6080 generate_instr_drop(&cctx, ISN_DROP, 1);
6081 line = p;
6082 continue;
6083 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006084 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006085 iemsg("Command from find_ex_command() not handled");
6086 goto erret;
6087 }
6088
6089 p = skipwhite(p);
6090
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006091 if (cctx.ctx_skip == TRUE
6092 && ea.cmdidx != CMD_elseif
6093 && ea.cmdidx != CMD_else
6094 && ea.cmdidx != CMD_endif)
6095 {
6096 line += STRLEN(line);
6097 continue;
6098 }
6099
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006100 switch (ea.cmdidx)
6101 {
6102 case CMD_def:
6103 case CMD_function:
6104 // TODO: Nested function
6105 emsg("Nested function not implemented yet");
6106 goto erret;
6107
6108 case CMD_return:
6109 line = compile_return(p, set_return_type, &cctx);
6110 had_return = TRUE;
6111 break;
6112
6113 case CMD_let:
6114 case CMD_const:
6115 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6116 break;
6117
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006118 case CMD_unlet:
6119 case CMD_unlockvar:
6120 case CMD_lockvar:
6121 line = compile_unletlock(p, &ea, &cctx);
6122 break;
6123
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006124 case CMD_import:
6125 line = compile_import(p, &cctx);
6126 break;
6127
6128 case CMD_if:
6129 line = compile_if(p, &cctx);
6130 break;
6131 case CMD_elseif:
6132 line = compile_elseif(p, &cctx);
6133 break;
6134 case CMD_else:
6135 line = compile_else(p, &cctx);
6136 break;
6137 case CMD_endif:
6138 line = compile_endif(p, &cctx);
6139 break;
6140
6141 case CMD_while:
6142 line = compile_while(p, &cctx);
6143 break;
6144 case CMD_endwhile:
6145 line = compile_endwhile(p, &cctx);
6146 break;
6147
6148 case CMD_for:
6149 line = compile_for(p, &cctx);
6150 break;
6151 case CMD_endfor:
6152 line = compile_endfor(p, &cctx);
6153 break;
6154 case CMD_continue:
6155 line = compile_continue(p, &cctx);
6156 break;
6157 case CMD_break:
6158 line = compile_break(p, &cctx);
6159 break;
6160
6161 case CMD_try:
6162 line = compile_try(p, &cctx);
6163 break;
6164 case CMD_catch:
6165 line = compile_catch(p, &cctx);
6166 break;
6167 case CMD_finally:
6168 line = compile_finally(p, &cctx);
6169 break;
6170 case CMD_endtry:
6171 line = compile_endtry(p, &cctx);
6172 break;
6173 case CMD_throw:
6174 line = compile_throw(p, &cctx);
6175 break;
6176
6177 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006178 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006179 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006180 case CMD_echomsg:
6181 case CMD_echoerr:
6182 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006183 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006184
6185 default:
6186 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006187 // TODO: other commands with an expression argument
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006188 generate_EXEC(&cctx, line);
6189 line = (char_u *)"";
6190 break;
6191 }
6192 if (line == NULL)
6193 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006194 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006195
6196 if (cctx.ctx_type_stack.ga_len < 0)
6197 {
6198 iemsg("Type stack underflow");
6199 goto erret;
6200 }
6201 }
6202
6203 if (cctx.ctx_scope != NULL)
6204 {
6205 if (cctx.ctx_scope->se_type == IF_SCOPE)
6206 emsg(_(e_endif));
6207 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6208 emsg(_(e_endwhile));
6209 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6210 emsg(_(e_endfor));
6211 else
6212 emsg(_("E1026: Missing }"));
6213 goto erret;
6214 }
6215
6216 if (!had_return)
6217 {
6218 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6219 {
6220 emsg(_("E1027: Missing return statement"));
6221 goto erret;
6222 }
6223
6224 // Return zero if there is no return at the end.
6225 generate_PUSHNR(&cctx, 0);
6226 generate_instr(&cctx, ISN_RETURN);
6227 }
6228
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006229 {
6230 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6231 + ufunc->uf_dfunc_idx;
6232 dfunc->df_deleted = FALSE;
6233 dfunc->df_instr = instr->ga_data;
6234 dfunc->df_instr_count = instr->ga_len;
6235 dfunc->df_varcount = cctx.ctx_max_local;
6236 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006237
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006238 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006239 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006240 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006241
6242 // Create a type for the function, with the return type and any
6243 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006244 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6245 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006246 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006247 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006248 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6249 argcount, &ufunc->uf_type_list);
6250 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006251 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006252 argcount + varargs,
6253 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006254 {
6255 ret = FAIL;
6256 goto erret;
6257 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006258 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6259 ufunc->uf_func_type->tt_min_argcount =
6260 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006261 if (ufunc->uf_arg_types == NULL)
6262 {
6263 int i;
6264
6265 // lambda does not have argument types.
6266 for (i = 0; i < argcount; ++i)
6267 ufunc->uf_func_type->tt_args[i] = &t_any;
6268 }
6269 else
6270 mch_memmove(ufunc->uf_func_type->tt_args,
6271 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006272 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006273 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006274 ufunc->uf_func_type->tt_args[argcount] =
6275 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006276 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6277 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006278 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006279 else
6280 // No arguments, can use a predefined type.
6281 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6282 argcount, &ufunc->uf_type_list);
6283
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006284 }
6285
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006286 ret = OK;
6287
6288erret:
6289 if (ret == FAIL)
6290 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006291 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006292 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6293 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006294
6295 for (idx = 0; idx < instr->ga_len; ++idx)
6296 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006297 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006298
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006299 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006300 if (!dfunc->df_deleted)
6301 --def_functions.ga_len;
6302
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006303 while (cctx.ctx_scope != NULL)
6304 drop_scope(&cctx);
6305
Bram Moolenaar20431c92020-03-20 18:39:46 +01006306 // Don't execute this function body.
6307 ga_clear_strings(&ufunc->uf_lines);
6308
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006309 if (errormsg != NULL)
6310 emsg(errormsg);
6311 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006312 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006313 }
6314
6315 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006316 free_imported(&cctx);
6317 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006318 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006319}
6320
6321/*
6322 * Delete an instruction, free what it contains.
6323 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006324 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006325delete_instr(isn_T *isn)
6326{
6327 switch (isn->isn_type)
6328 {
6329 case ISN_EXEC:
6330 case ISN_LOADENV:
6331 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006332 case ISN_LOADB:
6333 case ISN_LOADW:
6334 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006335 case ISN_LOADOPT:
6336 case ISN_MEMBER:
6337 case ISN_PUSHEXC:
6338 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006339 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006340 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006341 case ISN_STOREB:
6342 case ISN_STOREW:
6343 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006344 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006345 vim_free(isn->isn_arg.string);
6346 break;
6347
6348 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006349 case ISN_STORES:
6350 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006351 break;
6352
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006353 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006354 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006355 vim_free(isn->isn_arg.unlet.ul_name);
6356 break;
6357
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006358 case ISN_STOREOPT:
6359 vim_free(isn->isn_arg.storeopt.so_name);
6360 break;
6361
6362 case ISN_PUSHBLOB: // push blob isn_arg.blob
6363 blob_unref(isn->isn_arg.blob);
6364 break;
6365
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006366 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006367#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006368 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006369#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006370 break;
6371
6372 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006373#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006374 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006375#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006376 break;
6377
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006378 case ISN_UCALL:
6379 vim_free(isn->isn_arg.ufunc.cuf_name);
6380 break;
6381
6382 case ISN_2BOOL:
6383 case ISN_2STRING:
6384 case ISN_ADDBLOB:
6385 case ISN_ADDLIST:
6386 case ISN_BCALL:
6387 case ISN_CATCH:
6388 case ISN_CHECKNR:
6389 case ISN_CHECKTYPE:
6390 case ISN_COMPAREANY:
6391 case ISN_COMPAREBLOB:
6392 case ISN_COMPAREBOOL:
6393 case ISN_COMPAREDICT:
6394 case ISN_COMPAREFLOAT:
6395 case ISN_COMPAREFUNC:
6396 case ISN_COMPARELIST:
6397 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006398 case ISN_COMPARESPECIAL:
6399 case ISN_COMPARESTRING:
6400 case ISN_CONCAT:
6401 case ISN_DCALL:
6402 case ISN_DROP:
6403 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006404 case ISN_EXECUTE:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006405 case ISN_ECHOMSG:
6406 case ISN_ECHOERR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006407 case ISN_ENDTRY:
6408 case ISN_FOR:
6409 case ISN_FUNCREF:
6410 case ISN_INDEX:
6411 case ISN_JUMP:
6412 case ISN_LOAD:
6413 case ISN_LOADSCRIPT:
6414 case ISN_LOADREG:
6415 case ISN_LOADV:
6416 case ISN_NEGATENR:
6417 case ISN_NEWDICT:
6418 case ISN_NEWLIST:
6419 case ISN_OPNR:
6420 case ISN_OPFLOAT:
6421 case ISN_OPANY:
6422 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006423 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006424 case ISN_PUSHF:
6425 case ISN_PUSHNR:
6426 case ISN_PUSHBOOL:
6427 case ISN_PUSHSPEC:
6428 case ISN_RETURN:
6429 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006430 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006431 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006432 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006433 case ISN_STORESCRIPT:
6434 case ISN_THROW:
6435 case ISN_TRY:
6436 // nothing allocated
6437 break;
6438 }
6439}
6440
6441/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006442 * Free all instructions for "dfunc".
6443 */
6444 static void
6445delete_def_function_contents(dfunc_T *dfunc)
6446{
6447 int idx;
6448
6449 ga_clear(&dfunc->df_def_args_isn);
6450
6451 if (dfunc->df_instr != NULL)
6452 {
6453 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6454 delete_instr(dfunc->df_instr + idx);
6455 VIM_CLEAR(dfunc->df_instr);
6456 }
6457
6458 dfunc->df_deleted = TRUE;
6459}
6460
6461/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006462 * When a user function is deleted, delete any associated def function.
6463 */
6464 void
6465delete_def_function(ufunc_T *ufunc)
6466{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006467 if (ufunc->uf_dfunc_idx >= 0)
6468 {
6469 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6470 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006471
Bram Moolenaar20431c92020-03-20 18:39:46 +01006472 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006473 }
6474}
6475
6476#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006477/*
6478 * Free all functions defined with ":def".
6479 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006480 void
6481free_def_functions(void)
6482{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006483 int idx;
6484
6485 for (idx = 0; idx < def_functions.ga_len; ++idx)
6486 {
6487 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6488
6489 delete_def_function_contents(dfunc);
6490 }
6491
6492 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006493}
6494#endif
6495
6496
6497#endif // FEAT_EVAL