blob: e8e8598e6cbd0944aeff50aef0952dc6492df0f4 [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 Moolenaar8a7d6542020-01-26 15:56:19 +0100990 * Generate an ISN_LOADS instruction.
991 */
992 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100993generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100994 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100995 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100996 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100997 int sid,
998 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100999{
1000 isn_T *isn;
1001
Bram Moolenaar080457c2020-03-03 21:53:32 +01001002 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001003 if (isn_type == ISN_LOADS)
1004 isn = generate_instr_type(cctx, isn_type, type);
1005 else
1006 isn = generate_instr_drop(cctx, isn_type, 1);
1007 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001008 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001009 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1010 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011
1012 return OK;
1013}
1014
1015/*
1016 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1017 */
1018 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001019generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001020 cctx_T *cctx,
1021 isntype_T isn_type,
1022 int sid,
1023 int idx,
1024 type_T *type)
1025{
1026 isn_T *isn;
1027
Bram Moolenaar080457c2020-03-03 21:53:32 +01001028 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001029 if (isn_type == ISN_LOADSCRIPT)
1030 isn = generate_instr_type(cctx, isn_type, type);
1031 else
1032 isn = generate_instr_drop(cctx, isn_type, 1);
1033 if (isn == NULL)
1034 return FAIL;
1035 isn->isn_arg.script.script_sid = sid;
1036 isn->isn_arg.script.script_idx = idx;
1037 return OK;
1038}
1039
1040/*
1041 * Generate an ISN_NEWLIST instruction.
1042 */
1043 static int
1044generate_NEWLIST(cctx_T *cctx, int count)
1045{
1046 isn_T *isn;
1047 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001048 type_T *type;
1049 type_T *member;
1050
Bram Moolenaar080457c2020-03-03 21:53:32 +01001051 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001052 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1053 return FAIL;
1054 isn->isn_arg.number = count;
1055
1056 // drop the value types
1057 stack->ga_len -= count;
1058
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001059 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001060 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001061 if (count > 0)
1062 member = ((type_T **)stack->ga_data)[stack->ga_len];
1063 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001064 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001065 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001066
1067 // add the list type to the type stack
1068 if (ga_grow(stack, 1) == FAIL)
1069 return FAIL;
1070 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1071 ++stack->ga_len;
1072
1073 return OK;
1074}
1075
1076/*
1077 * Generate an ISN_NEWDICT instruction.
1078 */
1079 static int
1080generate_NEWDICT(cctx_T *cctx, int count)
1081{
1082 isn_T *isn;
1083 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001084 type_T *type;
1085 type_T *member;
1086
Bram Moolenaar080457c2020-03-03 21:53:32 +01001087 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001088 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1089 return FAIL;
1090 isn->isn_arg.number = count;
1091
1092 // drop the key and value types
1093 stack->ga_len -= 2 * count;
1094
Bram Moolenaar436472f2020-02-20 22:54:43 +01001095 // Use the first value type for the list member type. Use "void" for an
1096 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001097 if (count > 0)
1098 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1099 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001100 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001101 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001102
1103 // add the dict type to the type stack
1104 if (ga_grow(stack, 1) == FAIL)
1105 return FAIL;
1106 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1107 ++stack->ga_len;
1108
1109 return OK;
1110}
1111
1112/*
1113 * Generate an ISN_FUNCREF instruction.
1114 */
1115 static int
1116generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1117{
1118 isn_T *isn;
1119 garray_T *stack = &cctx->ctx_type_stack;
1120
Bram Moolenaar080457c2020-03-03 21:53:32 +01001121 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001122 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1123 return FAIL;
1124 isn->isn_arg.number = dfunc_idx;
1125
1126 if (ga_grow(stack, 1) == FAIL)
1127 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001128 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001129 // TODO: argument and return types
1130 ++stack->ga_len;
1131
1132 return OK;
1133}
1134
1135/*
1136 * Generate an ISN_JUMP instruction.
1137 */
1138 static int
1139generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1140{
1141 isn_T *isn;
1142 garray_T *stack = &cctx->ctx_type_stack;
1143
Bram Moolenaar080457c2020-03-03 21:53:32 +01001144 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001145 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1146 return FAIL;
1147 isn->isn_arg.jump.jump_when = when;
1148 isn->isn_arg.jump.jump_where = where;
1149
1150 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1151 --stack->ga_len;
1152
1153 return OK;
1154}
1155
1156 static int
1157generate_FOR(cctx_T *cctx, int loop_idx)
1158{
1159 isn_T *isn;
1160 garray_T *stack = &cctx->ctx_type_stack;
1161
Bram Moolenaar080457c2020-03-03 21:53:32 +01001162 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001163 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1164 return FAIL;
1165 isn->isn_arg.forloop.for_idx = loop_idx;
1166
1167 if (ga_grow(stack, 1) == FAIL)
1168 return FAIL;
1169 // type doesn't matter, will be stored next
1170 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1171 ++stack->ga_len;
1172
1173 return OK;
1174}
1175
1176/*
1177 * Generate an ISN_BCALL instruction.
1178 * Return FAIL if the number of arguments is wrong.
1179 */
1180 static int
1181generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1182{
1183 isn_T *isn;
1184 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001185 type_T *argtypes[MAX_FUNC_ARGS];
1186 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001187
Bram Moolenaar080457c2020-03-03 21:53:32 +01001188 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001189 if (check_internal_func(func_idx, argcount) == FAIL)
1190 return FAIL;
1191
1192 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1193 return FAIL;
1194 isn->isn_arg.bfunc.cbf_idx = func_idx;
1195 isn->isn_arg.bfunc.cbf_argcount = argcount;
1196
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001197 for (i = 0; i < argcount; ++i)
1198 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1199
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001200 stack->ga_len -= argcount; // drop the arguments
1201 if (ga_grow(stack, 1) == FAIL)
1202 return FAIL;
1203 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001204 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001205 ++stack->ga_len; // add return value
1206
1207 return OK;
1208}
1209
1210/*
1211 * Generate an ISN_DCALL or ISN_UCALL instruction.
1212 * Return FAIL if the number of arguments is wrong.
1213 */
1214 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001215generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001216{
1217 isn_T *isn;
1218 garray_T *stack = &cctx->ctx_type_stack;
1219 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001220 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001221
Bram Moolenaar080457c2020-03-03 21:53:32 +01001222 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001223 if (argcount > regular_args && !has_varargs(ufunc))
1224 {
1225 semsg(_(e_toomanyarg), ufunc->uf_name);
1226 return FAIL;
1227 }
1228 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1229 {
1230 semsg(_(e_toofewarg), ufunc->uf_name);
1231 return FAIL;
1232 }
1233
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001234 if (ufunc->uf_dfunc_idx >= 0)
1235 {
1236 int i;
1237
1238 for (i = 0; i < argcount; ++i)
1239 {
1240 type_T *expected;
1241 type_T *actual;
1242
1243 if (i < regular_args)
1244 {
1245 if (ufunc->uf_arg_types == NULL)
1246 continue;
1247 expected = ufunc->uf_arg_types[i];
1248 }
1249 else
1250 expected = ufunc->uf_va_type->tt_member;
1251 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1252 if (check_type(expected, actual, FALSE) == FAIL)
1253 {
1254 arg_type_mismatch(expected, actual, i + 1);
1255 return FAIL;
1256 }
1257 }
1258 }
1259
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001260 if ((isn = generate_instr(cctx,
1261 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1262 return FAIL;
1263 if (ufunc->uf_dfunc_idx >= 0)
1264 {
1265 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1266 isn->isn_arg.dfunc.cdf_argcount = argcount;
1267 }
1268 else
1269 {
1270 // A user function may be deleted and redefined later, can't use the
1271 // ufunc pointer, need to look it up again at runtime.
1272 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1273 isn->isn_arg.ufunc.cuf_argcount = argcount;
1274 }
1275
1276 stack->ga_len -= argcount; // drop the arguments
1277 if (ga_grow(stack, 1) == FAIL)
1278 return FAIL;
1279 // add return value
1280 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1281 ++stack->ga_len;
1282
1283 return OK;
1284}
1285
1286/*
1287 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1288 */
1289 static int
1290generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1291{
1292 isn_T *isn;
1293 garray_T *stack = &cctx->ctx_type_stack;
1294
Bram Moolenaar080457c2020-03-03 21:53:32 +01001295 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001296 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1297 return FAIL;
1298 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1299 isn->isn_arg.ufunc.cuf_argcount = argcount;
1300
1301 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001302 if (ga_grow(stack, 1) == FAIL)
1303 return FAIL;
1304 // add return value
1305 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1306 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001307
1308 return OK;
1309}
1310
1311/*
1312 * Generate an ISN_PCALL instruction.
1313 */
1314 static int
1315generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1316{
1317 isn_T *isn;
1318 garray_T *stack = &cctx->ctx_type_stack;
1319
Bram Moolenaar080457c2020-03-03 21:53:32 +01001320 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001321
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001322 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1323 return FAIL;
1324 isn->isn_arg.pfunc.cpf_top = at_top;
1325 isn->isn_arg.pfunc.cpf_argcount = argcount;
1326
1327 stack->ga_len -= argcount; // drop the arguments
1328
1329 // drop the funcref/partial, get back the return value
1330 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1331
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001332 // If partial is above the arguments it must be cleared and replaced with
1333 // the return value.
1334 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1335 return FAIL;
1336
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001337 return OK;
1338}
1339
1340/*
1341 * Generate an ISN_MEMBER instruction.
1342 */
1343 static int
1344generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1345{
1346 isn_T *isn;
1347 garray_T *stack = &cctx->ctx_type_stack;
1348 type_T *type;
1349
Bram Moolenaar080457c2020-03-03 21:53:32 +01001350 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001351 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1352 return FAIL;
1353 isn->isn_arg.string = vim_strnsave(name, (int)len);
1354
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001355 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001356 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001357 if (type->tt_type != VAR_DICT && type != &t_any)
1358 {
1359 emsg(_(e_dictreq));
1360 return FAIL;
1361 }
1362 // change dict type to dict member type
1363 if (type->tt_type == VAR_DICT)
1364 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001365
1366 return OK;
1367}
1368
1369/*
1370 * Generate an ISN_ECHO instruction.
1371 */
1372 static int
1373generate_ECHO(cctx_T *cctx, int with_white, int count)
1374{
1375 isn_T *isn;
1376
Bram Moolenaar080457c2020-03-03 21:53:32 +01001377 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001378 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1379 return FAIL;
1380 isn->isn_arg.echo.echo_with_white = with_white;
1381 isn->isn_arg.echo.echo_count = count;
1382
1383 return OK;
1384}
1385
Bram Moolenaarad39c092020-02-26 18:23:43 +01001386/*
1387 * Generate an ISN_EXECUTE instruction.
1388 */
1389 static int
1390generate_EXECUTE(cctx_T *cctx, int count)
1391{
1392 isn_T *isn;
1393
1394 if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL)
1395 return FAIL;
1396 isn->isn_arg.number = count;
1397
1398 return OK;
1399}
1400
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001401 static int
1402generate_EXEC(cctx_T *cctx, char_u *line)
1403{
1404 isn_T *isn;
1405
Bram Moolenaar080457c2020-03-03 21:53:32 +01001406 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001407 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1408 return FAIL;
1409 isn->isn_arg.string = vim_strsave(line);
1410 return OK;
1411}
1412
1413static char e_white_both[] =
1414 N_("E1004: white space required before and after '%s'");
Bram Moolenaard77a8522020-04-03 21:59:57 +02001415static char e_white_after[] = N_("E1069: white space required after '%s'");
1416static char e_no_white_before[] = N_("E1068: No white space allowed before '%s'");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001417
1418/*
1419 * Reserve space for a local variable.
1420 * Return the index or -1 if it failed.
1421 */
1422 static int
1423reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1424{
1425 int idx;
1426 lvar_T *lvar;
1427
1428 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1429 {
1430 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1431 return -1;
1432 }
1433
1434 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1435 return -1;
1436 idx = cctx->ctx_locals.ga_len;
1437 if (cctx->ctx_max_local < idx + 1)
1438 cctx->ctx_max_local = idx + 1;
1439 ++cctx->ctx_locals.ga_len;
1440
1441 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1442 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1443 lvar->lv_const = isConst;
1444 lvar->lv_type = type;
1445
1446 return idx;
1447}
1448
1449/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001450 * Remove local variables above "new_top".
1451 */
1452 static void
1453unwind_locals(cctx_T *cctx, int new_top)
1454{
1455 if (cctx->ctx_locals.ga_len > new_top)
1456 {
1457 int idx;
1458 lvar_T *lvar;
1459
1460 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1461 {
1462 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1463 vim_free(lvar->lv_name);
1464 }
1465 }
1466 cctx->ctx_locals.ga_len = new_top;
1467}
1468
1469/*
1470 * Free all local variables.
1471 */
1472 static void
1473free_local(cctx_T *cctx)
1474{
1475 unwind_locals(cctx, 0);
1476 ga_clear(&cctx->ctx_locals);
1477}
1478
1479/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001480 * Skip over a type definition and return a pointer to just after it.
1481 */
1482 char_u *
1483skip_type(char_u *start)
1484{
1485 char_u *p = start;
1486
1487 while (ASCII_ISALNUM(*p) || *p == '_')
1488 ++p;
1489
1490 // Skip over "<type>"; this is permissive about white space.
1491 if (*skipwhite(p) == '<')
1492 {
1493 p = skipwhite(p);
1494 p = skip_type(skipwhite(p + 1));
1495 p = skipwhite(p);
1496 if (*p == '>')
1497 ++p;
1498 }
1499 return p;
1500}
1501
1502/*
1503 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001504 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001505 * Returns NULL in case of failure.
1506 */
1507 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001508parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001509{
1510 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001511 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001512
1513 if (**arg != '<')
1514 {
1515 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001516 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001517 else
1518 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001519 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001520 }
1521 *arg = skipwhite(*arg + 1);
1522
Bram Moolenaard77a8522020-04-03 21:59:57 +02001523 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001524
1525 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001526 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001527 {
1528 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001529 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001530 }
1531 ++*arg;
1532
1533 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001534 return get_list_type(member_type, type_gap);
1535 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001536}
1537
1538/*
1539 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001540 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001541 */
1542 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001543parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001544{
1545 char_u *p = *arg;
1546 size_t len;
1547
1548 // skip over the first word
1549 while (ASCII_ISALNUM(*p) || *p == '_')
1550 ++p;
1551 len = p - *arg;
1552
1553 switch (**arg)
1554 {
1555 case 'a':
1556 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1557 {
1558 *arg += len;
1559 return &t_any;
1560 }
1561 break;
1562 case 'b':
1563 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1564 {
1565 *arg += len;
1566 return &t_bool;
1567 }
1568 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1569 {
1570 *arg += len;
1571 return &t_blob;
1572 }
1573 break;
1574 case 'c':
1575 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1576 {
1577 *arg += len;
1578 return &t_channel;
1579 }
1580 break;
1581 case 'd':
1582 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1583 {
1584 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001585 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001586 }
1587 break;
1588 case 'f':
1589 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1590 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001591#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001592 *arg += len;
1593 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001594#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001595 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001596 return &t_any;
1597#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001598 }
1599 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1600 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001601 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001602 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001603 int argcount = -1;
1604 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001605 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001606 type_T *arg_type[MAX_FUNC_ARGS + 1];
1607
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001608 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001609 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001610 if (**arg == '(')
1611 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001612 // "func" may or may not return a value, "func()" does
1613 // not return a value.
1614 ret_type = &t_void;
1615
Bram Moolenaard77a8522020-04-03 21:59:57 +02001616 p = ++*arg;
1617 argcount = 0;
1618 while (*p != NUL && *p != ')')
1619 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001620 if (*p == '?')
1621 {
1622 if (first_optional == -1)
1623 first_optional = argcount;
1624 ++p;
1625 }
1626 else if (first_optional != -1)
1627 {
1628 emsg(_("E1007: mandatory argument after optional argument"));
1629 return &t_any;
1630 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001631 else if (STRNCMP(p, "...", 3) == 0)
1632 {
1633 flags |= TTFLAG_VARARGS;
1634 p += 3;
1635 }
1636
1637 arg_type[argcount++] = parse_type(&p, type_gap);
1638
1639 // Nothing comes after "...{type}".
1640 if (flags & TTFLAG_VARARGS)
1641 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001642
Bram Moolenaard77a8522020-04-03 21:59:57 +02001643 if (*p != ',' && *skipwhite(p) == ',')
1644 {
1645 semsg(_(e_no_white_before), ",");
1646 return &t_any;
1647 }
1648 if (*p == ',')
1649 {
1650 ++p;
1651 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001652 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001653 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001654 return &t_any;
1655 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001656 }
1657 p = skipwhite(p);
1658 if (argcount == MAX_FUNC_ARGS)
1659 {
1660 emsg(_("E740: Too many argument types"));
1661 return &t_any;
1662 }
1663 }
1664
1665 p = skipwhite(p);
1666 if (*p != ')')
1667 {
1668 emsg(_(e_missing_close));
1669 return &t_any;
1670 }
1671 *arg = p + 1;
1672 }
1673 if (**arg == ':')
1674 {
1675 // parse return type
1676 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001677 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001678 semsg(_(e_white_after), ":");
1679 *arg = skipwhite(*arg);
1680 ret_type = parse_type(arg, type_gap);
1681 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001682 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001683 type = get_func_type(ret_type, argcount, type_gap);
1684 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001685 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001686 type = alloc_func_type(ret_type, argcount, type_gap);
1687 type->tt_flags = flags;
1688 if (argcount > 0)
1689 {
1690 type->tt_argcount = argcount;
1691 type->tt_min_argcount = first_optional == -1
1692 ? argcount : first_optional;
1693 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001694 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001695 return &t_any;
1696 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001697 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001698 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001699 }
1700 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001701 }
1702 break;
1703 case 'j':
1704 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1705 {
1706 *arg += len;
1707 return &t_job;
1708 }
1709 break;
1710 case 'l':
1711 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1712 {
1713 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001714 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001715 }
1716 break;
1717 case 'n':
1718 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1719 {
1720 *arg += len;
1721 return &t_number;
1722 }
1723 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001724 case 's':
1725 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1726 {
1727 *arg += len;
1728 return &t_string;
1729 }
1730 break;
1731 case 'v':
1732 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1733 {
1734 *arg += len;
1735 return &t_void;
1736 }
1737 break;
1738 }
1739
1740 semsg(_("E1010: Type not recognized: %s"), *arg);
1741 return &t_any;
1742}
1743
1744/*
1745 * Check if "type1" and "type2" are exactly the same.
1746 */
1747 static int
1748equal_type(type_T *type1, type_T *type2)
1749{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001750 int i;
1751
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001752 if (type1->tt_type != type2->tt_type)
1753 return FALSE;
1754 switch (type1->tt_type)
1755 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001756 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001757 case VAR_ANY:
1758 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001759 case VAR_SPECIAL:
1760 case VAR_BOOL:
1761 case VAR_NUMBER:
1762 case VAR_FLOAT:
1763 case VAR_STRING:
1764 case VAR_BLOB:
1765 case VAR_JOB:
1766 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001767 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001768 case VAR_LIST:
1769 case VAR_DICT:
1770 return equal_type(type1->tt_member, type2->tt_member);
1771 case VAR_FUNC:
1772 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001773 if (!equal_type(type1->tt_member, type2->tt_member)
1774 || type1->tt_argcount != type2->tt_argcount)
1775 return FALSE;
1776 if (type1->tt_argcount < 0
1777 || type1->tt_args == NULL || type2->tt_args == NULL)
1778 return TRUE;
1779 for (i = 0; i < type1->tt_argcount; ++i)
1780 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1781 return FALSE;
1782 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001783 }
1784 return TRUE;
1785}
1786
1787/*
1788 * Find the common type of "type1" and "type2" and put it in "dest".
1789 * "type2" and "dest" may be the same.
1790 */
1791 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001792common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001793{
1794 if (equal_type(type1, type2))
1795 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001796 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001797 return;
1798 }
1799
1800 if (type1->tt_type == type2->tt_type)
1801 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001802 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1803 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001804 type_T *common;
1805
Bram Moolenaard77a8522020-04-03 21:59:57 +02001806 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001807 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001808 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001809 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001810 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001811 return;
1812 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001813 if (type1->tt_type == VAR_FUNC)
1814 {
1815 type_T *common;
1816
1817 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1818 if (type1->tt_argcount == type2->tt_argcount
1819 && type1->tt_argcount >= 0)
1820 {
1821 int argcount = type1->tt_argcount;
1822 int i;
1823
1824 *dest = alloc_func_type(common, argcount, type_gap);
1825 if (type1->tt_args != NULL && type2->tt_args != NULL)
1826 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001827 if (func_type_add_arg_types(*dest, argcount,
1828 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001829 for (i = 0; i < argcount; ++i)
1830 common_type(type1->tt_args[i], type2->tt_args[i],
1831 &(*dest)->tt_args[i], type_gap);
1832 }
1833 }
1834 else
1835 *dest = alloc_func_type(common, -1, type_gap);
1836 return;
1837 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001838 }
1839
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001840 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001841}
1842
1843 char *
1844vartype_name(vartype_T type)
1845{
1846 switch (type)
1847 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001848 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001849 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001850 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001851 case VAR_SPECIAL: return "special";
1852 case VAR_BOOL: return "bool";
1853 case VAR_NUMBER: return "number";
1854 case VAR_FLOAT: return "float";
1855 case VAR_STRING: return "string";
1856 case VAR_BLOB: return "blob";
1857 case VAR_JOB: return "job";
1858 case VAR_CHANNEL: return "channel";
1859 case VAR_LIST: return "list";
1860 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001861
1862 case VAR_FUNC:
1863 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001864 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001865 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001866}
1867
1868/*
1869 * Return the name of a type.
1870 * The result may be in allocated memory, in which case "tofree" is set.
1871 */
1872 char *
1873type_name(type_T *type, char **tofree)
1874{
1875 char *name = vartype_name(type->tt_type);
1876
1877 *tofree = NULL;
1878 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1879 {
1880 char *member_free;
1881 char *member_name = type_name(type->tt_member, &member_free);
1882 size_t len;
1883
1884 len = STRLEN(name) + STRLEN(member_name) + 3;
1885 *tofree = alloc(len);
1886 if (*tofree != NULL)
1887 {
1888 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1889 vim_free(member_free);
1890 return *tofree;
1891 }
1892 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001893 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001894 {
1895 garray_T ga;
1896 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001897 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001898
1899 ga_init2(&ga, 1, 100);
1900 if (ga_grow(&ga, 20) == FAIL)
1901 return "[unknown]";
1902 *tofree = ga.ga_data;
1903 STRCPY(ga.ga_data, "func(");
1904 ga.ga_len += 5;
1905
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001906 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001907 {
1908 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001909 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001910 int len;
1911
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001912 if (type->tt_args == NULL)
1913 arg_type = "[unknown]";
1914 else
1915 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001916 if (i > 0)
1917 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001918 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001919 ga.ga_len += 2;
1920 }
1921 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001922 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001923 {
1924 vim_free(arg_free);
1925 return "[unknown]";
1926 }
1927 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001928 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001929 {
1930 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1931 ga.ga_len += 3;
1932 }
1933 else if (i >= type->tt_min_argcount)
1934 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001935 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001936 ga.ga_len += len;
1937 vim_free(arg_free);
1938 }
1939
1940 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001941 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001942 else
1943 {
1944 char *ret_free;
1945 char *ret_name = type_name(type->tt_member, &ret_free);
1946 int len;
1947
1948 len = (int)STRLEN(ret_name) + 4;
1949 if (ga_grow(&ga, len) == FAIL)
1950 {
1951 vim_free(ret_free);
1952 return "[unknown]";
1953 }
1954 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001955 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1956 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001957 vim_free(ret_free);
1958 }
1959 return ga.ga_data;
1960 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001961
1962 return name;
1963}
1964
1965/*
1966 * Find "name" in script-local items of script "sid".
1967 * Returns the index in "sn_var_vals" if found.
1968 * If found but not in "sn_var_vals" returns -1.
1969 * If not found returns -2.
1970 */
1971 int
1972get_script_item_idx(int sid, char_u *name, int check_writable)
1973{
1974 hashtab_T *ht;
1975 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001976 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001977 int idx;
1978
1979 // First look the name up in the hashtable.
1980 if (sid <= 0 || sid > script_items.ga_len)
1981 return -1;
1982 ht = &SCRIPT_VARS(sid);
1983 di = find_var_in_ht(ht, 0, name, TRUE);
1984 if (di == NULL)
1985 return -2;
1986
1987 // Now find the svar_T index in sn_var_vals.
1988 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
1989 {
1990 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1991
1992 if (sv->sv_tv == &di->di_tv)
1993 {
1994 if (check_writable && sv->sv_const)
1995 semsg(_(e_readonlyvar), name);
1996 return idx;
1997 }
1998 }
1999 return -1;
2000}
2001
2002/*
2003 * Find "name" in imported items of the current script/
2004 */
2005 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002006find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002007{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002008 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002009 int idx;
2010
2011 if (cctx != NULL)
2012 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2013 {
2014 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2015 + idx;
2016
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002017 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2018 : STRLEN(import->imp_name) == len
2019 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002020 return import;
2021 }
2022
2023 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2024 {
2025 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2026
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002027 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2028 : STRLEN(import->imp_name) == len
2029 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002030 return import;
2031 }
2032 return NULL;
2033}
2034
2035/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002036 * Free all imported variables.
2037 */
2038 static void
2039free_imported(cctx_T *cctx)
2040{
2041 int idx;
2042
2043 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2044 {
2045 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2046
2047 vim_free(import->imp_name);
2048 }
2049 ga_clear(&cctx->ctx_imports);
2050}
2051
2052/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002053 * Get the next line of the function from "cctx".
2054 * Returns NULL when at the end.
2055 */
2056 static char_u *
2057next_line_from_context(cctx_T *cctx)
2058{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002059 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002060
2061 do
2062 {
2063 ++cctx->ctx_lnum;
2064 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002065 {
2066 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002067 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002068 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002069 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002070 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002071 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2072 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002073 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002074 return line;
2075}
2076
2077/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002078 * Return TRUE if "p" points at a "#" but not at "#{".
2079 */
2080 static int
2081comment_start(char_u *p)
2082{
2083 return p[0] == '#' && p[1] != '{';
2084}
2085
2086/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002087 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002088 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002089 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2090 */
2091 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002092may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002093{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002094 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002095 {
2096 char_u *next = next_line_from_context(cctx);
2097
2098 if (next == NULL)
2099 return FAIL;
2100 *arg = skipwhite(next);
2101 }
2102 return OK;
2103}
2104
2105/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002106 * Generate an instruction to load script-local variable "name", without the
2107 * leading "s:".
2108 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002109 */
2110 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002111compile_load_scriptvar(
2112 cctx_T *cctx,
2113 char_u *name, // variable NUL terminated
2114 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002115 char_u **end, // end of variable
2116 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002117{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002118 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002119 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2120 imported_T *import;
2121
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002122 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002123 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002124 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002125 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2126 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002127 }
2128 if (idx >= 0)
2129 {
2130 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2131
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002132 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002133 current_sctx.sc_sid, idx, sv->sv_type);
2134 return OK;
2135 }
2136
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002137 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002138 if (import != NULL)
2139 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002140 if (import->imp_all)
2141 {
2142 char_u *p = skipwhite(*end);
2143 int name_len;
2144 ufunc_T *ufunc;
2145 type_T *type;
2146
2147 // Used "import * as Name", need to lookup the member.
2148 if (*p != '.')
2149 {
2150 semsg(_("E1060: expected dot after name: %s"), start);
2151 return FAIL;
2152 }
2153 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002154 if (VIM_ISWHITE(*p))
2155 {
2156 emsg(_("E1074: no white space allowed after dot"));
2157 return FAIL;
2158 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002159
2160 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2161 // TODO: what if it is a function?
2162 if (idx < 0)
2163 return FAIL;
2164 *end = p;
2165
2166 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2167 import->imp_sid,
2168 idx,
2169 type);
2170 }
2171 else
2172 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002173 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002174 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2175 import->imp_sid,
2176 import->imp_var_vals_idx,
2177 import->imp_type);
2178 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002179 return OK;
2180 }
2181
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002182 if (error)
2183 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002184 return FAIL;
2185}
2186
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002187 static int
2188generate_funcref(cctx_T *cctx, char_u *name)
2189{
2190 ufunc_T *ufunc = find_func(name, cctx);
2191
2192 if (ufunc == NULL)
2193 return FAIL;
2194
2195 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2196}
2197
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002198/*
2199 * Compile a variable name into a load instruction.
2200 * "end" points to just after the name.
2201 * When "error" is FALSE do not give an error when not found.
2202 */
2203 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002204compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002205{
2206 type_T *type;
2207 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002208 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002209 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002210 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002211
2212 if (*(*arg + 1) == ':')
2213 {
2214 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002215 if (end <= *arg + 2)
2216 name = vim_strsave((char_u *)"[empty]");
2217 else
2218 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002219 if (name == NULL)
2220 return FAIL;
2221
2222 if (**arg == 'v')
2223 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002224 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002225 }
2226 else if (**arg == 'g')
2227 {
2228 // Global variables can be defined later, thus we don't check if it
2229 // exists, give error at runtime.
2230 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2231 }
2232 else if (**arg == 's')
2233 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002234 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002235 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002236 else if (**arg == 'b')
2237 {
2238 semsg("Namespace b: not supported yet: %s", *arg);
2239 goto theend;
2240 }
2241 else if (**arg == 'w')
2242 {
2243 semsg("Namespace w: not supported yet: %s", *arg);
2244 goto theend;
2245 }
2246 else if (**arg == 't')
2247 {
2248 semsg("Namespace t: not supported yet: %s", *arg);
2249 goto theend;
2250 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002251 else
2252 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002253 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002254 goto theend;
2255 }
2256 }
2257 else
2258 {
2259 size_t len = end - *arg;
2260 int idx;
2261 int gen_load = FALSE;
2262
2263 name = vim_strnsave(*arg, end - *arg);
2264 if (name == NULL)
2265 return FAIL;
2266
2267 idx = lookup_arg(*arg, len, cctx);
2268 if (idx >= 0)
2269 {
2270 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2271 type = cctx->ctx_ufunc->uf_arg_types[idx];
2272 else
2273 type = &t_any;
2274
2275 // Arguments are located above the frame pointer.
2276 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2277 if (cctx->ctx_ufunc->uf_va_name != NULL)
2278 --idx;
2279 gen_load = TRUE;
2280 }
2281 else if (lookup_vararg(*arg, len, cctx))
2282 {
2283 // varargs is always the last argument
2284 idx = -STACK_FRAME_SIZE - 1;
2285 type = cctx->ctx_ufunc->uf_va_type;
2286 gen_load = TRUE;
2287 }
2288 else
2289 {
2290 idx = lookup_local(*arg, len, cctx);
2291 if (idx >= 0)
2292 {
2293 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2294 gen_load = TRUE;
2295 }
2296 else
2297 {
2298 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2299 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2300 res = generate_PUSHBOOL(cctx, **arg == 't'
2301 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002302 else
2303 {
2304 // "var" can be script-local even without using "s:" if it
2305 // already exists.
2306 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2307 == SCRIPT_VERSION_VIM9
2308 || lookup_script(*arg, len) == OK)
2309 res = compile_load_scriptvar(cctx, name, *arg, &end,
2310 FALSE);
2311
2312 // When the name starts with an uppercase letter or "x:" it
2313 // can be a user defined function.
2314 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2315 res = generate_funcref(cctx, name);
2316 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002317 }
2318 }
2319 if (gen_load)
2320 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2321 }
2322
2323 *arg = end;
2324
2325theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002326 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002327 semsg(_(e_var_notfound), name);
2328 vim_free(name);
2329 return res;
2330}
2331
2332/*
2333 * Compile the argument expressions.
2334 * "arg" points to just after the "(" and is advanced to after the ")"
2335 */
2336 static int
2337compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2338{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002339 char_u *p = *arg;
2340 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002341
Bram Moolenaare6085c52020-04-12 20:19:16 +02002342 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002343 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002344 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002345 {
2346 p = next_line_from_context(cctx);
2347 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002348 goto failret;
2349 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002350 p = skipwhite(p);
2351 }
2352 if (*p == ')')
2353 {
2354 *arg = p + 1;
2355 return OK;
2356 }
2357
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002358 if (compile_expr1(&p, cctx) == FAIL)
2359 return FAIL;
2360 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002361
2362 if (*p != ',' && *skipwhite(p) == ',')
2363 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002364 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002365 p = skipwhite(p);
2366 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002367 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002368 {
2369 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002370 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002371 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002372 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002373 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002374 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002375 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002376failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002377 emsg(_(e_missing_close));
2378 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002379}
2380
2381/*
2382 * Compile a function call: name(arg1, arg2)
2383 * "arg" points to "name", "arg + varlen" to the "(".
2384 * "argcount_init" is 1 for "value->method()"
2385 * Instructions:
2386 * EVAL arg1
2387 * EVAL arg2
2388 * BCALL / DCALL / UCALL
2389 */
2390 static int
2391compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2392{
2393 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002394 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395 int argcount = argcount_init;
2396 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002397 char_u fname_buf[FLEN_FIXED + 1];
2398 char_u *tofree = NULL;
2399 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002400 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002401 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002402
2403 if (varlen >= sizeof(namebuf))
2404 {
2405 semsg(_("E1011: name too long: %s"), name);
2406 return FAIL;
2407 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002408 vim_strncpy(namebuf, *arg, varlen);
2409 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002410
2411 *arg = skipwhite(*arg + varlen + 1);
2412 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002413 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002414
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002415 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002416 {
2417 int idx;
2418
2419 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002420 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002421 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002422 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002423 else
2424 semsg(_(e_unknownfunc), namebuf);
2425 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002426 }
2427
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002428 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002429 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002430 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002431 {
2432 res = generate_CALL(cctx, ufunc, argcount);
2433 goto theend;
2434 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002435
2436 // If the name is a variable, load it and use PCALL.
2437 p = namebuf;
2438 if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002439 {
2440 res = generate_PCALL(cctx, argcount, FALSE);
2441 goto theend;
2442 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002443
2444 // The function may be defined only later. Need to figure out at runtime.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002445 res = generate_UCALL(cctx, name, argcount);
2446
2447theend:
2448 vim_free(tofree);
2449 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002450}
2451
2452// like NAMESPACE_CHAR but with 'a' and 'l'.
2453#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2454
2455/*
2456 * Find the end of a variable or function name. Unlike find_name_end() this
2457 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002458 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002459 * Return a pointer to just after the name. Equal to "arg" if there is no
2460 * valid name.
2461 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002462 static char_u *
2463to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002464{
2465 char_u *p;
2466
2467 // Quick check for valid starting character.
2468 if (!eval_isnamec1(*arg))
2469 return arg;
2470
2471 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2472 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2473 // and can be used in slice "[n:]".
2474 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002475 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002476 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2477 break;
2478 return p;
2479}
2480
2481/*
2482 * Like to_name_end() but also skip over a list or dict constant.
2483 */
2484 char_u *
2485to_name_const_end(char_u *arg)
2486{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002487 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002488 typval_T rettv;
2489
2490 if (p == arg && *arg == '[')
2491 {
2492
2493 // Can be "[1, 2, 3]->Func()".
2494 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2495 p = arg;
2496 }
2497 else if (p == arg && *arg == '#' && arg[1] == '{')
2498 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002499 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002500 ++p;
2501 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2502 p = arg;
2503 }
2504 else if (p == arg && *arg == '{')
2505 {
2506 int ret = get_lambda_tv(&p, &rettv, FALSE);
2507
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002508 // Can be "{x -> ret}()".
2509 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002510 if (ret == NOTDONE)
2511 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2512 if (ret != OK)
2513 p = arg;
2514 }
2515
2516 return p;
2517}
2518
2519 static void
2520type_mismatch(type_T *expected, type_T *actual)
2521{
2522 char *tofree1, *tofree2;
2523
2524 semsg(_("E1013: type mismatch, expected %s but got %s"),
2525 type_name(expected, &tofree1), type_name(actual, &tofree2));
2526 vim_free(tofree1);
2527 vim_free(tofree2);
2528}
2529
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002530 static void
2531arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2532{
2533 char *tofree1, *tofree2;
2534
2535 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2536 argidx,
2537 type_name(expected, &tofree1), type_name(actual, &tofree2));
2538 vim_free(tofree1);
2539 vim_free(tofree2);
2540}
2541
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002542/*
2543 * Check if the expected and actual types match.
2544 */
2545 static int
2546check_type(type_T *expected, type_T *actual, int give_msg)
2547{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002548 int ret = OK;
2549
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002550 // When expected is "unknown" we accept any actual type.
2551 // When expected is "any" we accept any actual type except "void".
2552 if (expected->tt_type != VAR_UNKNOWN
2553 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002554 {
2555 if (expected->tt_type != actual->tt_type)
2556 {
2557 if (give_msg)
2558 type_mismatch(expected, actual);
2559 return FAIL;
2560 }
2561 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2562 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002563 // "unknown" is used for an empty list or dict
2564 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002565 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002566 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002567 else if (expected->tt_type == VAR_FUNC)
2568 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002569 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002570 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2571 if (ret == OK && expected->tt_argcount != -1
2572 && (actual->tt_argcount < expected->tt_min_argcount
2573 || actual->tt_argcount > expected->tt_argcount))
2574 ret = FAIL;
2575 }
2576 if (ret == FAIL && give_msg)
2577 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002578 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002579 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002580}
2581
2582/*
2583 * Check that
2584 * - "actual" is "expected" type or
2585 * - "actual" is a type that can be "expected" type: add a runtime check; or
2586 * - return FAIL.
2587 */
2588 static int
2589need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2590{
Bram Moolenaar89228602020-04-05 22:14:54 +02002591 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002592 return OK;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002593 if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002594 {
2595 type_mismatch(expected, actual);
2596 return FAIL;
2597 }
2598 generate_TYPECHECK(cctx, expected, offset);
2599 return OK;
2600}
2601
2602/*
2603 * parse a list: [expr, expr]
2604 * "*arg" points to the '['.
2605 */
2606 static int
2607compile_list(char_u **arg, cctx_T *cctx)
2608{
2609 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002610 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002611 int count = 0;
2612
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002613 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002614 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002615 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002616 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002617 p = next_line_from_context(cctx);
2618 if (p == NULL)
2619 {
2620 semsg(_(e_list_end), *arg);
2621 return FAIL;
2622 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002623 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002624 p = skipwhite(p);
2625 }
2626 if (*p == ']')
2627 {
2628 ++p;
2629 // Allow for following comment, after at least one space.
2630 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2631 p += STRLEN(p);
2632 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002633 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002634 if (compile_expr1(&p, cctx) == FAIL)
2635 break;
2636 ++count;
2637 if (*p == ',')
2638 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002639 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002640 p = skipwhite(p);
2641 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002642 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002643
2644 generate_NEWLIST(cctx, count);
2645 return OK;
2646}
2647
2648/*
2649 * parse a lambda: {arg, arg -> expr}
2650 * "*arg" points to the '{'.
2651 */
2652 static int
2653compile_lambda(char_u **arg, cctx_T *cctx)
2654{
2655 garray_T *instr = &cctx->ctx_instr;
2656 typval_T rettv;
2657 ufunc_T *ufunc;
2658
2659 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002660 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002661 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002662
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002663 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002664 ++ufunc->uf_refcount;
2665 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002666 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002667
2668 // The function will have one line: "return {expr}".
2669 // Compile it into instructions.
2670 compile_def_function(ufunc, TRUE);
2671
2672 if (ufunc->uf_dfunc_idx >= 0)
2673 {
2674 if (ga_grow(instr, 1) == FAIL)
2675 return FAIL;
2676 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2677 return OK;
2678 }
2679 return FAIL;
2680}
2681
2682/*
2683 * Compile a lamda call: expr->{lambda}(args)
2684 * "arg" points to the "{".
2685 */
2686 static int
2687compile_lambda_call(char_u **arg, cctx_T *cctx)
2688{
2689 ufunc_T *ufunc;
2690 typval_T rettv;
2691 int argcount = 1;
2692 int ret = FAIL;
2693
2694 // Get the funcref in "rettv".
2695 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2696 return FAIL;
2697
2698 if (**arg != '(')
2699 {
2700 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002701 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002702 else
2703 semsg(_(e_missing_paren), "lambda");
2704 clear_tv(&rettv);
2705 return FAIL;
2706 }
2707
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002708 ufunc = rettv.vval.v_partial->pt_func;
2709 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002710 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002711 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002712
2713 // The function will have one line: "return {expr}".
2714 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002715 compile_def_function(ufunc, TRUE);
2716
2717 // compile the arguments
2718 *arg = skipwhite(*arg + 1);
2719 if (compile_arguments(arg, cctx, &argcount) == OK)
2720 // call the compiled function
2721 ret = generate_CALL(cctx, ufunc, argcount);
2722
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002723 return ret;
2724}
2725
2726/*
2727 * parse a dict: {'key': val} or #{key: val}
2728 * "*arg" points to the '{'.
2729 */
2730 static int
2731compile_dict(char_u **arg, cctx_T *cctx, int literal)
2732{
2733 garray_T *instr = &cctx->ctx_instr;
2734 int count = 0;
2735 dict_T *d = dict_alloc();
2736 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002737 char_u *whitep = *arg;
2738 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002739
2740 if (d == NULL)
2741 return FAIL;
2742 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002743 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002744 {
2745 char_u *key = NULL;
2746
Bram Moolenaar2c330432020-04-13 14:41:35 +02002747 while (**arg == NUL || (literal && **arg == '"')
2748 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002749 {
2750 *arg = next_line_from_context(cctx);
2751 if (*arg == NULL)
2752 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002753 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002754 *arg = skipwhite(*arg);
2755 }
2756
2757 if (**arg == '}')
2758 break;
2759
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002760 if (literal)
2761 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002762 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002763
Bram Moolenaar2c330432020-04-13 14:41:35 +02002764 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002765 {
2766 semsg(_("E1014: Invalid key: %s"), *arg);
2767 return FAIL;
2768 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002769 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002770 if (generate_PUSHS(cctx, key) == FAIL)
2771 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002772 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002773 }
2774 else
2775 {
2776 isn_T *isn;
2777
2778 if (compile_expr1(arg, cctx) == FAIL)
2779 return FAIL;
2780 // TODO: check type is string
2781 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2782 if (isn->isn_type == ISN_PUSHS)
2783 key = isn->isn_arg.string;
2784 }
2785
2786 // Check for duplicate keys, if using string keys.
2787 if (key != NULL)
2788 {
2789 item = dict_find(d, key, -1);
2790 if (item != NULL)
2791 {
2792 semsg(_(e_duplicate_key), key);
2793 goto failret;
2794 }
2795 item = dictitem_alloc(key);
2796 if (item != NULL)
2797 {
2798 item->di_tv.v_type = VAR_UNKNOWN;
2799 item->di_tv.v_lock = 0;
2800 if (dict_add(d, item) == FAIL)
2801 dictitem_free(item);
2802 }
2803 }
2804
2805 *arg = skipwhite(*arg);
2806 if (**arg != ':')
2807 {
2808 semsg(_(e_missing_dict_colon), *arg);
2809 return FAIL;
2810 }
2811
Bram Moolenaar2c330432020-04-13 14:41:35 +02002812 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002813 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002814 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002815 {
2816 *arg = next_line_from_context(cctx);
2817 if (*arg == NULL)
2818 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002819 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002820 *arg = skipwhite(*arg);
2821 }
2822
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002823 if (compile_expr1(arg, cctx) == FAIL)
2824 return FAIL;
2825 ++count;
2826
Bram Moolenaar2c330432020-04-13 14:41:35 +02002827 whitep = *arg;
2828 p = skipwhite(*arg);
2829 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002830 {
2831 *arg = next_line_from_context(cctx);
2832 if (*arg == NULL)
2833 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002834 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002835 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002836 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002837 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002838 if (**arg == '}')
2839 break;
2840 if (**arg != ',')
2841 {
2842 semsg(_(e_missing_dict_comma), *arg);
2843 goto failret;
2844 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002845 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002846 *arg = skipwhite(*arg + 1);
2847 }
2848
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002849 *arg = *arg + 1;
2850
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002851 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002852 p = skipwhite(*arg);
2853 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002854 *arg += STRLEN(*arg);
2855
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002856 dict_unref(d);
2857 return generate_NEWDICT(cctx, count);
2858
2859failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002860 if (*arg == NULL)
2861 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002862 dict_unref(d);
2863 return FAIL;
2864}
2865
2866/*
2867 * Compile "&option".
2868 */
2869 static int
2870compile_get_option(char_u **arg, cctx_T *cctx)
2871{
2872 typval_T rettv;
2873 char_u *start = *arg;
2874 int ret;
2875
2876 // parse the option and get the current value to get the type.
2877 rettv.v_type = VAR_UNKNOWN;
2878 ret = get_option_tv(arg, &rettv, TRUE);
2879 if (ret == OK)
2880 {
2881 // include the '&' in the name, get_option_tv() expects it.
2882 char_u *name = vim_strnsave(start, *arg - start);
2883 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2884
2885 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2886 vim_free(name);
2887 }
2888 clear_tv(&rettv);
2889
2890 return ret;
2891}
2892
2893/*
2894 * Compile "$VAR".
2895 */
2896 static int
2897compile_get_env(char_u **arg, cctx_T *cctx)
2898{
2899 char_u *start = *arg;
2900 int len;
2901 int ret;
2902 char_u *name;
2903
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002904 ++*arg;
2905 len = get_env_len(arg);
2906 if (len == 0)
2907 {
2908 semsg(_(e_syntax_at), start - 1);
2909 return FAIL;
2910 }
2911
2912 // include the '$' in the name, get_env_tv() expects it.
2913 name = vim_strnsave(start, len + 1);
2914 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2915 vim_free(name);
2916 return ret;
2917}
2918
2919/*
2920 * Compile "@r".
2921 */
2922 static int
2923compile_get_register(char_u **arg, cctx_T *cctx)
2924{
2925 int ret;
2926
2927 ++*arg;
2928 if (**arg == NUL)
2929 {
2930 semsg(_(e_syntax_at), *arg - 1);
2931 return FAIL;
2932 }
2933 if (!valid_yank_reg(**arg, TRUE))
2934 {
2935 emsg_invreg(**arg);
2936 return FAIL;
2937 }
2938 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2939 ++*arg;
2940 return ret;
2941}
2942
2943/*
2944 * Apply leading '!', '-' and '+' to constant "rettv".
2945 */
2946 static int
2947apply_leader(typval_T *rettv, char_u *start, char_u *end)
2948{
2949 char_u *p = end;
2950
2951 // this works from end to start
2952 while (p > start)
2953 {
2954 --p;
2955 if (*p == '-' || *p == '+')
2956 {
2957 // only '-' has an effect, for '+' we only check the type
2958#ifdef FEAT_FLOAT
2959 if (rettv->v_type == VAR_FLOAT)
2960 {
2961 if (*p == '-')
2962 rettv->vval.v_float = -rettv->vval.v_float;
2963 }
2964 else
2965#endif
2966 {
2967 varnumber_T val;
2968 int error = FALSE;
2969
2970 // tv_get_number_chk() accepts a string, but we don't want that
2971 // here
2972 if (check_not_string(rettv) == FAIL)
2973 return FAIL;
2974 val = tv_get_number_chk(rettv, &error);
2975 clear_tv(rettv);
2976 if (error)
2977 return FAIL;
2978 if (*p == '-')
2979 val = -val;
2980 rettv->v_type = VAR_NUMBER;
2981 rettv->vval.v_number = val;
2982 }
2983 }
2984 else
2985 {
2986 int v = tv2bool(rettv);
2987
2988 // '!' is permissive in the type.
2989 clear_tv(rettv);
2990 rettv->v_type = VAR_BOOL;
2991 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
2992 }
2993 }
2994 return OK;
2995}
2996
2997/*
2998 * Recognize v: variables that are constants and set "rettv".
2999 */
3000 static void
3001get_vim_constant(char_u **arg, typval_T *rettv)
3002{
3003 if (STRNCMP(*arg, "v:true", 6) == 0)
3004 {
3005 rettv->v_type = VAR_BOOL;
3006 rettv->vval.v_number = VVAL_TRUE;
3007 *arg += 6;
3008 }
3009 else if (STRNCMP(*arg, "v:false", 7) == 0)
3010 {
3011 rettv->v_type = VAR_BOOL;
3012 rettv->vval.v_number = VVAL_FALSE;
3013 *arg += 7;
3014 }
3015 else if (STRNCMP(*arg, "v:null", 6) == 0)
3016 {
3017 rettv->v_type = VAR_SPECIAL;
3018 rettv->vval.v_number = VVAL_NULL;
3019 *arg += 6;
3020 }
3021 else if (STRNCMP(*arg, "v:none", 6) == 0)
3022 {
3023 rettv->v_type = VAR_SPECIAL;
3024 rettv->vval.v_number = VVAL_NONE;
3025 *arg += 6;
3026 }
3027}
3028
3029/*
3030 * Compile code to apply '-', '+' and '!'.
3031 */
3032 static int
3033compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3034{
3035 char_u *p = end;
3036
3037 // this works from end to start
3038 while (p > start)
3039 {
3040 --p;
3041 if (*p == '-' || *p == '+')
3042 {
3043 int negate = *p == '-';
3044 isn_T *isn;
3045
3046 // TODO: check type
3047 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3048 {
3049 --p;
3050 if (*p == '-')
3051 negate = !negate;
3052 }
3053 // only '-' has an effect, for '+' we only check the type
3054 if (negate)
3055 isn = generate_instr(cctx, ISN_NEGATENR);
3056 else
3057 isn = generate_instr(cctx, ISN_CHECKNR);
3058 if (isn == NULL)
3059 return FAIL;
3060 }
3061 else
3062 {
3063 int invert = TRUE;
3064
3065 while (p > start && p[-1] == '!')
3066 {
3067 --p;
3068 invert = !invert;
3069 }
3070 if (generate_2BOOL(cctx, invert) == FAIL)
3071 return FAIL;
3072 }
3073 }
3074 return OK;
3075}
3076
3077/*
3078 * Compile whatever comes after "name" or "name()".
3079 */
3080 static int
3081compile_subscript(
3082 char_u **arg,
3083 cctx_T *cctx,
3084 char_u **start_leader,
3085 char_u *end_leader)
3086{
3087 for (;;)
3088 {
3089 if (**arg == '(')
3090 {
3091 int argcount = 0;
3092
3093 // funcref(arg)
3094 *arg = skipwhite(*arg + 1);
3095 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3096 return FAIL;
3097 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
3098 return FAIL;
3099 }
3100 else if (**arg == '-' && (*arg)[1] == '>')
3101 {
3102 char_u *p;
3103
3104 // something->method()
3105 // Apply the '!', '-' and '+' first:
3106 // -1.0->func() works like (-1.0)->func()
3107 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3108 return FAIL;
3109 *start_leader = end_leader; // don't apply again later
3110
3111 *arg = skipwhite(*arg + 2);
3112 if (**arg == '{')
3113 {
3114 // lambda call: list->{lambda}
3115 if (compile_lambda_call(arg, cctx) == FAIL)
3116 return FAIL;
3117 }
3118 else
3119 {
3120 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003121 p = *arg;
3122 if (ASCII_ISALPHA(*p) && p[1] == ':')
3123 p += 2;
3124 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003125 ;
3126 if (*p != '(')
3127 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003128 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003129 return FAIL;
3130 }
3131 // TODO: base value may not be the first argument
3132 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3133 return FAIL;
3134 }
3135 }
3136 else if (**arg == '[')
3137 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003138 garray_T *stack;
3139 type_T **typep;
3140
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003141 // list index: list[123]
3142 // TODO: more arguments
3143 // TODO: dict member dict['name']
3144 *arg = skipwhite(*arg + 1);
3145 if (compile_expr1(arg, cctx) == FAIL)
3146 return FAIL;
3147
3148 if (**arg != ']')
3149 {
3150 emsg(_(e_missbrac));
3151 return FAIL;
3152 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003153 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003154
3155 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3156 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003157 stack = &cctx->ctx_type_stack;
3158 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3159 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3160 {
3161 emsg(_(e_listreq));
3162 return FAIL;
3163 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003164 if ((*typep)->tt_type == VAR_LIST)
3165 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003166 }
3167 else if (**arg == '.' && (*arg)[1] != '.')
3168 {
3169 char_u *p;
3170
3171 ++*arg;
3172 p = *arg;
3173 // dictionary member: dict.name
3174 if (eval_isnamec1(*p))
3175 while (eval_isnamec(*p))
3176 MB_PTR_ADV(p);
3177 if (p == *arg)
3178 {
3179 semsg(_(e_syntax_at), *arg);
3180 return FAIL;
3181 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003182 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3183 return FAIL;
3184 *arg = p;
3185 }
3186 else
3187 break;
3188 }
3189
3190 // TODO - see handle_subscript():
3191 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3192 // Don't do this when "Func" is already a partial that was bound
3193 // explicitly (pt_auto is FALSE).
3194
3195 return OK;
3196}
3197
3198/*
3199 * Compile an expression at "*p" and add instructions to "instr".
3200 * "p" is advanced until after the expression, skipping white space.
3201 *
3202 * This is the equivalent of eval1(), eval2(), etc.
3203 */
3204
3205/*
3206 * number number constant
3207 * 0zFFFFFFFF Blob constant
3208 * "string" string constant
3209 * 'string' literal string constant
3210 * &option-name option value
3211 * @r register contents
3212 * identifier variable value
3213 * function() function call
3214 * $VAR environment variable
3215 * (expression) nested expression
3216 * [expr, expr] List
3217 * {key: val, key: val} Dictionary
3218 * #{key: val, key: val} Dictionary with literal keys
3219 *
3220 * Also handle:
3221 * ! in front logical NOT
3222 * - in front unary minus
3223 * + in front unary plus (ignored)
3224 * trailing (arg) funcref/partial call
3225 * trailing [] subscript in String or List
3226 * trailing .name entry in Dictionary
3227 * trailing ->name() method call
3228 */
3229 static int
3230compile_expr7(char_u **arg, cctx_T *cctx)
3231{
3232 typval_T rettv;
3233 char_u *start_leader, *end_leader;
3234 int ret = OK;
3235
3236 /*
3237 * Skip '!', '-' and '+' characters. They are handled later.
3238 */
3239 start_leader = *arg;
3240 while (**arg == '!' || **arg == '-' || **arg == '+')
3241 *arg = skipwhite(*arg + 1);
3242 end_leader = *arg;
3243
3244 rettv.v_type = VAR_UNKNOWN;
3245 switch (**arg)
3246 {
3247 /*
3248 * Number constant.
3249 */
3250 case '0': // also for blob starting with 0z
3251 case '1':
3252 case '2':
3253 case '3':
3254 case '4':
3255 case '5':
3256 case '6':
3257 case '7':
3258 case '8':
3259 case '9':
3260 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3261 return FAIL;
3262 break;
3263
3264 /*
3265 * String constant: "string".
3266 */
3267 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3268 return FAIL;
3269 break;
3270
3271 /*
3272 * Literal string constant: 'str''ing'.
3273 */
3274 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3275 return FAIL;
3276 break;
3277
3278 /*
3279 * Constant Vim variable.
3280 */
3281 case 'v': get_vim_constant(arg, &rettv);
3282 ret = NOTDONE;
3283 break;
3284
3285 /*
3286 * List: [expr, expr]
3287 */
3288 case '[': ret = compile_list(arg, cctx);
3289 break;
3290
3291 /*
3292 * Dictionary: #{key: val, key: val}
3293 */
3294 case '#': if ((*arg)[1] == '{')
3295 {
3296 ++*arg;
3297 ret = compile_dict(arg, cctx, TRUE);
3298 }
3299 else
3300 ret = NOTDONE;
3301 break;
3302
3303 /*
3304 * Lambda: {arg, arg -> expr}
3305 * Dictionary: {'key': val, 'key': val}
3306 */
3307 case '{': {
3308 char_u *start = skipwhite(*arg + 1);
3309
3310 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003311 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003312 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003313 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003314 if (ret != FAIL && *start == '>')
3315 ret = compile_lambda(arg, cctx);
3316 else
3317 ret = compile_dict(arg, cctx, FALSE);
3318 }
3319 break;
3320
3321 /*
3322 * Option value: &name
3323 */
3324 case '&': ret = compile_get_option(arg, cctx);
3325 break;
3326
3327 /*
3328 * Environment variable: $VAR.
3329 */
3330 case '$': ret = compile_get_env(arg, cctx);
3331 break;
3332
3333 /*
3334 * Register contents: @r.
3335 */
3336 case '@': ret = compile_get_register(arg, cctx);
3337 break;
3338 /*
3339 * nested expression: (expression).
3340 */
3341 case '(': *arg = skipwhite(*arg + 1);
3342 ret = compile_expr1(arg, cctx); // recursive!
3343 *arg = skipwhite(*arg);
3344 if (**arg == ')')
3345 ++*arg;
3346 else if (ret == OK)
3347 {
3348 emsg(_(e_missing_close));
3349 ret = FAIL;
3350 }
3351 break;
3352
3353 default: ret = NOTDONE;
3354 break;
3355 }
3356 if (ret == FAIL)
3357 return FAIL;
3358
3359 if (rettv.v_type != VAR_UNKNOWN)
3360 {
3361 // apply the '!', '-' and '+' before the constant
3362 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3363 {
3364 clear_tv(&rettv);
3365 return FAIL;
3366 }
3367 start_leader = end_leader; // don't apply again below
3368
3369 // push constant
3370 switch (rettv.v_type)
3371 {
3372 case VAR_BOOL:
3373 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3374 break;
3375 case VAR_SPECIAL:
3376 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3377 break;
3378 case VAR_NUMBER:
3379 generate_PUSHNR(cctx, rettv.vval.v_number);
3380 break;
3381#ifdef FEAT_FLOAT
3382 case VAR_FLOAT:
3383 generate_PUSHF(cctx, rettv.vval.v_float);
3384 break;
3385#endif
3386 case VAR_BLOB:
3387 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3388 rettv.vval.v_blob = NULL;
3389 break;
3390 case VAR_STRING:
3391 generate_PUSHS(cctx, rettv.vval.v_string);
3392 rettv.vval.v_string = NULL;
3393 break;
3394 default:
3395 iemsg("constant type missing");
3396 return FAIL;
3397 }
3398 }
3399 else if (ret == NOTDONE)
3400 {
3401 char_u *p;
3402 int r;
3403
3404 if (!eval_isnamec1(**arg))
3405 {
3406 semsg(_("E1015: Name expected: %s"), *arg);
3407 return FAIL;
3408 }
3409
3410 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003411 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003412 if (*p == '(')
3413 r = compile_call(arg, p - *arg, cctx, 0);
3414 else
3415 r = compile_load(arg, p, cctx, TRUE);
3416 if (r == FAIL)
3417 return FAIL;
3418 }
3419
3420 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3421 return FAIL;
3422
3423 // Now deal with prefixed '-', '+' and '!', if not done already.
3424 return compile_leader(cctx, start_leader, end_leader);
3425}
3426
3427/*
3428 * * number multiplication
3429 * / number division
3430 * % number modulo
3431 */
3432 static int
3433compile_expr6(char_u **arg, cctx_T *cctx)
3434{
3435 char_u *op;
3436
3437 // get the first variable
3438 if (compile_expr7(arg, cctx) == FAIL)
3439 return FAIL;
3440
3441 /*
3442 * Repeat computing, until no "*", "/" or "%" is following.
3443 */
3444 for (;;)
3445 {
3446 op = skipwhite(*arg);
3447 if (*op != '*' && *op != '/' && *op != '%')
3448 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003449 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003450 {
3451 char_u buf[3];
3452
3453 vim_strncpy(buf, op, 1);
3454 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003455 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003456 }
3457 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003458 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003459 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003460
3461 // get the second variable
3462 if (compile_expr7(arg, cctx) == FAIL)
3463 return FAIL;
3464
3465 generate_two_op(cctx, op);
3466 }
3467
3468 return OK;
3469}
3470
3471/*
3472 * + number addition
3473 * - number subtraction
3474 * .. string concatenation
3475 */
3476 static int
3477compile_expr5(char_u **arg, cctx_T *cctx)
3478{
3479 char_u *op;
3480 int oplen;
3481
3482 // get the first variable
3483 if (compile_expr6(arg, cctx) == FAIL)
3484 return FAIL;
3485
3486 /*
3487 * Repeat computing, until no "+", "-" or ".." is following.
3488 */
3489 for (;;)
3490 {
3491 op = skipwhite(*arg);
3492 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3493 break;
3494 oplen = (*op == '.' ? 2 : 1);
3495
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003496 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003497 {
3498 char_u buf[3];
3499
3500 vim_strncpy(buf, op, oplen);
3501 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003502 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003503 }
3504
3505 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003506 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003507 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003508
3509 // get the second variable
3510 if (compile_expr6(arg, cctx) == FAIL)
3511 return FAIL;
3512
3513 if (*op == '.')
3514 {
3515 if (may_generate_2STRING(-2, cctx) == FAIL
3516 || may_generate_2STRING(-1, cctx) == FAIL)
3517 return FAIL;
3518 generate_instr_drop(cctx, ISN_CONCAT, 1);
3519 }
3520 else
3521 generate_two_op(cctx, op);
3522 }
3523
3524 return OK;
3525}
3526
Bram Moolenaar080457c2020-03-03 21:53:32 +01003527 static exptype_T
3528get_compare_type(char_u *p, int *len, int *type_is)
3529{
3530 exptype_T type = EXPR_UNKNOWN;
3531 int i;
3532
3533 switch (p[0])
3534 {
3535 case '=': if (p[1] == '=')
3536 type = EXPR_EQUAL;
3537 else if (p[1] == '~')
3538 type = EXPR_MATCH;
3539 break;
3540 case '!': if (p[1] == '=')
3541 type = EXPR_NEQUAL;
3542 else if (p[1] == '~')
3543 type = EXPR_NOMATCH;
3544 break;
3545 case '>': if (p[1] != '=')
3546 {
3547 type = EXPR_GREATER;
3548 *len = 1;
3549 }
3550 else
3551 type = EXPR_GEQUAL;
3552 break;
3553 case '<': if (p[1] != '=')
3554 {
3555 type = EXPR_SMALLER;
3556 *len = 1;
3557 }
3558 else
3559 type = EXPR_SEQUAL;
3560 break;
3561 case 'i': if (p[1] == 's')
3562 {
3563 // "is" and "isnot"; but not a prefix of a name
3564 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3565 *len = 5;
3566 i = p[*len];
3567 if (!isalnum(i) && i != '_')
3568 {
3569 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3570 *type_is = TRUE;
3571 }
3572 }
3573 break;
3574 }
3575 return type;
3576}
3577
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003578/*
3579 * expr5a == expr5b
3580 * expr5a =~ expr5b
3581 * expr5a != expr5b
3582 * expr5a !~ expr5b
3583 * expr5a > expr5b
3584 * expr5a >= expr5b
3585 * expr5a < expr5b
3586 * expr5a <= expr5b
3587 * expr5a is expr5b
3588 * expr5a isnot expr5b
3589 *
3590 * Produces instructions:
3591 * EVAL expr5a Push result of "expr5a"
3592 * EVAL expr5b Push result of "expr5b"
3593 * COMPARE one of the compare instructions
3594 */
3595 static int
3596compile_expr4(char_u **arg, cctx_T *cctx)
3597{
3598 exptype_T type = EXPR_UNKNOWN;
3599 char_u *p;
3600 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003601 int type_is = FALSE;
3602
3603 // get the first variable
3604 if (compile_expr5(arg, cctx) == FAIL)
3605 return FAIL;
3606
3607 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003608 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003609
3610 /*
3611 * If there is a comparative operator, use it.
3612 */
3613 if (type != EXPR_UNKNOWN)
3614 {
3615 int ic = FALSE; // Default: do not ignore case
3616
3617 if (type_is && (p[len] == '?' || p[len] == '#'))
3618 {
3619 semsg(_(e_invexpr2), *arg);
3620 return FAIL;
3621 }
3622 // extra question mark appended: ignore case
3623 if (p[len] == '?')
3624 {
3625 ic = TRUE;
3626 ++len;
3627 }
3628 // extra '#' appended: match case (ignored)
3629 else if (p[len] == '#')
3630 ++len;
3631 // nothing appended: match case
3632
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003633 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003634 {
3635 char_u buf[7];
3636
3637 vim_strncpy(buf, p, len);
3638 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003639 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003640 }
3641
3642 // get the second variable
3643 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003644 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003645 return FAIL;
3646
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003647 if (compile_expr5(arg, cctx) == FAIL)
3648 return FAIL;
3649
3650 generate_COMPARE(cctx, type, ic);
3651 }
3652
3653 return OK;
3654}
3655
3656/*
3657 * Compile || or &&.
3658 */
3659 static int
3660compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3661{
3662 char_u *p = skipwhite(*arg);
3663 int opchar = *op;
3664
3665 if (p[0] == opchar && p[1] == opchar)
3666 {
3667 garray_T *instr = &cctx->ctx_instr;
3668 garray_T end_ga;
3669
3670 /*
3671 * Repeat until there is no following "||" or "&&"
3672 */
3673 ga_init2(&end_ga, sizeof(int), 10);
3674 while (p[0] == opchar && p[1] == opchar)
3675 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003676 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3677 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003678 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003679 return FAIL;
3680 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003681
3682 if (ga_grow(&end_ga, 1) == FAIL)
3683 {
3684 ga_clear(&end_ga);
3685 return FAIL;
3686 }
3687 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3688 ++end_ga.ga_len;
3689 generate_JUMP(cctx, opchar == '|'
3690 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3691
3692 // eval the next expression
3693 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003694 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003695 return FAIL;
3696
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003697 if ((opchar == '|' ? compile_expr3(arg, cctx)
3698 : compile_expr4(arg, cctx)) == FAIL)
3699 {
3700 ga_clear(&end_ga);
3701 return FAIL;
3702 }
3703 p = skipwhite(*arg);
3704 }
3705
3706 // Fill in the end label in all jumps.
3707 while (end_ga.ga_len > 0)
3708 {
3709 isn_T *isn;
3710
3711 --end_ga.ga_len;
3712 isn = ((isn_T *)instr->ga_data)
3713 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3714 isn->isn_arg.jump.jump_where = instr->ga_len;
3715 }
3716 ga_clear(&end_ga);
3717 }
3718
3719 return OK;
3720}
3721
3722/*
3723 * expr4a && expr4a && expr4a logical AND
3724 *
3725 * Produces instructions:
3726 * EVAL expr4a Push result of "expr4a"
3727 * JUMP_AND_KEEP_IF_FALSE end
3728 * EVAL expr4b Push result of "expr4b"
3729 * JUMP_AND_KEEP_IF_FALSE end
3730 * EVAL expr4c Push result of "expr4c"
3731 * end:
3732 */
3733 static int
3734compile_expr3(char_u **arg, cctx_T *cctx)
3735{
3736 // get the first variable
3737 if (compile_expr4(arg, cctx) == FAIL)
3738 return FAIL;
3739
3740 // || and && work almost the same
3741 return compile_and_or(arg, cctx, "&&");
3742}
3743
3744/*
3745 * expr3a || expr3b || expr3c logical OR
3746 *
3747 * Produces instructions:
3748 * EVAL expr3a Push result of "expr3a"
3749 * JUMP_AND_KEEP_IF_TRUE end
3750 * EVAL expr3b Push result of "expr3b"
3751 * JUMP_AND_KEEP_IF_TRUE end
3752 * EVAL expr3c Push result of "expr3c"
3753 * end:
3754 */
3755 static int
3756compile_expr2(char_u **arg, cctx_T *cctx)
3757{
3758 // eval the first expression
3759 if (compile_expr3(arg, cctx) == FAIL)
3760 return FAIL;
3761
3762 // || and && work almost the same
3763 return compile_and_or(arg, cctx, "||");
3764}
3765
3766/*
3767 * Toplevel expression: expr2 ? expr1a : expr1b
3768 *
3769 * Produces instructions:
3770 * EVAL expr2 Push result of "expr"
3771 * JUMP_IF_FALSE alt jump if false
3772 * EVAL expr1a
3773 * JUMP_ALWAYS end
3774 * alt: EVAL expr1b
3775 * end:
3776 */
3777 static int
3778compile_expr1(char_u **arg, cctx_T *cctx)
3779{
3780 char_u *p;
3781
3782 // evaluate the first expression
3783 if (compile_expr2(arg, cctx) == FAIL)
3784 return FAIL;
3785
3786 p = skipwhite(*arg);
3787 if (*p == '?')
3788 {
3789 garray_T *instr = &cctx->ctx_instr;
3790 garray_T *stack = &cctx->ctx_type_stack;
3791 int alt_idx = instr->ga_len;
3792 int end_idx;
3793 isn_T *isn;
3794 type_T *type1;
3795 type_T *type2;
3796
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003797 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3798 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003799 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003800 return FAIL;
3801 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003802
3803 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3804
3805 // evaluate the second expression; any type is accepted
3806 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003807 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003808 return FAIL;
3809
Bram Moolenaara6d53682020-01-28 23:04:06 +01003810 if (compile_expr1(arg, cctx) == FAIL)
3811 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003812
3813 // remember the type and drop it
3814 --stack->ga_len;
3815 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3816
3817 end_idx = instr->ga_len;
3818 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3819
3820 // jump here from JUMP_IF_FALSE
3821 isn = ((isn_T *)instr->ga_data) + alt_idx;
3822 isn->isn_arg.jump.jump_where = instr->ga_len;
3823
3824 // Check for the ":".
3825 p = skipwhite(*arg);
3826 if (*p != ':')
3827 {
3828 emsg(_(e_missing_colon));
3829 return FAIL;
3830 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003831 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3832 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003833 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003834 return FAIL;
3835 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003836
3837 // evaluate the third expression
3838 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003839 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003840 return FAIL;
3841
Bram Moolenaara6d53682020-01-28 23:04:06 +01003842 if (compile_expr1(arg, cctx) == FAIL)
3843 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003844
3845 // If the types differ, the result has a more generic type.
3846 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003847 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003848
3849 // jump here from JUMP_ALWAYS
3850 isn = ((isn_T *)instr->ga_data) + end_idx;
3851 isn->isn_arg.jump.jump_where = instr->ga_len;
3852 }
3853 return OK;
3854}
3855
3856/*
3857 * compile "return [expr]"
3858 */
3859 static char_u *
3860compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3861{
3862 char_u *p = arg;
3863 garray_T *stack = &cctx->ctx_type_stack;
3864 type_T *stack_type;
3865
3866 if (*p != NUL && *p != '|' && *p != '\n')
3867 {
3868 // compile return argument into instructions
3869 if (compile_expr1(&p, cctx) == FAIL)
3870 return NULL;
3871
3872 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3873 if (set_return_type)
3874 cctx->ctx_ufunc->uf_ret_type = stack_type;
3875 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3876 == FAIL)
3877 return NULL;
3878 }
3879 else
3880 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003881 // "set_return_type" cannot be TRUE, only used for a lambda which
3882 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003883 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3884 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003885 {
3886 emsg(_("E1003: Missing return value"));
3887 return NULL;
3888 }
3889
3890 // No argument, return zero.
3891 generate_PUSHNR(cctx, 0);
3892 }
3893
3894 if (generate_instr(cctx, ISN_RETURN) == NULL)
3895 return NULL;
3896
3897 // "return val | endif" is possible
3898 return skipwhite(p);
3899}
3900
3901/*
3902 * Return the length of an assignment operator, or zero if there isn't one.
3903 */
3904 int
3905assignment_len(char_u *p, int *heredoc)
3906{
3907 if (*p == '=')
3908 {
3909 if (p[1] == '<' && p[2] == '<')
3910 {
3911 *heredoc = TRUE;
3912 return 3;
3913 }
3914 return 1;
3915 }
3916 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3917 return 2;
3918 if (STRNCMP(p, "..=", 3) == 0)
3919 return 3;
3920 return 0;
3921}
3922
3923// words that cannot be used as a variable
3924static char *reserved[] = {
3925 "true",
3926 "false",
3927 NULL
3928};
3929
3930/*
3931 * Get a line for "=<<".
3932 * Return a pointer to the line in allocated memory.
3933 * Return NULL for end-of-file or some error.
3934 */
3935 static char_u *
3936heredoc_getline(
3937 int c UNUSED,
3938 void *cookie,
3939 int indent UNUSED,
3940 int do_concat UNUSED)
3941{
3942 cctx_T *cctx = (cctx_T *)cookie;
3943
3944 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003945 {
3946 iemsg("Heredoc got to end");
3947 return NULL;
3948 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003949 ++cctx->ctx_lnum;
3950 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3951 [cctx->ctx_lnum]);
3952}
3953
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003954typedef enum {
3955 dest_local,
3956 dest_option,
3957 dest_env,
3958 dest_global,
3959 dest_vimvar,
3960 dest_script,
3961 dest_reg,
3962} assign_dest_T;
3963
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003964/*
3965 * compile "let var [= expr]", "const var = expr" and "var = expr"
3966 * "arg" points to "var".
3967 */
3968 static char_u *
3969compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3970{
3971 char_u *p;
3972 char_u *ret = NULL;
3973 int var_count = 0;
3974 int semicolon = 0;
3975 size_t varlen;
3976 garray_T *instr = &cctx->ctx_instr;
3977 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02003978 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003979 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003980 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003981 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003982 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003983 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003984 int oplen = 0;
3985 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003986 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003987 lvar_T *lvar;
3988 char_u *name;
3989 char_u *sp;
3990 int has_type = FALSE;
3991 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
3992 int instr_count = -1;
3993
3994 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
3995 if (p == NULL)
3996 return NULL;
3997 if (var_count > 0)
3998 {
3999 // TODO: let [var, var] = list
4000 emsg("Cannot handle a list yet");
4001 return NULL;
4002 }
4003
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004004 // "a: type" is declaring variable "a" with a type, not "a:".
4005 if (is_decl && p == arg + 2 && p[-1] == ':')
4006 --p;
4007
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004008 varlen = p - arg;
4009 name = vim_strnsave(arg, (int)varlen);
4010 if (name == NULL)
4011 return NULL;
4012
Bram Moolenaar080457c2020-03-03 21:53:32 +01004013 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004014 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004015 if (*arg == '&')
4016 {
4017 int cc;
4018 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004019
Bram Moolenaar080457c2020-03-03 21:53:32 +01004020 dest = dest_option;
4021 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004022 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004023 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004024 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004025 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004026 if (is_decl)
4027 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004028 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004029 goto theend;
4030 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004031 p = arg;
4032 p = find_option_end(&p, &opt_flags);
4033 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004034 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004035 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004036 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004037 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004038 }
4039 cc = *p;
4040 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004041 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004042 *p = cc;
4043 if (opt_type == -3)
4044 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004045 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004046 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004047 }
4048 if (opt_type == -2 || opt_type == 0)
4049 type = &t_string;
4050 else
4051 type = &t_number; // both number and boolean option
4052 }
4053 else if (*arg == '$')
4054 {
4055 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004056 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004057 if (is_decl)
4058 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004059 semsg(_("E1065: Cannot declare an environment variable: %s"),
4060 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004061 goto theend;
4062 }
4063 }
4064 else if (*arg == '@')
4065 {
4066 if (!valid_yank_reg(arg[1], TRUE))
4067 {
4068 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004069 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004070 }
4071 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004072 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004073 if (is_decl)
4074 {
4075 semsg(_("E1066: Cannot declare a register: %s"), name);
4076 goto theend;
4077 }
4078 }
4079 else if (STRNCMP(arg, "g:", 2) == 0)
4080 {
4081 dest = dest_global;
4082 if (is_decl)
4083 {
4084 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4085 goto theend;
4086 }
4087 }
4088 else if (STRNCMP(arg, "v:", 2) == 0)
4089 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004090 typval_T *vtv;
4091 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004092
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004093 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004094 if (vimvaridx < 0)
4095 {
4096 semsg(_(e_var_notfound), arg);
4097 goto theend;
4098 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004099 // We use the current value of "sandbox" here, is that OK?
4100 if (var_check_ro(di_flags, name, FALSE))
4101 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004102 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004103 vtv = get_vim_var_tv(vimvaridx);
4104 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004105 if (is_decl)
4106 {
4107 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4108 goto theend;
4109 }
4110 }
4111 else
4112 {
4113 for (idx = 0; reserved[idx] != NULL; ++idx)
4114 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004115 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004116 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004117 goto theend;
4118 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004119
4120 idx = lookup_local(arg, varlen, cctx);
4121 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004122 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004123 if (is_decl)
4124 {
4125 semsg(_("E1017: Variable already declared: %s"), name);
4126 goto theend;
4127 }
4128 else
4129 {
4130 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4131 if (lvar->lv_const)
4132 {
4133 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4134 goto theend;
4135 }
4136 }
4137 }
4138 else if (STRNCMP(arg, "s:", 2) == 0
4139 || lookup_script(arg, varlen) == OK
4140 || find_imported(arg, varlen, cctx) != NULL)
4141 {
4142 dest = dest_script;
4143 if (is_decl)
4144 {
4145 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004146 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004147 goto theend;
4148 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004149 }
4150 }
4151 }
4152
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004153 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004154 {
4155 if (is_decl && *p == ':')
4156 {
4157 // parse optional type: "let var: type = expr"
4158 p = skipwhite(p + 1);
4159 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004160 has_type = TRUE;
4161 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004162 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004163 {
4164 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4165 type = lvar->lv_type;
4166 }
4167 }
4168
4169 sp = p;
4170 p = skipwhite(p);
4171 op = p;
4172 oplen = assignment_len(p, &heredoc);
4173 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4174 {
4175 char_u buf[4];
4176
4177 vim_strncpy(buf, op, oplen);
4178 semsg(_(e_white_both), buf);
4179 }
4180
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004181 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004182 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004183 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004184 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004185 goto theend;
4186 }
4187
Bram Moolenaar080457c2020-03-03 21:53:32 +01004188 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004189 {
4190 if (oplen > 1 && !heredoc)
4191 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004192 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004193 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4194 name);
4195 goto theend;
4196 }
4197
4198 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004199 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004200 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004201 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4202 if (idx < 0)
4203 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004204 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004205 }
4206
4207 if (heredoc)
4208 {
4209 list_T *l;
4210 listitem_T *li;
4211
4212 // [let] varname =<< [trim] {end}
4213 eap->getline = heredoc_getline;
4214 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004215 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004216
4217 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004218 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004219 {
4220 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4221 li->li_tv.vval.v_string = NULL;
4222 }
4223 generate_NEWLIST(cctx, l->lv_len);
4224 type = &t_list_string;
4225 list_free(l);
4226 p += STRLEN(p);
4227 }
4228 else if (oplen > 0)
4229 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004230 int r;
4231 type_T *stacktype;
4232 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004233
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004234 // for "+=", "*=", "..=" etc. first load the current value
4235 if (*op != '=')
4236 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004237 switch (dest)
4238 {
4239 case dest_option:
4240 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004241 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004242 break;
4243 case dest_global:
4244 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4245 break;
4246 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004247 compile_load_scriptvar(cctx,
4248 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004249 break;
4250 case dest_env:
4251 // Include $ in the name here
4252 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4253 break;
4254 case dest_reg:
4255 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4256 break;
4257 case dest_vimvar:
4258 generate_LOADV(cctx, name + 2, TRUE);
4259 break;
4260 case dest_local:
4261 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4262 break;
4263 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004264 }
4265
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004266 // Compile the expression. Temporarily hide the new local variable
4267 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004268 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004269 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004270 instr_count = instr->ga_len;
4271 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004272 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004273 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004274 ++cctx->ctx_locals.ga_len;
4275 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004276 goto theend;
4277
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004278 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004279 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004280 stack = &cctx->ctx_type_stack;
4281 stacktype = stack->ga_len == 0 ? &t_void
4282 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4283 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004284 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004285 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4286 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004287 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004288 if (stacktype->tt_type == VAR_VOID)
4289 {
4290 emsg(_("E1031: Cannot use void value"));
4291 goto theend;
4292 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004293 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004294 {
4295 // An empty list or dict has a &t_void member, for a
4296 // variable that implies &t_any.
4297 if (stacktype == &t_list_empty)
4298 lvar->lv_type = &t_list_any;
4299 else if (stacktype == &t_dict_empty)
4300 lvar->lv_type = &t_dict_any;
4301 else
4302 lvar->lv_type = stacktype;
4303 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004304 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004305 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4306 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004307 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004308 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004309 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004310 }
4311 }
4312 else if (cmdidx == CMD_const)
4313 {
4314 emsg(_("E1021: const requires a value"));
4315 goto theend;
4316 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004317 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004318 {
4319 emsg(_("E1022: type or initialization required"));
4320 goto theend;
4321 }
4322 else
4323 {
4324 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004325 if (ga_grow(instr, 1) == FAIL)
4326 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004327 switch (type->tt_type)
4328 {
4329 case VAR_BOOL:
4330 generate_PUSHBOOL(cctx, VVAL_FALSE);
4331 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004332 case VAR_FLOAT:
4333#ifdef FEAT_FLOAT
4334 generate_PUSHF(cctx, 0.0);
4335#endif
4336 break;
4337 case VAR_STRING:
4338 generate_PUSHS(cctx, NULL);
4339 break;
4340 case VAR_BLOB:
4341 generate_PUSHBLOB(cctx, NULL);
4342 break;
4343 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004344 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004345 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004346 case VAR_LIST:
4347 generate_NEWLIST(cctx, 0);
4348 break;
4349 case VAR_DICT:
4350 generate_NEWDICT(cctx, 0);
4351 break;
4352 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004353 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004354 break;
4355 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004356 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004357 break;
4358 case VAR_NUMBER:
4359 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004360 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004361 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004362 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004363 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004364 generate_PUSHNR(cctx, 0);
4365 break;
4366 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004367 }
4368
4369 if (oplen > 0 && *op != '=')
4370 {
4371 type_T *expected = &t_number;
4372 garray_T *stack = &cctx->ctx_type_stack;
4373 type_T *stacktype;
4374
4375 // TODO: if type is known use float or any operation
4376
4377 if (*op == '.')
4378 expected = &t_string;
4379 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4380 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4381 goto theend;
4382
4383 if (*op == '.')
4384 generate_instr_drop(cctx, ISN_CONCAT, 1);
4385 else
4386 {
4387 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4388
4389 if (isn == NULL)
4390 goto theend;
4391 switch (*op)
4392 {
4393 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4394 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4395 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4396 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4397 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4398 }
4399 }
4400 }
4401
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004402 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004403 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004404 case dest_option:
4405 generate_STOREOPT(cctx, name + 1, opt_flags);
4406 break;
4407 case dest_global:
4408 // include g: with the name, easier to execute that way
4409 generate_STORE(cctx, ISN_STOREG, 0, name);
4410 break;
4411 case dest_env:
4412 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4413 break;
4414 case dest_reg:
4415 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4416 break;
4417 case dest_vimvar:
4418 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4419 break;
4420 case dest_script:
4421 {
4422 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4423 imported_T *import = NULL;
4424 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004425
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004426 if (name[1] != ':')
4427 {
4428 import = find_imported(name, 0, cctx);
4429 if (import != NULL)
4430 sid = import->imp_sid;
4431 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004432
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004433 idx = get_script_item_idx(sid, rawname, TRUE);
4434 // TODO: specific type
4435 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004436 {
4437 char_u *name_s = name;
4438
4439 // Include s: in the name for store_var()
4440 if (name[1] != ':')
4441 {
4442 int len = (int)STRLEN(name) + 3;
4443
4444 name_s = alloc(len);
4445 if (name_s == NULL)
4446 name_s = name;
4447 else
4448 vim_snprintf((char *)name_s, len, "s:%s", name);
4449 }
4450 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4451 if (name_s != name)
4452 vim_free(name_s);
4453 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004454 else
4455 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4456 sid, idx, &t_any);
4457 }
4458 break;
4459 case dest_local:
4460 {
4461 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004462
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004463 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4464 // into ISN_STORENR
4465 if (instr->ga_len == instr_count + 1
4466 && isn->isn_type == ISN_PUSHNR)
4467 {
4468 varnumber_T val = isn->isn_arg.number;
4469 garray_T *stack = &cctx->ctx_type_stack;
4470
4471 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004472 isn->isn_arg.storenr.stnr_idx = idx;
4473 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004474 if (stack->ga_len > 0)
4475 --stack->ga_len;
4476 }
4477 else
4478 generate_STORE(cctx, ISN_STORE, idx, NULL);
4479 }
4480 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004481 }
4482 ret = p;
4483
4484theend:
4485 vim_free(name);
4486 return ret;
4487}
4488
4489/*
4490 * Compile an :import command.
4491 */
4492 static char_u *
4493compile_import(char_u *arg, cctx_T *cctx)
4494{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004495 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004496}
4497
4498/*
4499 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4500 */
4501 static int
4502compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4503{
4504 garray_T *instr = &cctx->ctx_instr;
4505 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4506
4507 if (endlabel == NULL)
4508 return FAIL;
4509 endlabel->el_next = *el;
4510 *el = endlabel;
4511 endlabel->el_end_label = instr->ga_len;
4512
4513 generate_JUMP(cctx, when, 0);
4514 return OK;
4515}
4516
4517 static void
4518compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4519{
4520 garray_T *instr = &cctx->ctx_instr;
4521
4522 while (*el != NULL)
4523 {
4524 endlabel_T *cur = (*el);
4525 isn_T *isn;
4526
4527 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4528 isn->isn_arg.jump.jump_where = instr->ga_len;
4529 *el = cur->el_next;
4530 vim_free(cur);
4531 }
4532}
4533
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004534 static void
4535compile_free_jump_to_end(endlabel_T **el)
4536{
4537 while (*el != NULL)
4538 {
4539 endlabel_T *cur = (*el);
4540
4541 *el = cur->el_next;
4542 vim_free(cur);
4543 }
4544}
4545
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004546/*
4547 * Create a new scope and set up the generic items.
4548 */
4549 static scope_T *
4550new_scope(cctx_T *cctx, scopetype_T type)
4551{
4552 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4553
4554 if (scope == NULL)
4555 return NULL;
4556 scope->se_outer = cctx->ctx_scope;
4557 cctx->ctx_scope = scope;
4558 scope->se_type = type;
4559 scope->se_local_count = cctx->ctx_locals.ga_len;
4560 return scope;
4561}
4562
4563/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004564 * Free the current scope and go back to the outer scope.
4565 */
4566 static void
4567drop_scope(cctx_T *cctx)
4568{
4569 scope_T *scope = cctx->ctx_scope;
4570
4571 if (scope == NULL)
4572 {
4573 iemsg("calling drop_scope() without a scope");
4574 return;
4575 }
4576 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004577 switch (scope->se_type)
4578 {
4579 case IF_SCOPE:
4580 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4581 case FOR_SCOPE:
4582 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4583 case WHILE_SCOPE:
4584 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4585 case TRY_SCOPE:
4586 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4587 case NO_SCOPE:
4588 case BLOCK_SCOPE:
4589 break;
4590 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004591 vim_free(scope);
4592}
4593
4594/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004595 * Evaluate an expression that is a constant:
4596 * has(arg)
4597 *
4598 * Also handle:
4599 * ! in front logical NOT
4600 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004601 * Return FAIL if the expression is not a constant.
4602 */
4603 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004604evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004605{
4606 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004607 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004608 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004609
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004610 /*
4611 * Skip '!' characters. They are handled later.
4612 */
4613 start_leader = *arg;
4614 while (**arg == '!')
4615 *arg = skipwhite(*arg + 1);
4616 end_leader = *arg;
4617
4618 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004619 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004620 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004621 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4622 {
4623 tv->v_type = VAR_SPECIAL;
4624 tv->vval.v_number = VVAL_TRUE;
4625 *arg += 4;
4626 return OK;
4627 }
4628 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4629 {
4630 tv->v_type = VAR_SPECIAL;
4631 tv->vval.v_number = VVAL_FALSE;
4632 *arg += 5;
4633 return OK;
4634 }
4635
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004636 if (STRNCMP("has(", *arg, 4) == 0)
4637 {
4638 has_call = TRUE;
4639 *arg = skipwhite(*arg + 4);
4640 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004641
4642 if (**arg == '"')
4643 {
4644 if (get_string_tv(arg, tv, TRUE) == FAIL)
4645 return FAIL;
4646 }
4647 else if (**arg == '\'')
4648 {
4649 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4650 return FAIL;
4651 }
4652 else
4653 return FAIL;
4654
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004655 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004656 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004657 *arg = skipwhite(*arg);
4658 if (**arg != ')')
4659 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004660 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004661
4662 argvars[0] = *tv;
4663 argvars[1].v_type = VAR_UNKNOWN;
4664 tv->v_type = VAR_NUMBER;
4665 tv->vval.v_number = 0;
4666 f_has(argvars, tv);
4667 clear_tv(&argvars[0]);
4668
4669 while (start_leader < end_leader)
4670 {
4671 if (*start_leader == '!')
4672 tv->vval.v_number = !tv->vval.v_number;
4673 ++start_leader;
4674 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004675 }
4676
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004677 return OK;
4678}
4679
Bram Moolenaar080457c2020-03-03 21:53:32 +01004680 static int
4681evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4682{
4683 exptype_T type = EXPR_UNKNOWN;
4684 char_u *p;
4685 int len = 2;
4686 int type_is = FALSE;
4687
4688 // get the first variable
4689 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4690 return FAIL;
4691
4692 p = skipwhite(*arg);
4693 type = get_compare_type(p, &len, &type_is);
4694
4695 /*
4696 * If there is a comparative operator, use it.
4697 */
4698 if (type != EXPR_UNKNOWN)
4699 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004700 typval_T tv2;
4701 char_u *s1, *s2;
4702 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4703 int n;
4704
4705 // TODO: Only string == string is supported now
4706 if (tv->v_type != VAR_STRING)
4707 return FAIL;
4708 if (type != EXPR_EQUAL)
4709 return FAIL;
4710
4711 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004712 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004713 *arg = skipwhite(p + len);
4714 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4715 || tv2.v_type != VAR_STRING)
4716 {
4717 clear_tv(&tv2);
4718 return FAIL;
4719 }
4720 s1 = tv_get_string_buf(tv, buf1);
4721 s2 = tv_get_string_buf(&tv2, buf2);
4722 n = STRCMP(s1, s2);
4723 clear_tv(tv);
4724 clear_tv(&tv2);
4725 tv->v_type = VAR_BOOL;
4726 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004727 }
4728
4729 return OK;
4730}
4731
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004732static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4733
4734/*
4735 * Compile constant || or &&.
4736 */
4737 static int
4738evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4739{
4740 char_u *p = skipwhite(*arg);
4741 int opchar = *op;
4742
4743 if (p[0] == opchar && p[1] == opchar)
4744 {
4745 int val = tv2bool(tv);
4746
4747 /*
4748 * Repeat until there is no following "||" or "&&"
4749 */
4750 while (p[0] == opchar && p[1] == opchar)
4751 {
4752 typval_T tv2;
4753
4754 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4755 return FAIL;
4756
4757 // eval the next expression
4758 *arg = skipwhite(p + 2);
4759 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004760 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004761 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004762 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004763 {
4764 clear_tv(&tv2);
4765 return FAIL;
4766 }
4767 if ((opchar == '&') == val)
4768 {
4769 // false || tv2 or true && tv2: use tv2
4770 clear_tv(tv);
4771 *tv = tv2;
4772 val = tv2bool(tv);
4773 }
4774 else
4775 clear_tv(&tv2);
4776 p = skipwhite(*arg);
4777 }
4778 }
4779
4780 return OK;
4781}
4782
4783/*
4784 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4785 * Return FAIL if the expression is not a constant.
4786 */
4787 static int
4788evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4789{
4790 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004791 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004792 return FAIL;
4793
4794 // || and && work almost the same
4795 return evaluate_const_and_or(arg, cctx, "&&", tv);
4796}
4797
4798/*
4799 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4800 * Return FAIL if the expression is not a constant.
4801 */
4802 static int
4803evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4804{
4805 // evaluate the first expression
4806 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4807 return FAIL;
4808
4809 // || and && work almost the same
4810 return evaluate_const_and_or(arg, cctx, "||", tv);
4811}
4812
4813/*
4814 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4815 * E.g. for "has('feature')".
4816 * This does not produce error messages. "tv" should be cleared afterwards.
4817 * Return FAIL if the expression is not a constant.
4818 */
4819 static int
4820evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4821{
4822 char_u *p;
4823
4824 // evaluate the first expression
4825 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4826 return FAIL;
4827
4828 p = skipwhite(*arg);
4829 if (*p == '?')
4830 {
4831 int val = tv2bool(tv);
4832 typval_T tv2;
4833
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004834 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004835 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4836 return FAIL;
4837
4838 // evaluate the second expression; any type is accepted
4839 clear_tv(tv);
4840 *arg = skipwhite(p + 1);
4841 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
4842 return FAIL;
4843
4844 // Check for the ":".
4845 p = skipwhite(*arg);
4846 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4847 return FAIL;
4848
4849 // evaluate the third expression
4850 *arg = skipwhite(p + 1);
4851 tv2.v_type = VAR_UNKNOWN;
4852 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
4853 {
4854 clear_tv(&tv2);
4855 return FAIL;
4856 }
4857 if (val)
4858 {
4859 // use the expr after "?"
4860 clear_tv(&tv2);
4861 }
4862 else
4863 {
4864 // use the expr after ":"
4865 clear_tv(tv);
4866 *tv = tv2;
4867 }
4868 }
4869 return OK;
4870}
4871
4872/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004873 * compile "if expr"
4874 *
4875 * "if expr" Produces instructions:
4876 * EVAL expr Push result of "expr"
4877 * JUMP_IF_FALSE end
4878 * ... body ...
4879 * end:
4880 *
4881 * "if expr | else" Produces instructions:
4882 * EVAL expr Push result of "expr"
4883 * JUMP_IF_FALSE else
4884 * ... body ...
4885 * JUMP_ALWAYS end
4886 * else:
4887 * ... body ...
4888 * end:
4889 *
4890 * "if expr1 | elseif expr2 | else" Produces instructions:
4891 * EVAL expr Push result of "expr"
4892 * JUMP_IF_FALSE elseif
4893 * ... body ...
4894 * JUMP_ALWAYS end
4895 * elseif:
4896 * EVAL expr Push result of "expr"
4897 * JUMP_IF_FALSE else
4898 * ... body ...
4899 * JUMP_ALWAYS end
4900 * else:
4901 * ... body ...
4902 * end:
4903 */
4904 static char_u *
4905compile_if(char_u *arg, cctx_T *cctx)
4906{
4907 char_u *p = arg;
4908 garray_T *instr = &cctx->ctx_instr;
4909 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004910 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004911
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004912 // compile "expr"; if we know it evaluates to FALSE skip the block
4913 tv.v_type = VAR_UNKNOWN;
4914 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4915 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4916 else
4917 cctx->ctx_skip = MAYBE;
4918 clear_tv(&tv);
4919 if (cctx->ctx_skip == MAYBE)
4920 {
4921 p = arg;
4922 if (compile_expr1(&p, cctx) == FAIL)
4923 return NULL;
4924 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004925
4926 scope = new_scope(cctx, IF_SCOPE);
4927 if (scope == NULL)
4928 return NULL;
4929
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004930 if (cctx->ctx_skip == MAYBE)
4931 {
4932 // "where" is set when ":elseif", "else" or ":endif" is found
4933 scope->se_u.se_if.is_if_label = instr->ga_len;
4934 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4935 }
4936 else
4937 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004938
4939 return p;
4940}
4941
4942 static char_u *
4943compile_elseif(char_u *arg, cctx_T *cctx)
4944{
4945 char_u *p = arg;
4946 garray_T *instr = &cctx->ctx_instr;
4947 isn_T *isn;
4948 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004949 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004950
4951 if (scope == NULL || scope->se_type != IF_SCOPE)
4952 {
4953 emsg(_(e_elseif_without_if));
4954 return NULL;
4955 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004956 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004957
Bram Moolenaar158906c2020-02-06 20:39:45 +01004958 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004959 {
4960 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004961 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004962 return NULL;
4963 // previous "if" or "elseif" jumps here
4964 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4965 isn->isn_arg.jump.jump_where = instr->ga_len;
4966 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004967
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004968 // compile "expr"; if we know it evaluates to FALSE skip the block
4969 tv.v_type = VAR_UNKNOWN;
4970 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4971 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4972 else
4973 cctx->ctx_skip = MAYBE;
4974 clear_tv(&tv);
4975 if (cctx->ctx_skip == MAYBE)
4976 {
4977 p = arg;
4978 if (compile_expr1(&p, cctx) == FAIL)
4979 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004980
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004981 // "where" is set when ":elseif", "else" or ":endif" is found
4982 scope->se_u.se_if.is_if_label = instr->ga_len;
4983 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4984 }
4985 else
4986 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004987
4988 return p;
4989}
4990
4991 static char_u *
4992compile_else(char_u *arg, cctx_T *cctx)
4993{
4994 char_u *p = arg;
4995 garray_T *instr = &cctx->ctx_instr;
4996 isn_T *isn;
4997 scope_T *scope = cctx->ctx_scope;
4998
4999 if (scope == NULL || scope->se_type != IF_SCOPE)
5000 {
5001 emsg(_(e_else_without_if));
5002 return NULL;
5003 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005004 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005005
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005006 // jump from previous block to the end, unless the else block is empty
5007 if (cctx->ctx_skip == MAYBE)
5008 {
5009 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005010 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005011 return NULL;
5012 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005013
Bram Moolenaar158906c2020-02-06 20:39:45 +01005014 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005015 {
5016 if (scope->se_u.se_if.is_if_label >= 0)
5017 {
5018 // previous "if" or "elseif" jumps here
5019 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5020 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005021 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005022 }
5023 }
5024
5025 if (cctx->ctx_skip != MAYBE)
5026 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005027
5028 return p;
5029}
5030
5031 static char_u *
5032compile_endif(char_u *arg, cctx_T *cctx)
5033{
5034 scope_T *scope = cctx->ctx_scope;
5035 ifscope_T *ifscope;
5036 garray_T *instr = &cctx->ctx_instr;
5037 isn_T *isn;
5038
5039 if (scope == NULL || scope->se_type != IF_SCOPE)
5040 {
5041 emsg(_(e_endif_without_if));
5042 return NULL;
5043 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005044 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005045 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005046
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005047 if (scope->se_u.se_if.is_if_label >= 0)
5048 {
5049 // previous "if" or "elseif" jumps here
5050 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5051 isn->isn_arg.jump.jump_where = instr->ga_len;
5052 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005053 // Fill in the "end" label in jumps at the end of the blocks.
5054 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005055 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005056
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005057 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005058 return arg;
5059}
5060
5061/*
5062 * compile "for var in expr"
5063 *
5064 * Produces instructions:
5065 * PUSHNR -1
5066 * STORE loop-idx Set index to -1
5067 * EVAL expr Push result of "expr"
5068 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5069 * - if beyond end, jump to "end"
5070 * - otherwise get item from list and push it
5071 * STORE var Store item in "var"
5072 * ... body ...
5073 * JUMP top Jump back to repeat
5074 * end: DROP Drop the result of "expr"
5075 *
5076 */
5077 static char_u *
5078compile_for(char_u *arg, cctx_T *cctx)
5079{
5080 char_u *p;
5081 size_t varlen;
5082 garray_T *instr = &cctx->ctx_instr;
5083 garray_T *stack = &cctx->ctx_type_stack;
5084 scope_T *scope;
5085 int loop_idx; // index of loop iteration variable
5086 int var_idx; // index of "var"
5087 type_T *vartype;
5088
5089 // TODO: list of variables: "for [key, value] in dict"
5090 // parse "var"
5091 for (p = arg; eval_isnamec1(*p); ++p)
5092 ;
5093 varlen = p - arg;
5094 var_idx = lookup_local(arg, varlen, cctx);
5095 if (var_idx >= 0)
5096 {
5097 semsg(_("E1023: variable already defined: %s"), arg);
5098 return NULL;
5099 }
5100
5101 // consume "in"
5102 p = skipwhite(p);
5103 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5104 {
5105 emsg(_(e_missing_in));
5106 return NULL;
5107 }
5108 p = skipwhite(p + 2);
5109
5110
5111 scope = new_scope(cctx, FOR_SCOPE);
5112 if (scope == NULL)
5113 return NULL;
5114
5115 // Reserve a variable to store the loop iteration counter.
5116 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5117 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005118 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005119 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005120 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005121 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005122 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005123
5124 // Reserve a variable to store "var"
5125 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5126 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005127 {
5128 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005129 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005130 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005131
5132 generate_STORENR(cctx, loop_idx, -1);
5133
5134 // compile "expr", it remains on the stack until "endfor"
5135 arg = p;
5136 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005137 {
5138 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005139 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005140 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005141
5142 // now we know the type of "var"
5143 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5144 if (vartype->tt_type != VAR_LIST)
5145 {
5146 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005147 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005148 return NULL;
5149 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005150 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005151 {
5152 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
5153
5154 lvar->lv_type = vartype->tt_member;
5155 }
5156
5157 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005158 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005159
5160 generate_FOR(cctx, loop_idx);
5161 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
5162
5163 return arg;
5164}
5165
5166/*
5167 * compile "endfor"
5168 */
5169 static char_u *
5170compile_endfor(char_u *arg, cctx_T *cctx)
5171{
5172 garray_T *instr = &cctx->ctx_instr;
5173 scope_T *scope = cctx->ctx_scope;
5174 forscope_T *forscope;
5175 isn_T *isn;
5176
5177 if (scope == NULL || scope->se_type != FOR_SCOPE)
5178 {
5179 emsg(_(e_for));
5180 return NULL;
5181 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005182 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005183 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005184 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005185
5186 // At end of ":for" scope jump back to the FOR instruction.
5187 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5188
5189 // Fill in the "end" label in the FOR statement so it can jump here
5190 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5191 isn->isn_arg.forloop.for_end = instr->ga_len;
5192
5193 // Fill in the "end" label any BREAK statements
5194 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5195
5196 // Below the ":for" scope drop the "expr" list from the stack.
5197 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5198 return NULL;
5199
5200 vim_free(scope);
5201
5202 return arg;
5203}
5204
5205/*
5206 * compile "while expr"
5207 *
5208 * Produces instructions:
5209 * top: EVAL expr Push result of "expr"
5210 * JUMP_IF_FALSE end jump if false
5211 * ... body ...
5212 * JUMP top Jump back to repeat
5213 * end:
5214 *
5215 */
5216 static char_u *
5217compile_while(char_u *arg, cctx_T *cctx)
5218{
5219 char_u *p = arg;
5220 garray_T *instr = &cctx->ctx_instr;
5221 scope_T *scope;
5222
5223 scope = new_scope(cctx, WHILE_SCOPE);
5224 if (scope == NULL)
5225 return NULL;
5226
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005227 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005228
5229 // compile "expr"
5230 if (compile_expr1(&p, cctx) == FAIL)
5231 return NULL;
5232
5233 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005234 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005235 JUMP_IF_FALSE, cctx) == FAIL)
5236 return FAIL;
5237
5238 return p;
5239}
5240
5241/*
5242 * compile "endwhile"
5243 */
5244 static char_u *
5245compile_endwhile(char_u *arg, cctx_T *cctx)
5246{
5247 scope_T *scope = cctx->ctx_scope;
5248
5249 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5250 {
5251 emsg(_(e_while));
5252 return NULL;
5253 }
5254 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005255 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005256
5257 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005258 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005259
5260 // Fill in the "end" label in the WHILE statement so it can jump here.
5261 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005262 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005263
5264 vim_free(scope);
5265
5266 return arg;
5267}
5268
5269/*
5270 * compile "continue"
5271 */
5272 static char_u *
5273compile_continue(char_u *arg, cctx_T *cctx)
5274{
5275 scope_T *scope = cctx->ctx_scope;
5276
5277 for (;;)
5278 {
5279 if (scope == NULL)
5280 {
5281 emsg(_(e_continue));
5282 return NULL;
5283 }
5284 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5285 break;
5286 scope = scope->se_outer;
5287 }
5288
5289 // Jump back to the FOR or WHILE instruction.
5290 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005291 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5292 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005293 return arg;
5294}
5295
5296/*
5297 * compile "break"
5298 */
5299 static char_u *
5300compile_break(char_u *arg, cctx_T *cctx)
5301{
5302 scope_T *scope = cctx->ctx_scope;
5303 endlabel_T **el;
5304
5305 for (;;)
5306 {
5307 if (scope == NULL)
5308 {
5309 emsg(_(e_break));
5310 return NULL;
5311 }
5312 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5313 break;
5314 scope = scope->se_outer;
5315 }
5316
5317 // Jump to the end of the FOR or WHILE loop.
5318 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005319 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005320 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005321 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005322 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5323 return FAIL;
5324
5325 return arg;
5326}
5327
5328/*
5329 * compile "{" start of block
5330 */
5331 static char_u *
5332compile_block(char_u *arg, cctx_T *cctx)
5333{
5334 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5335 return NULL;
5336 return skipwhite(arg + 1);
5337}
5338
5339/*
5340 * compile end of block: drop one scope
5341 */
5342 static void
5343compile_endblock(cctx_T *cctx)
5344{
5345 scope_T *scope = cctx->ctx_scope;
5346
5347 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005348 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005349 vim_free(scope);
5350}
5351
5352/*
5353 * compile "try"
5354 * Creates a new scope for the try-endtry, pointing to the first catch and
5355 * finally.
5356 * Creates another scope for the "try" block itself.
5357 * TRY instruction sets up exception handling at runtime.
5358 *
5359 * "try"
5360 * TRY -> catch1, -> finally push trystack entry
5361 * ... try block
5362 * "throw {exception}"
5363 * EVAL {exception}
5364 * THROW create exception
5365 * ... try block
5366 * " catch {expr}"
5367 * JUMP -> finally
5368 * catch1: PUSH exeception
5369 * EVAL {expr}
5370 * MATCH
5371 * JUMP nomatch -> catch2
5372 * CATCH remove exception
5373 * ... catch block
5374 * " catch"
5375 * JUMP -> finally
5376 * catch2: CATCH remove exception
5377 * ... catch block
5378 * " finally"
5379 * finally:
5380 * ... finally block
5381 * " endtry"
5382 * ENDTRY pop trystack entry, may rethrow
5383 */
5384 static char_u *
5385compile_try(char_u *arg, cctx_T *cctx)
5386{
5387 garray_T *instr = &cctx->ctx_instr;
5388 scope_T *try_scope;
5389 scope_T *scope;
5390
5391 // scope that holds the jumps that go to catch/finally/endtry
5392 try_scope = new_scope(cctx, TRY_SCOPE);
5393 if (try_scope == NULL)
5394 return NULL;
5395
5396 // "catch" is set when the first ":catch" is found.
5397 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005398 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005399 if (generate_instr(cctx, ISN_TRY) == NULL)
5400 return NULL;
5401
5402 // scope for the try block itself
5403 scope = new_scope(cctx, BLOCK_SCOPE);
5404 if (scope == NULL)
5405 return NULL;
5406
5407 return arg;
5408}
5409
5410/*
5411 * compile "catch {expr}"
5412 */
5413 static char_u *
5414compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5415{
5416 scope_T *scope = cctx->ctx_scope;
5417 garray_T *instr = &cctx->ctx_instr;
5418 char_u *p;
5419 isn_T *isn;
5420
5421 // end block scope from :try or :catch
5422 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5423 compile_endblock(cctx);
5424 scope = cctx->ctx_scope;
5425
5426 // Error if not in a :try scope
5427 if (scope == NULL || scope->se_type != TRY_SCOPE)
5428 {
5429 emsg(_(e_catch));
5430 return NULL;
5431 }
5432
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005433 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005434 {
5435 emsg(_("E1033: catch unreachable after catch-all"));
5436 return NULL;
5437 }
5438
5439 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005440 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005441 JUMP_ALWAYS, cctx) == FAIL)
5442 return NULL;
5443
5444 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005445 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005446 if (isn->isn_arg.try.try_catch == 0)
5447 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005448 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005449 {
5450 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005451 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005452 isn->isn_arg.jump.jump_where = instr->ga_len;
5453 }
5454
5455 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005456 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005457 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005458 scope->se_u.se_try.ts_caught_all = TRUE;
5459 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005460 }
5461 else
5462 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005463 char_u *end;
5464 char_u *pat;
5465 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005466 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005467 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005468
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005469 // Push v:exception, push {expr} and MATCH
5470 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5471
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005472 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005473 if (*end != *p)
5474 {
5475 semsg(_("E1067: Separator mismatch: %s"), p);
5476 vim_free(tofree);
5477 return FAIL;
5478 }
5479 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005480 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005481 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005482 len = (int)(end - tofree);
5483 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005484 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005485 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005486 if (pat == NULL)
5487 return FAIL;
5488 if (generate_PUSHS(cctx, pat) == FAIL)
5489 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005490
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005491 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5492 return NULL;
5493
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005494 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005495 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5496 return NULL;
5497 }
5498
5499 if (generate_instr(cctx, ISN_CATCH) == NULL)
5500 return NULL;
5501
5502 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5503 return NULL;
5504 return p;
5505}
5506
5507 static char_u *
5508compile_finally(char_u *arg, cctx_T *cctx)
5509{
5510 scope_T *scope = cctx->ctx_scope;
5511 garray_T *instr = &cctx->ctx_instr;
5512 isn_T *isn;
5513
5514 // end block scope from :try or :catch
5515 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5516 compile_endblock(cctx);
5517 scope = cctx->ctx_scope;
5518
5519 // Error if not in a :try scope
5520 if (scope == NULL || scope->se_type != TRY_SCOPE)
5521 {
5522 emsg(_(e_finally));
5523 return NULL;
5524 }
5525
5526 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005527 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005528 if (isn->isn_arg.try.try_finally != 0)
5529 {
5530 emsg(_(e_finally_dup));
5531 return NULL;
5532 }
5533
5534 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005535 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005536
Bram Moolenaar585fea72020-04-02 22:33:21 +02005537 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005538 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005539 {
5540 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005541 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005542 isn->isn_arg.jump.jump_where = instr->ga_len;
5543 }
5544
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005545 // TODO: set index in ts_finally_label jumps
5546
5547 return arg;
5548}
5549
5550 static char_u *
5551compile_endtry(char_u *arg, cctx_T *cctx)
5552{
5553 scope_T *scope = cctx->ctx_scope;
5554 garray_T *instr = &cctx->ctx_instr;
5555 isn_T *isn;
5556
5557 // end block scope from :catch or :finally
5558 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5559 compile_endblock(cctx);
5560 scope = cctx->ctx_scope;
5561
5562 // Error if not in a :try scope
5563 if (scope == NULL || scope->se_type != TRY_SCOPE)
5564 {
5565 if (scope == NULL)
5566 emsg(_(e_no_endtry));
5567 else if (scope->se_type == WHILE_SCOPE)
5568 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005569 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005570 emsg(_(e_endfor));
5571 else
5572 emsg(_(e_endif));
5573 return NULL;
5574 }
5575
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005576 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005577 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5578 {
5579 emsg(_("E1032: missing :catch or :finally"));
5580 return NULL;
5581 }
5582
5583 // Fill in the "end" label in jumps at the end of the blocks, if not done
5584 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005585 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005586
5587 // End :catch or :finally scope: set value in ISN_TRY instruction
5588 if (isn->isn_arg.try.try_finally == 0)
5589 isn->isn_arg.try.try_finally = instr->ga_len;
5590 compile_endblock(cctx);
5591
5592 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5593 return NULL;
5594 return arg;
5595}
5596
5597/*
5598 * compile "throw {expr}"
5599 */
5600 static char_u *
5601compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5602{
5603 char_u *p = skipwhite(arg);
5604
5605 if (ends_excmd(*p))
5606 {
5607 emsg(_(e_argreq));
5608 return NULL;
5609 }
5610 if (compile_expr1(&p, cctx) == FAIL)
5611 return NULL;
5612 if (may_generate_2STRING(-1, cctx) == FAIL)
5613 return NULL;
5614 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5615 return NULL;
5616
5617 return p;
5618}
5619
5620/*
5621 * compile "echo expr"
5622 */
5623 static char_u *
5624compile_echo(char_u *arg, int with_white, cctx_T *cctx)
5625{
5626 char_u *p = arg;
5627 int count = 0;
5628
Bram Moolenaarad39c092020-02-26 18:23:43 +01005629 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005630 {
5631 if (compile_expr1(&p, cctx) == FAIL)
5632 return NULL;
5633 ++count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005634 p = skipwhite(p);
5635 if (ends_excmd(*p))
5636 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005637 }
5638
5639 generate_ECHO(cctx, with_white, count);
Bram Moolenaarad39c092020-02-26 18:23:43 +01005640 return p;
5641}
5642
5643/*
5644 * compile "execute expr"
5645 */
5646 static char_u *
5647compile_execute(char_u *arg, cctx_T *cctx)
5648{
5649 char_u *p = arg;
5650 int count = 0;
5651
5652 for (;;)
5653 {
5654 if (compile_expr1(&p, cctx) == FAIL)
5655 return NULL;
5656 ++count;
5657 p = skipwhite(p);
5658 if (ends_excmd(*p))
5659 break;
5660 }
5661
5662 generate_EXECUTE(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005663
5664 return p;
5665}
5666
5667/*
5668 * After ex_function() has collected all the function lines: parse and compile
5669 * the lines into instructions.
5670 * Adds the function to "def_functions".
5671 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5672 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005673 * This can be used recursively through compile_lambda(), which may reallocate
5674 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005675 */
5676 void
5677compile_def_function(ufunc_T *ufunc, int set_return_type)
5678{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005679 char_u *line = NULL;
5680 char_u *p;
5681 exarg_T ea;
5682 char *errormsg = NULL; // error message
5683 int had_return = FALSE;
5684 cctx_T cctx;
5685 garray_T *instr;
5686 int called_emsg_before = called_emsg;
5687 int ret = FAIL;
5688 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005689 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005690
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005691 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005692 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005693
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005694 if (ufunc->uf_dfunc_idx >= 0)
5695 {
5696 // Redefining a function that was compiled before.
5697 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5698
5699 // Free old instructions.
5700 delete_def_function_contents(dfunc);
5701 }
5702 else
5703 {
5704 // Add the function to "def_functions".
5705 if (ga_grow(&def_functions, 1) == FAIL)
5706 return;
5707 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005708 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005709 dfunc->df_idx = def_functions.ga_len;
5710 ufunc->uf_dfunc_idx = dfunc->df_idx;
5711 dfunc->df_ufunc = ufunc;
5712 ++def_functions.ga_len;
5713 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005714 }
5715
Bram Moolenaara80faa82020-04-12 19:37:17 +02005716 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005717 cctx.ctx_ufunc = ufunc;
5718 cctx.ctx_lnum = -1;
5719 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5720 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5721 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5722 cctx.ctx_type_list = &ufunc->uf_type_list;
5723 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5724 instr = &cctx.ctx_instr;
5725
5726 // Most modern script version.
5727 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5728
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005729 if (ufunc->uf_def_args.ga_len > 0)
5730 {
5731 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005732 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005733 int i;
5734 char_u *arg;
5735 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5736
5737 // Produce instructions for the default values of optional arguments.
5738 // Store the instruction index in uf_def_arg_idx[] so that we know
5739 // where to start when the function is called, depending on the number
5740 // of arguments.
5741 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5742 if (ufunc->uf_def_arg_idx == NULL)
5743 goto erret;
5744 for (i = 0; i < count; ++i)
5745 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005746 garray_T *stack = &cctx.ctx_type_stack;
5747 type_T *val_type;
5748 int arg_idx = first_def_arg + i;
5749
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005750 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5751 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005752 if (compile_expr1(&arg, &cctx) == FAIL)
5753 goto erret;
5754
5755 // If no type specified use the type of the default value.
5756 // Otherwise check that the default value type matches the
5757 // specified type.
5758 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5759 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
5760 ufunc->uf_arg_types[arg_idx] = val_type;
5761 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
5762 == FAIL)
5763 {
5764 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
5765 arg_idx + 1);
5766 goto erret;
5767 }
5768
5769 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005770 goto erret;
5771 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005772 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5773 }
5774
5775 /*
5776 * Loop over all the lines of the function and generate instructions.
5777 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005778 for (;;)
5779 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005780 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005781
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005782 // Bail out on the first error to avoid a flood of errors and report
5783 // the right line number when inside try/catch.
5784 if (emsg_before != called_emsg)
5785 goto erret;
5786
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005787 if (line != NULL && *line == '|')
5788 // the line continues after a '|'
5789 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02005790 else if (line != NULL && *line != NUL
5791 && !(*line == '#' && (line == cctx.ctx_line_start
5792 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005793 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005794 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005795 goto erret;
5796 }
5797 else
5798 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02005799 line = next_line_from_context(&cctx);
5800 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005801 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005802 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005803 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005804 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005805
5806 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005807 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005808 ea.cmdlinep = &line;
5809 ea.cmd = skipwhite(line);
5810
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005811 // Some things can be recognized by the first character.
5812 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005813 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005814 case '#':
5815 // "#" starts a comment, but not "#{".
5816 if (ea.cmd[1] != '{')
5817 {
5818 line = (char_u *)"";
5819 continue;
5820 }
5821 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005822
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005823 case '}':
5824 {
5825 // "}" ends a block scope
5826 scopetype_T stype = cctx.ctx_scope == NULL
5827 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005828
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005829 if (stype == BLOCK_SCOPE)
5830 {
5831 compile_endblock(&cctx);
5832 line = ea.cmd;
5833 }
5834 else
5835 {
5836 emsg(_("E1025: using } outside of a block scope"));
5837 goto erret;
5838 }
5839 if (line != NULL)
5840 line = skipwhite(ea.cmd + 1);
5841 continue;
5842 }
5843
5844 case '{':
5845 // "{" starts a block scope
5846 // "{'a': 1}->func() is something else
5847 if (ends_excmd(*skipwhite(ea.cmd + 1)))
5848 {
5849 line = compile_block(ea.cmd, &cctx);
5850 continue;
5851 }
5852 break;
5853
5854 case ':':
5855 is_ex_command = TRUE;
5856 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005857 }
5858
5859 /*
5860 * COMMAND MODIFIERS
5861 */
5862 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
5863 {
5864 if (errormsg != NULL)
5865 goto erret;
5866 // empty line or comment
5867 line = (char_u *)"";
5868 continue;
5869 }
5870
5871 // Skip ":call" to get to the function name.
5872 if (checkforcmd(&ea.cmd, "call", 3))
5873 ea.cmd = skipwhite(ea.cmd);
5874
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005875 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005876 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005877 // Assuming the command starts with a variable or function name,
5878 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
5879 // val".
5880 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
5881 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005882 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02005883 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005884 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005885 int oplen;
5886 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005887
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005888 oplen = assignment_len(skipwhite(p), &heredoc);
5889 if (oplen > 0)
5890 {
5891 // Recognize an assignment if we recognize the variable
5892 // name:
5893 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005894 // "local = expr" where "local" is a local var.
5895 // "script = expr" where "script" is a script-local var.
5896 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005897 // "&opt = expr"
5898 // "$ENV = expr"
5899 // "@r = expr"
5900 if (*ea.cmd == '&'
5901 || *ea.cmd == '$'
5902 || *ea.cmd == '@'
5903 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
5904 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
5905 || lookup_script(ea.cmd, p - ea.cmd) == OK
5906 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
5907 {
5908 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
5909 if (line == NULL)
5910 goto erret;
5911 continue;
5912 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005913 }
5914 }
5915 }
5916
5917 /*
5918 * COMMAND after range
5919 */
5920 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005921 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
5922 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005923
5924 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
5925 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005926 if (cctx.ctx_skip == TRUE)
5927 {
5928 line += STRLEN(line);
5929 continue;
5930 }
5931
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005932 // Expression or function call.
5933 if (ea.cmdidx == CMD_eval)
5934 {
5935 p = ea.cmd;
5936 if (compile_expr1(&p, &cctx) == FAIL)
5937 goto erret;
5938
5939 // drop the return value
5940 generate_instr_drop(&cctx, ISN_DROP, 1);
5941 line = p;
5942 continue;
5943 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02005944 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005945 iemsg("Command from find_ex_command() not handled");
5946 goto erret;
5947 }
5948
5949 p = skipwhite(p);
5950
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005951 if (cctx.ctx_skip == TRUE
5952 && ea.cmdidx != CMD_elseif
5953 && ea.cmdidx != CMD_else
5954 && ea.cmdidx != CMD_endif)
5955 {
5956 line += STRLEN(line);
5957 continue;
5958 }
5959
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005960 switch (ea.cmdidx)
5961 {
5962 case CMD_def:
5963 case CMD_function:
5964 // TODO: Nested function
5965 emsg("Nested function not implemented yet");
5966 goto erret;
5967
5968 case CMD_return:
5969 line = compile_return(p, set_return_type, &cctx);
5970 had_return = TRUE;
5971 break;
5972
5973 case CMD_let:
5974 case CMD_const:
5975 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
5976 break;
5977
5978 case CMD_import:
5979 line = compile_import(p, &cctx);
5980 break;
5981
5982 case CMD_if:
5983 line = compile_if(p, &cctx);
5984 break;
5985 case CMD_elseif:
5986 line = compile_elseif(p, &cctx);
5987 break;
5988 case CMD_else:
5989 line = compile_else(p, &cctx);
5990 break;
5991 case CMD_endif:
5992 line = compile_endif(p, &cctx);
5993 break;
5994
5995 case CMD_while:
5996 line = compile_while(p, &cctx);
5997 break;
5998 case CMD_endwhile:
5999 line = compile_endwhile(p, &cctx);
6000 break;
6001
6002 case CMD_for:
6003 line = compile_for(p, &cctx);
6004 break;
6005 case CMD_endfor:
6006 line = compile_endfor(p, &cctx);
6007 break;
6008 case CMD_continue:
6009 line = compile_continue(p, &cctx);
6010 break;
6011 case CMD_break:
6012 line = compile_break(p, &cctx);
6013 break;
6014
6015 case CMD_try:
6016 line = compile_try(p, &cctx);
6017 break;
6018 case CMD_catch:
6019 line = compile_catch(p, &cctx);
6020 break;
6021 case CMD_finally:
6022 line = compile_finally(p, &cctx);
6023 break;
6024 case CMD_endtry:
6025 line = compile_endtry(p, &cctx);
6026 break;
6027 case CMD_throw:
6028 line = compile_throw(p, &cctx);
6029 break;
6030
6031 case CMD_echo:
6032 line = compile_echo(p, TRUE, &cctx);
6033 break;
6034 case CMD_echon:
6035 line = compile_echo(p, FALSE, &cctx);
6036 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01006037 case CMD_execute:
6038 line = compile_execute(p, &cctx);
6039 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006040
6041 default:
6042 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01006043 // TODO:
6044 // CMD_echomsg
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01006045 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006046 generate_EXEC(&cctx, line);
6047 line = (char_u *)"";
6048 break;
6049 }
6050 if (line == NULL)
6051 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006052 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006053
6054 if (cctx.ctx_type_stack.ga_len < 0)
6055 {
6056 iemsg("Type stack underflow");
6057 goto erret;
6058 }
6059 }
6060
6061 if (cctx.ctx_scope != NULL)
6062 {
6063 if (cctx.ctx_scope->se_type == IF_SCOPE)
6064 emsg(_(e_endif));
6065 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6066 emsg(_(e_endwhile));
6067 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6068 emsg(_(e_endfor));
6069 else
6070 emsg(_("E1026: Missing }"));
6071 goto erret;
6072 }
6073
6074 if (!had_return)
6075 {
6076 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6077 {
6078 emsg(_("E1027: Missing return statement"));
6079 goto erret;
6080 }
6081
6082 // Return zero if there is no return at the end.
6083 generate_PUSHNR(&cctx, 0);
6084 generate_instr(&cctx, ISN_RETURN);
6085 }
6086
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006087 {
6088 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6089 + ufunc->uf_dfunc_idx;
6090 dfunc->df_deleted = FALSE;
6091 dfunc->df_instr = instr->ga_data;
6092 dfunc->df_instr_count = instr->ga_len;
6093 dfunc->df_varcount = cctx.ctx_max_local;
6094 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006095
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006096 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006097 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006098 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006099
6100 // Create a type for the function, with the return type and any
6101 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006102 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6103 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006104 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006105 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006106 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6107 argcount, &ufunc->uf_type_list);
6108 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006109 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006110 argcount + varargs,
6111 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006112 {
6113 ret = FAIL;
6114 goto erret;
6115 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006116 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6117 ufunc->uf_func_type->tt_min_argcount =
6118 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006119 if (ufunc->uf_arg_types == NULL)
6120 {
6121 int i;
6122
6123 // lambda does not have argument types.
6124 for (i = 0; i < argcount; ++i)
6125 ufunc->uf_func_type->tt_args[i] = &t_any;
6126 }
6127 else
6128 mch_memmove(ufunc->uf_func_type->tt_args,
6129 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006130 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006131 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006132 ufunc->uf_func_type->tt_args[argcount] =
6133 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006134 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6135 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006136 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006137 else
6138 // No arguments, can use a predefined type.
6139 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6140 argcount, &ufunc->uf_type_list);
6141
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006142 }
6143
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006144 ret = OK;
6145
6146erret:
6147 if (ret == FAIL)
6148 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006149 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006150 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6151 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006152
6153 for (idx = 0; idx < instr->ga_len; ++idx)
6154 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006155 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006156
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006157 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006158 if (!dfunc->df_deleted)
6159 --def_functions.ga_len;
6160
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006161 while (cctx.ctx_scope != NULL)
6162 drop_scope(&cctx);
6163
Bram Moolenaar20431c92020-03-20 18:39:46 +01006164 // Don't execute this function body.
6165 ga_clear_strings(&ufunc->uf_lines);
6166
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006167 if (errormsg != NULL)
6168 emsg(errormsg);
6169 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006170 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006171 }
6172
6173 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006174 free_imported(&cctx);
6175 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006176 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006177}
6178
6179/*
6180 * Delete an instruction, free what it contains.
6181 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006182 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006183delete_instr(isn_T *isn)
6184{
6185 switch (isn->isn_type)
6186 {
6187 case ISN_EXEC:
6188 case ISN_LOADENV:
6189 case ISN_LOADG:
6190 case ISN_LOADOPT:
6191 case ISN_MEMBER:
6192 case ISN_PUSHEXC:
6193 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006194 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006195 case ISN_STOREG:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006196 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006197 vim_free(isn->isn_arg.string);
6198 break;
6199
6200 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006201 case ISN_STORES:
6202 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006203 break;
6204
6205 case ISN_STOREOPT:
6206 vim_free(isn->isn_arg.storeopt.so_name);
6207 break;
6208
6209 case ISN_PUSHBLOB: // push blob isn_arg.blob
6210 blob_unref(isn->isn_arg.blob);
6211 break;
6212
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006213 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006214#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006215 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006216#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006217 break;
6218
6219 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006220#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006221 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006222#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006223 break;
6224
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006225 case ISN_UCALL:
6226 vim_free(isn->isn_arg.ufunc.cuf_name);
6227 break;
6228
6229 case ISN_2BOOL:
6230 case ISN_2STRING:
6231 case ISN_ADDBLOB:
6232 case ISN_ADDLIST:
6233 case ISN_BCALL:
6234 case ISN_CATCH:
6235 case ISN_CHECKNR:
6236 case ISN_CHECKTYPE:
6237 case ISN_COMPAREANY:
6238 case ISN_COMPAREBLOB:
6239 case ISN_COMPAREBOOL:
6240 case ISN_COMPAREDICT:
6241 case ISN_COMPAREFLOAT:
6242 case ISN_COMPAREFUNC:
6243 case ISN_COMPARELIST:
6244 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006245 case ISN_COMPARESPECIAL:
6246 case ISN_COMPARESTRING:
6247 case ISN_CONCAT:
6248 case ISN_DCALL:
6249 case ISN_DROP:
6250 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006251 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006252 case ISN_ENDTRY:
6253 case ISN_FOR:
6254 case ISN_FUNCREF:
6255 case ISN_INDEX:
6256 case ISN_JUMP:
6257 case ISN_LOAD:
6258 case ISN_LOADSCRIPT:
6259 case ISN_LOADREG:
6260 case ISN_LOADV:
6261 case ISN_NEGATENR:
6262 case ISN_NEWDICT:
6263 case ISN_NEWLIST:
6264 case ISN_OPNR:
6265 case ISN_OPFLOAT:
6266 case ISN_OPANY:
6267 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006268 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006269 case ISN_PUSHF:
6270 case ISN_PUSHNR:
6271 case ISN_PUSHBOOL:
6272 case ISN_PUSHSPEC:
6273 case ISN_RETURN:
6274 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006275 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006276 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006277 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006278 case ISN_STORESCRIPT:
6279 case ISN_THROW:
6280 case ISN_TRY:
6281 // nothing allocated
6282 break;
6283 }
6284}
6285
6286/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006287 * Free all instructions for "dfunc".
6288 */
6289 static void
6290delete_def_function_contents(dfunc_T *dfunc)
6291{
6292 int idx;
6293
6294 ga_clear(&dfunc->df_def_args_isn);
6295
6296 if (dfunc->df_instr != NULL)
6297 {
6298 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6299 delete_instr(dfunc->df_instr + idx);
6300 VIM_CLEAR(dfunc->df_instr);
6301 }
6302
6303 dfunc->df_deleted = TRUE;
6304}
6305
6306/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006307 * When a user function is deleted, delete any associated def function.
6308 */
6309 void
6310delete_def_function(ufunc_T *ufunc)
6311{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006312 if (ufunc->uf_dfunc_idx >= 0)
6313 {
6314 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6315 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006316
Bram Moolenaar20431c92020-03-20 18:39:46 +01006317 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006318 }
6319}
6320
6321#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006322/*
6323 * Free all functions defined with ":def".
6324 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006325 void
6326free_def_functions(void)
6327{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006328 int idx;
6329
6330 for (idx = 0; idx < def_functions.ga_len; ++idx)
6331 {
6332 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6333
6334 delete_def_function_contents(dfunc);
6335 }
6336
6337 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006338}
6339#endif
6340
6341
6342#endif // FEAT_EVAL