blob: aa3cd07d3d1fff295877df313891871e0400517a [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9compile.c: :def and dealing with instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#define DEFINE_VIM9_GLOBALS
24#include "vim9.h"
25
26/*
27 * Chain of jump instructions where the end label needs to be set.
28 */
29typedef struct endlabel_S endlabel_T;
30struct endlabel_S {
31 endlabel_T *el_next; // chain end_label locations
32 int el_end_label; // instruction idx where to set end
33};
34
35/*
36 * info specific for the scope of :if / elseif / else
37 */
38typedef struct {
39 int is_if_label; // instruction idx at IF or ELSEIF
40 endlabel_T *is_end_label; // instructions to set end label
41} ifscope_T;
42
43/*
44 * info specific for the scope of :while
45 */
46typedef struct {
47 int ws_top_label; // instruction idx at WHILE
48 endlabel_T *ws_end_label; // instructions to set end
49} whilescope_T;
50
51/*
52 * info specific for the scope of :for
53 */
54typedef struct {
55 int fs_top_label; // instruction idx at FOR
56 endlabel_T *fs_end_label; // break instructions
57} forscope_T;
58
59/*
60 * info specific for the scope of :try
61 */
62typedef struct {
63 int ts_try_label; // instruction idx at TRY
64 endlabel_T *ts_end_label; // jump to :finally or :endtry
65 int ts_catch_label; // instruction idx of last CATCH
66 int ts_caught_all; // "catch" without argument encountered
67} tryscope_T;
68
69typedef enum {
70 NO_SCOPE,
71 IF_SCOPE,
72 WHILE_SCOPE,
73 FOR_SCOPE,
74 TRY_SCOPE,
75 BLOCK_SCOPE
76} scopetype_T;
77
78/*
79 * Info for one scope, pointed to by "ctx_scope".
80 */
81typedef struct scope_S scope_T;
82struct scope_S {
83 scope_T *se_outer; // scope containing this one
84 scopetype_T se_type;
85 int se_local_count; // ctx_locals.ga_len before scope
86 union {
87 ifscope_T se_if;
88 whilescope_T se_while;
89 forscope_T se_for;
90 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +010091 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010092};
93
94/*
95 * Entry for "ctx_locals". Used for arguments and local variables.
96 */
97typedef struct {
98 char_u *lv_name;
99 type_T *lv_type;
100 int lv_const; // when TRUE cannot be assigned to
101 int lv_arg; // when TRUE this is an argument
102} lvar_T;
103
104/*
105 * Context for compiling lines of Vim script.
106 * Stores info about the local variables and condition stack.
107 */
108struct cctx_S {
109 ufunc_T *ctx_ufunc; // current function
110 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200111 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100112 garray_T ctx_instr; // generated instructions
113
114 garray_T ctx_locals; // currently visible local variables
115 int ctx_max_local; // maximum number of locals at one time
116
117 garray_T ctx_imports; // imported items
118
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100119 int ctx_skip; // when TRUE skip commands, when FALSE skip
120 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100121 scope_T *ctx_scope; // current scope, NULL at toplevel
122
123 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200124 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100125};
126
127static char e_var_notfound[] = N_("E1001: variable not found: %s");
128static char e_syntax_at[] = N_("E1002: Syntax error at %s");
129
130static int compile_expr1(char_u **arg, cctx_T *cctx);
131static int compile_expr2(char_u **arg, cctx_T *cctx);
132static int compile_expr3(char_u **arg, cctx_T *cctx);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100133static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200134static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
135static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100136
137/*
138 * Lookup variable "name" in the local scope and return the index.
139 */
140 static int
141lookup_local(char_u *name, size_t len, cctx_T *cctx)
142{
143 int idx;
144
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100145 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146 return -1;
147 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
148 {
149 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
150
151 if (STRNCMP(name, lvar->lv_name, len) == 0
152 && STRLEN(lvar->lv_name) == len)
153 return idx;
154 }
155 return -1;
156}
157
158/*
159 * Lookup an argument in the current function.
160 * Returns the argument index or -1 if not found.
161 */
162 static int
163lookup_arg(char_u *name, size_t len, cctx_T *cctx)
164{
165 int idx;
166
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100167 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100168 return -1;
169 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
170 {
171 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
172
173 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
174 return idx;
175 }
176 return -1;
177}
178
179/*
180 * Lookup a vararg argument in the current function.
181 * Returns TRUE if there is a match.
182 */
183 static int
184lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
185{
186 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
187
188 return len > 0 && va_name != NULL
189 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
190}
191
192/*
193 * Lookup a variable in the current script.
194 * Returns OK or FAIL.
195 */
196 static int
197lookup_script(char_u *name, size_t len)
198{
199 int cc;
200 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
201 dictitem_T *di;
202
203 cc = name[len];
204 name[len] = NUL;
205 di = find_var_in_ht(ht, 0, name, TRUE);
206 name[len] = cc;
207 return di == NULL ? FAIL: OK;
208}
209
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100210/*
211 * Check if "p[len]" is already defined, either in script "import_sid" or in
212 * compilation context "cctx".
213 * Return FAIL and give an error if it defined.
214 */
215 int
216check_defined(char_u *p, int len, cctx_T *cctx)
217{
218 if (lookup_script(p, len) == OK
219 || (cctx != NULL
220 && (lookup_local(p, len, cctx) >= 0
221 || find_imported(p, len, cctx) != NULL)))
222 {
223 semsg("E1073: imported name already defined: %s", p);
224 return FAIL;
225 }
226 return OK;
227}
228
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200229/*
230 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
231 * be freed later.
232 */
233 static type_T *
234alloc_type(garray_T *type_gap)
235{
236 type_T *type;
237
238 if (ga_grow(type_gap, 1) == FAIL)
239 return NULL;
240 type = ALLOC_CLEAR_ONE(type_T);
241 if (type != NULL)
242 {
243 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
244 ++type_gap->ga_len;
245 }
246 return type;
247}
248
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100249 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200250get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100251{
252 type_T *type;
253
254 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200255 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100256 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200257 if (member_type->tt_type == VAR_VOID
258 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100259 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100260 if (member_type->tt_type == VAR_BOOL)
261 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100262 if (member_type->tt_type == VAR_NUMBER)
263 return &t_list_number;
264 if (member_type->tt_type == VAR_STRING)
265 return &t_list_string;
266
267 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200268 type = alloc_type(type_gap);
269 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100270 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 type->tt_type = VAR_LIST;
272 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200273 type->tt_argcount = 0;
274 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100275 return type;
276}
277
278 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200279get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100280{
281 type_T *type;
282
283 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200284 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100285 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200286 if (member_type->tt_type == VAR_VOID
287 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100288 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100289 if (member_type->tt_type == VAR_BOOL)
290 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100291 if (member_type->tt_type == VAR_NUMBER)
292 return &t_dict_number;
293 if (member_type->tt_type == VAR_STRING)
294 return &t_dict_string;
295
296 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200297 type = alloc_type(type_gap);
298 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100299 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100300 type->tt_type = VAR_DICT;
301 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200302 type->tt_argcount = 0;
303 type->tt_args = NULL;
304 return type;
305}
306
307/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200308 * Allocate a new type for a function.
309 */
310 static type_T *
311alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
312{
313 type_T *type = alloc_type(type_gap);
314
315 if (type == NULL)
316 return &t_any;
317 type->tt_type = VAR_FUNC;
318 type->tt_member = ret_type;
319 type->tt_argcount = argcount;
320 type->tt_args = NULL;
321 return type;
322}
323
324/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200325 * Get a function type, based on the return type "ret_type".
326 * If "argcount" is -1 or 0 a predefined type can be used.
327 * If "argcount" > 0 always create a new type, so that arguments can be added.
328 */
329 static type_T *
330get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
331{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200332 // recognize commonly used types
333 if (argcount <= 0)
334 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200335 if (ret_type == &t_unknown)
336 {
337 // (argcount == 0) is not possible
338 return &t_func_unknown;
339 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200340 if (ret_type == &t_void)
341 {
342 if (argcount == 0)
343 return &t_func_0_void;
344 else
345 return &t_func_void;
346 }
347 if (ret_type == &t_any)
348 {
349 if (argcount == 0)
350 return &t_func_0_any;
351 else
352 return &t_func_any;
353 }
354 if (ret_type == &t_number)
355 {
356 if (argcount == 0)
357 return &t_func_0_number;
358 else
359 return &t_func_number;
360 }
361 if (ret_type == &t_string)
362 {
363 if (argcount == 0)
364 return &t_func_0_string;
365 else
366 return &t_func_string;
367 }
368 }
369
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200370 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100371}
372
Bram Moolenaara8c17702020-04-01 21:17:24 +0200373/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200374 * For a function type, reserve space for "argcount" argument types (including
375 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200376 */
377 static int
378func_type_add_arg_types(
379 type_T *functype,
380 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200381 garray_T *type_gap)
382{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200383 // To make it easy to free the space needed for the argument types, add the
384 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200385 if (ga_grow(type_gap, 1) == FAIL)
386 return FAIL;
387 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
388 if (functype->tt_args == NULL)
389 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200390 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
391 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200392 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200393 return OK;
394}
395
396/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200397 * Return the type_T for a typval. Only for primitive types.
398 */
399 static type_T *
400typval2type(typval_T *tv)
401{
402 if (tv->v_type == VAR_NUMBER)
403 return &t_number;
404 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200405 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200406 if (tv->v_type == VAR_STRING)
407 return &t_string;
408 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
409 return &t_list_string;
410 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
411 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200412 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200413}
414
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100415/////////////////////////////////////////////////////////////////////
416// Following generate_ functions expect the caller to call ga_grow().
417
Bram Moolenaar080457c2020-03-03 21:53:32 +0100418#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
419#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
420
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100421/*
422 * Generate an instruction without arguments.
423 * Returns a pointer to the new instruction, NULL if failed.
424 */
425 static isn_T *
426generate_instr(cctx_T *cctx, isntype_T isn_type)
427{
428 garray_T *instr = &cctx->ctx_instr;
429 isn_T *isn;
430
Bram Moolenaar080457c2020-03-03 21:53:32 +0100431 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100432 if (ga_grow(instr, 1) == FAIL)
433 return NULL;
434 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
435 isn->isn_type = isn_type;
436 isn->isn_lnum = cctx->ctx_lnum + 1;
437 ++instr->ga_len;
438
439 return isn;
440}
441
442/*
443 * Generate an instruction without arguments.
444 * "drop" will be removed from the stack.
445 * Returns a pointer to the new instruction, NULL if failed.
446 */
447 static isn_T *
448generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
449{
450 garray_T *stack = &cctx->ctx_type_stack;
451
Bram Moolenaar080457c2020-03-03 21:53:32 +0100452 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100453 stack->ga_len -= drop;
454 return generate_instr(cctx, isn_type);
455}
456
457/*
458 * Generate instruction "isn_type" and put "type" on the type stack.
459 */
460 static isn_T *
461generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
462{
463 isn_T *isn;
464 garray_T *stack = &cctx->ctx_type_stack;
465
466 if ((isn = generate_instr(cctx, isn_type)) == NULL)
467 return NULL;
468
469 if (ga_grow(stack, 1) == FAIL)
470 return NULL;
471 ((type_T **)stack->ga_data)[stack->ga_len] = type;
472 ++stack->ga_len;
473
474 return isn;
475}
476
477/*
478 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
479 */
480 static int
481may_generate_2STRING(int offset, cctx_T *cctx)
482{
483 isn_T *isn;
484 garray_T *stack = &cctx->ctx_type_stack;
485 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
486
487 if ((*type)->tt_type == VAR_STRING)
488 return OK;
489 *type = &t_string;
490
491 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
492 return FAIL;
493 isn->isn_arg.number = offset;
494
495 return OK;
496}
497
498 static int
499check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
500{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200501 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100502 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200503 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100504 {
505 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100506 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100507 else
508 semsg(_("E1036: %c requires number or float arguments"), *op);
509 return FAIL;
510 }
511 return OK;
512}
513
514/*
515 * Generate an instruction with two arguments. The instruction depends on the
516 * type of the arguments.
517 */
518 static int
519generate_two_op(cctx_T *cctx, char_u *op)
520{
521 garray_T *stack = &cctx->ctx_type_stack;
522 type_T *type1;
523 type_T *type2;
524 vartype_T vartype;
525 isn_T *isn;
526
Bram Moolenaar080457c2020-03-03 21:53:32 +0100527 RETURN_OK_IF_SKIP(cctx);
528
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100529 // Get the known type of the two items on the stack. If they are matching
530 // use a type-specific instruction. Otherwise fall back to runtime type
531 // checking.
532 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
533 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200534 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100535 if (type1->tt_type == type2->tt_type
536 && (type1->tt_type == VAR_NUMBER
537 || type1->tt_type == VAR_LIST
538#ifdef FEAT_FLOAT
539 || type1->tt_type == VAR_FLOAT
540#endif
541 || type1->tt_type == VAR_BLOB))
542 vartype = type1->tt_type;
543
544 switch (*op)
545 {
546 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200547 && type1->tt_type != VAR_ANY
548 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100549 && check_number_or_float(
550 type1->tt_type, type2->tt_type, op) == FAIL)
551 return FAIL;
552 isn = generate_instr_drop(cctx,
553 vartype == VAR_NUMBER ? ISN_OPNR
554 : vartype == VAR_LIST ? ISN_ADDLIST
555 : vartype == VAR_BLOB ? ISN_ADDBLOB
556#ifdef FEAT_FLOAT
557 : vartype == VAR_FLOAT ? ISN_OPFLOAT
558#endif
559 : ISN_OPANY, 1);
560 if (isn != NULL)
561 isn->isn_arg.op.op_type = EXPR_ADD;
562 break;
563
564 case '-':
565 case '*':
566 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
567 op) == FAIL)
568 return FAIL;
569 if (vartype == VAR_NUMBER)
570 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
571#ifdef FEAT_FLOAT
572 else if (vartype == VAR_FLOAT)
573 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
574#endif
575 else
576 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
577 if (isn != NULL)
578 isn->isn_arg.op.op_type = *op == '*'
579 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
580 break;
581
Bram Moolenaar4c683752020-04-05 21:38:23 +0200582 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100583 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200584 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100585 && type2->tt_type != VAR_NUMBER))
586 {
587 emsg(_("E1035: % requires number arguments"));
588 return FAIL;
589 }
590 isn = generate_instr_drop(cctx,
591 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
592 if (isn != NULL)
593 isn->isn_arg.op.op_type = EXPR_REM;
594 break;
595 }
596
597 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200598 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100599 {
600 type_T *type = &t_any;
601
602#ifdef FEAT_FLOAT
603 // float+number and number+float results in float
604 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
605 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
606 type = &t_float;
607#endif
608 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
609 }
610
611 return OK;
612}
613
614/*
615 * Generate an ISN_COMPARE* instruction with a boolean result.
616 */
617 static int
618generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
619{
620 isntype_T isntype = ISN_DROP;
621 isn_T *isn;
622 garray_T *stack = &cctx->ctx_type_stack;
623 vartype_T type1;
624 vartype_T type2;
625
Bram Moolenaar080457c2020-03-03 21:53:32 +0100626 RETURN_OK_IF_SKIP(cctx);
627
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100628 // Get the known type of the two items on the stack. If they are matching
629 // use a type-specific instruction. Otherwise fall back to runtime type
630 // checking.
631 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
632 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200633 if (type1 == VAR_UNKNOWN)
634 type1 = VAR_ANY;
635 if (type2 == VAR_UNKNOWN)
636 type2 = VAR_ANY;
637
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100638 if (type1 == type2)
639 {
640 switch (type1)
641 {
642 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
643 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
644 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
645 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
646 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
647 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
648 case VAR_LIST: isntype = ISN_COMPARELIST; break;
649 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
650 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100651 default: isntype = ISN_COMPAREANY; break;
652 }
653 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200654 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100655 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
656 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
657 isntype = ISN_COMPAREANY;
658
659 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
660 && (isntype == ISN_COMPAREBOOL
661 || isntype == ISN_COMPARESPECIAL
662 || isntype == ISN_COMPARENR
663 || isntype == ISN_COMPAREFLOAT))
664 {
665 semsg(_("E1037: Cannot use \"%s\" with %s"),
666 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
667 return FAIL;
668 }
669 if (isntype == ISN_DROP
670 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
671 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
672 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
673 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
674 && exptype != EXPR_IS && exptype != EXPR_ISNOT
675 && (type1 == VAR_BLOB || type2 == VAR_BLOB
676 || type1 == VAR_LIST || type2 == VAR_LIST))))
677 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100678 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100679 vartype_name(type1), vartype_name(type2));
680 return FAIL;
681 }
682
683 if ((isn = generate_instr(cctx, isntype)) == NULL)
684 return FAIL;
685 isn->isn_arg.op.op_type = exptype;
686 isn->isn_arg.op.op_ic = ic;
687
688 // takes two arguments, puts one bool back
689 if (stack->ga_len >= 2)
690 {
691 --stack->ga_len;
692 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
693 }
694
695 return OK;
696}
697
698/*
699 * Generate an ISN_2BOOL instruction.
700 */
701 static int
702generate_2BOOL(cctx_T *cctx, int invert)
703{
704 isn_T *isn;
705 garray_T *stack = &cctx->ctx_type_stack;
706
Bram Moolenaar080457c2020-03-03 21:53:32 +0100707 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100708 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
709 return FAIL;
710 isn->isn_arg.number = invert;
711
712 // type becomes bool
713 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
714
715 return OK;
716}
717
718 static int
719generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
720{
721 isn_T *isn;
722 garray_T *stack = &cctx->ctx_type_stack;
723
Bram Moolenaar080457c2020-03-03 21:53:32 +0100724 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100725 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
726 return FAIL;
727 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
728 isn->isn_arg.type.ct_off = offset;
729
730 // type becomes vartype
731 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
732
733 return OK;
734}
735
736/*
737 * Generate an ISN_PUSHNR instruction.
738 */
739 static int
740generate_PUSHNR(cctx_T *cctx, varnumber_T number)
741{
742 isn_T *isn;
743
Bram Moolenaar080457c2020-03-03 21:53:32 +0100744 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100745 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
746 return FAIL;
747 isn->isn_arg.number = number;
748
749 return OK;
750}
751
752/*
753 * Generate an ISN_PUSHBOOL instruction.
754 */
755 static int
756generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
757{
758 isn_T *isn;
759
Bram Moolenaar080457c2020-03-03 21:53:32 +0100760 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100761 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
762 return FAIL;
763 isn->isn_arg.number = number;
764
765 return OK;
766}
767
768/*
769 * Generate an ISN_PUSHSPEC instruction.
770 */
771 static int
772generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
773{
774 isn_T *isn;
775
Bram Moolenaar080457c2020-03-03 21:53:32 +0100776 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100777 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
778 return FAIL;
779 isn->isn_arg.number = number;
780
781 return OK;
782}
783
784#ifdef FEAT_FLOAT
785/*
786 * Generate an ISN_PUSHF instruction.
787 */
788 static int
789generate_PUSHF(cctx_T *cctx, float_T fnumber)
790{
791 isn_T *isn;
792
Bram Moolenaar080457c2020-03-03 21:53:32 +0100793 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100794 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
795 return FAIL;
796 isn->isn_arg.fnumber = fnumber;
797
798 return OK;
799}
800#endif
801
802/*
803 * Generate an ISN_PUSHS instruction.
804 * Consumes "str".
805 */
806 static int
807generate_PUSHS(cctx_T *cctx, char_u *str)
808{
809 isn_T *isn;
810
Bram Moolenaar080457c2020-03-03 21:53:32 +0100811 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100812 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
813 return FAIL;
814 isn->isn_arg.string = str;
815
816 return OK;
817}
818
819/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100820 * Generate an ISN_PUSHCHANNEL instruction.
821 * Consumes "channel".
822 */
823 static int
824generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
825{
826 isn_T *isn;
827
Bram Moolenaar080457c2020-03-03 21:53:32 +0100828 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100829 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
830 return FAIL;
831 isn->isn_arg.channel = channel;
832
833 return OK;
834}
835
836/*
837 * Generate an ISN_PUSHJOB instruction.
838 * Consumes "job".
839 */
840 static int
841generate_PUSHJOB(cctx_T *cctx, job_T *job)
842{
843 isn_T *isn;
844
Bram Moolenaar080457c2020-03-03 21:53:32 +0100845 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100846 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100847 return FAIL;
848 isn->isn_arg.job = job;
849
850 return OK;
851}
852
853/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100854 * Generate an ISN_PUSHBLOB instruction.
855 * Consumes "blob".
856 */
857 static int
858generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
859{
860 isn_T *isn;
861
Bram Moolenaar080457c2020-03-03 21:53:32 +0100862 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100863 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
864 return FAIL;
865 isn->isn_arg.blob = blob;
866
867 return OK;
868}
869
870/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100871 * Generate an ISN_PUSHFUNC instruction with name "name".
872 * Consumes "name".
873 */
874 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200875generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100876{
877 isn_T *isn;
878
Bram Moolenaar080457c2020-03-03 21:53:32 +0100879 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200880 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100881 return FAIL;
882 isn->isn_arg.string = name;
883
884 return OK;
885}
886
887/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100888 * Generate an ISN_STORE instruction.
889 */
890 static int
891generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
892{
893 isn_T *isn;
894
Bram Moolenaar080457c2020-03-03 21:53:32 +0100895 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100896 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
897 return FAIL;
898 if (name != NULL)
899 isn->isn_arg.string = vim_strsave(name);
900 else
901 isn->isn_arg.number = idx;
902
903 return OK;
904}
905
906/*
907 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
908 */
909 static int
910generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
911{
912 isn_T *isn;
913
Bram Moolenaar080457c2020-03-03 21:53:32 +0100914 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100915 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
916 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100917 isn->isn_arg.storenr.stnr_idx = idx;
918 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100919
920 return OK;
921}
922
923/*
924 * Generate an ISN_STOREOPT instruction
925 */
926 static int
927generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
928{
929 isn_T *isn;
930
Bram Moolenaar080457c2020-03-03 21:53:32 +0100931 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100932 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
933 return FAIL;
934 isn->isn_arg.storeopt.so_name = vim_strsave(name);
935 isn->isn_arg.storeopt.so_flags = opt_flags;
936
937 return OK;
938}
939
940/*
941 * Generate an ISN_LOAD or similar instruction.
942 */
943 static int
944generate_LOAD(
945 cctx_T *cctx,
946 isntype_T isn_type,
947 int idx,
948 char_u *name,
949 type_T *type)
950{
951 isn_T *isn;
952
Bram Moolenaar080457c2020-03-03 21:53:32 +0100953 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100954 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
955 return FAIL;
956 if (name != NULL)
957 isn->isn_arg.string = vim_strsave(name);
958 else
959 isn->isn_arg.number = idx;
960
961 return OK;
962}
963
964/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200965 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100966 */
967 static int
968generate_LOADV(
969 cctx_T *cctx,
970 char_u *name,
971 int error)
972{
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200973 int di_flags;
974 int vidx = find_vim_var(name, &di_flags);
975 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100976
Bram Moolenaar080457c2020-03-03 21:53:32 +0100977 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100978 if (vidx < 0)
979 {
980 if (error)
981 semsg(_(e_var_notfound), name);
982 return FAIL;
983 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200984 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100985
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200986 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100987}
988
989/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200990 * Generate an ISN_UNLET instruction.
991 */
992 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200993generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200994{
995 isn_T *isn;
996
997 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200998 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200999 return FAIL;
1000 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1001 isn->isn_arg.unlet.ul_forceit = forceit;
1002
1003 return OK;
1004}
1005
1006/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001007 * Generate an ISN_LOADS instruction.
1008 */
1009 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001010generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001012 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001013 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001014 int sid,
1015 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001016{
1017 isn_T *isn;
1018
Bram Moolenaar080457c2020-03-03 21:53:32 +01001019 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001020 if (isn_type == ISN_LOADS)
1021 isn = generate_instr_type(cctx, isn_type, type);
1022 else
1023 isn = generate_instr_drop(cctx, isn_type, 1);
1024 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001025 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001026 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1027 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001028
1029 return OK;
1030}
1031
1032/*
1033 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1034 */
1035 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001036generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001037 cctx_T *cctx,
1038 isntype_T isn_type,
1039 int sid,
1040 int idx,
1041 type_T *type)
1042{
1043 isn_T *isn;
1044
Bram Moolenaar080457c2020-03-03 21:53:32 +01001045 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001046 if (isn_type == ISN_LOADSCRIPT)
1047 isn = generate_instr_type(cctx, isn_type, type);
1048 else
1049 isn = generate_instr_drop(cctx, isn_type, 1);
1050 if (isn == NULL)
1051 return FAIL;
1052 isn->isn_arg.script.script_sid = sid;
1053 isn->isn_arg.script.script_idx = idx;
1054 return OK;
1055}
1056
1057/*
1058 * Generate an ISN_NEWLIST instruction.
1059 */
1060 static int
1061generate_NEWLIST(cctx_T *cctx, int count)
1062{
1063 isn_T *isn;
1064 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001065 type_T *type;
1066 type_T *member;
1067
Bram Moolenaar080457c2020-03-03 21:53:32 +01001068 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001069 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1070 return FAIL;
1071 isn->isn_arg.number = count;
1072
1073 // drop the value types
1074 stack->ga_len -= count;
1075
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001076 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001077 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001078 if (count > 0)
1079 member = ((type_T **)stack->ga_data)[stack->ga_len];
1080 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001081 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001082 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001083
1084 // add the list type to the type stack
1085 if (ga_grow(stack, 1) == FAIL)
1086 return FAIL;
1087 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1088 ++stack->ga_len;
1089
1090 return OK;
1091}
1092
1093/*
1094 * Generate an ISN_NEWDICT instruction.
1095 */
1096 static int
1097generate_NEWDICT(cctx_T *cctx, int count)
1098{
1099 isn_T *isn;
1100 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001101 type_T *type;
1102 type_T *member;
1103
Bram Moolenaar080457c2020-03-03 21:53:32 +01001104 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001105 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1106 return FAIL;
1107 isn->isn_arg.number = count;
1108
1109 // drop the key and value types
1110 stack->ga_len -= 2 * count;
1111
Bram Moolenaar436472f2020-02-20 22:54:43 +01001112 // Use the first value type for the list member type. Use "void" for an
1113 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001114 if (count > 0)
1115 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1116 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001117 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001118 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001119
1120 // add the dict type to the type stack
1121 if (ga_grow(stack, 1) == FAIL)
1122 return FAIL;
1123 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1124 ++stack->ga_len;
1125
1126 return OK;
1127}
1128
1129/*
1130 * Generate an ISN_FUNCREF instruction.
1131 */
1132 static int
1133generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1134{
1135 isn_T *isn;
1136 garray_T *stack = &cctx->ctx_type_stack;
1137
Bram Moolenaar080457c2020-03-03 21:53:32 +01001138 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001139 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1140 return FAIL;
1141 isn->isn_arg.number = dfunc_idx;
1142
1143 if (ga_grow(stack, 1) == FAIL)
1144 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001145 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001146 // TODO: argument and return types
1147 ++stack->ga_len;
1148
1149 return OK;
1150}
1151
1152/*
1153 * Generate an ISN_JUMP instruction.
1154 */
1155 static int
1156generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1157{
1158 isn_T *isn;
1159 garray_T *stack = &cctx->ctx_type_stack;
1160
Bram Moolenaar080457c2020-03-03 21:53:32 +01001161 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001162 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1163 return FAIL;
1164 isn->isn_arg.jump.jump_when = when;
1165 isn->isn_arg.jump.jump_where = where;
1166
1167 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1168 --stack->ga_len;
1169
1170 return OK;
1171}
1172
1173 static int
1174generate_FOR(cctx_T *cctx, int loop_idx)
1175{
1176 isn_T *isn;
1177 garray_T *stack = &cctx->ctx_type_stack;
1178
Bram Moolenaar080457c2020-03-03 21:53:32 +01001179 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001180 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1181 return FAIL;
1182 isn->isn_arg.forloop.for_idx = loop_idx;
1183
1184 if (ga_grow(stack, 1) == FAIL)
1185 return FAIL;
1186 // type doesn't matter, will be stored next
1187 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1188 ++stack->ga_len;
1189
1190 return OK;
1191}
1192
1193/*
1194 * Generate an ISN_BCALL instruction.
1195 * Return FAIL if the number of arguments is wrong.
1196 */
1197 static int
1198generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1199{
1200 isn_T *isn;
1201 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001202 type_T *argtypes[MAX_FUNC_ARGS];
1203 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001204
Bram Moolenaar080457c2020-03-03 21:53:32 +01001205 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001206 if (check_internal_func(func_idx, argcount) == FAIL)
1207 return FAIL;
1208
1209 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1210 return FAIL;
1211 isn->isn_arg.bfunc.cbf_idx = func_idx;
1212 isn->isn_arg.bfunc.cbf_argcount = argcount;
1213
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001214 for (i = 0; i < argcount; ++i)
1215 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1216
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001217 stack->ga_len -= argcount; // drop the arguments
1218 if (ga_grow(stack, 1) == FAIL)
1219 return FAIL;
1220 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001221 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001222 ++stack->ga_len; // add return value
1223
1224 return OK;
1225}
1226
1227/*
1228 * Generate an ISN_DCALL or ISN_UCALL instruction.
1229 * Return FAIL if the number of arguments is wrong.
1230 */
1231 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001232generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001233{
1234 isn_T *isn;
1235 garray_T *stack = &cctx->ctx_type_stack;
1236 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001237 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001238
Bram Moolenaar080457c2020-03-03 21:53:32 +01001239 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001240 if (argcount > regular_args && !has_varargs(ufunc))
1241 {
1242 semsg(_(e_toomanyarg), ufunc->uf_name);
1243 return FAIL;
1244 }
1245 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1246 {
1247 semsg(_(e_toofewarg), ufunc->uf_name);
1248 return FAIL;
1249 }
1250
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001251 if (ufunc->uf_dfunc_idx >= 0)
1252 {
1253 int i;
1254
1255 for (i = 0; i < argcount; ++i)
1256 {
1257 type_T *expected;
1258 type_T *actual;
1259
1260 if (i < regular_args)
1261 {
1262 if (ufunc->uf_arg_types == NULL)
1263 continue;
1264 expected = ufunc->uf_arg_types[i];
1265 }
1266 else
1267 expected = ufunc->uf_va_type->tt_member;
1268 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1269 if (check_type(expected, actual, FALSE) == FAIL)
1270 {
1271 arg_type_mismatch(expected, actual, i + 1);
1272 return FAIL;
1273 }
1274 }
1275 }
1276
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001277 if ((isn = generate_instr(cctx,
1278 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1279 return FAIL;
1280 if (ufunc->uf_dfunc_idx >= 0)
1281 {
1282 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1283 isn->isn_arg.dfunc.cdf_argcount = argcount;
1284 }
1285 else
1286 {
1287 // A user function may be deleted and redefined later, can't use the
1288 // ufunc pointer, need to look it up again at runtime.
1289 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1290 isn->isn_arg.ufunc.cuf_argcount = argcount;
1291 }
1292
1293 stack->ga_len -= argcount; // drop the arguments
1294 if (ga_grow(stack, 1) == FAIL)
1295 return FAIL;
1296 // add return value
1297 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1298 ++stack->ga_len;
1299
1300 return OK;
1301}
1302
1303/*
1304 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1305 */
1306 static int
1307generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1308{
1309 isn_T *isn;
1310 garray_T *stack = &cctx->ctx_type_stack;
1311
Bram Moolenaar080457c2020-03-03 21:53:32 +01001312 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001313 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1314 return FAIL;
1315 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1316 isn->isn_arg.ufunc.cuf_argcount = argcount;
1317
1318 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001319 if (ga_grow(stack, 1) == FAIL)
1320 return FAIL;
1321 // add return value
1322 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1323 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001324
1325 return OK;
1326}
1327
1328/*
1329 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001330 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001331 */
1332 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001333generate_PCALL(
1334 cctx_T *cctx,
1335 int argcount,
1336 char_u *name,
1337 type_T *type,
1338 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001339{
1340 isn_T *isn;
1341 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001342 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001343
Bram Moolenaar080457c2020-03-03 21:53:32 +01001344 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001345
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001346 if (type->tt_type == VAR_ANY)
1347 ret_type = &t_any;
1348 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
1349 ret_type = type->tt_member;
1350 else
1351 {
1352 semsg(_("E1085: Not a callable type: %s"), name);
1353 return FAIL;
1354 }
1355
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001356 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1357 return FAIL;
1358 isn->isn_arg.pfunc.cpf_top = at_top;
1359 isn->isn_arg.pfunc.cpf_argcount = argcount;
1360
1361 stack->ga_len -= argcount; // drop the arguments
1362
1363 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001364 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001365
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001366 // If partial is above the arguments it must be cleared and replaced with
1367 // the return value.
1368 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1369 return FAIL;
1370
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001371 return OK;
1372}
1373
1374/*
1375 * Generate an ISN_MEMBER instruction.
1376 */
1377 static int
1378generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1379{
1380 isn_T *isn;
1381 garray_T *stack = &cctx->ctx_type_stack;
1382 type_T *type;
1383
Bram Moolenaar080457c2020-03-03 21:53:32 +01001384 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001385 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1386 return FAIL;
1387 isn->isn_arg.string = vim_strnsave(name, (int)len);
1388
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001389 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001390 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001391 if (type->tt_type != VAR_DICT && type != &t_any)
1392 {
1393 emsg(_(e_dictreq));
1394 return FAIL;
1395 }
1396 // change dict type to dict member type
1397 if (type->tt_type == VAR_DICT)
1398 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001399
1400 return OK;
1401}
1402
1403/*
1404 * Generate an ISN_ECHO instruction.
1405 */
1406 static int
1407generate_ECHO(cctx_T *cctx, int with_white, int count)
1408{
1409 isn_T *isn;
1410
Bram Moolenaar080457c2020-03-03 21:53:32 +01001411 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001412 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1413 return FAIL;
1414 isn->isn_arg.echo.echo_with_white = with_white;
1415 isn->isn_arg.echo.echo_count = count;
1416
1417 return OK;
1418}
1419
Bram Moolenaarad39c092020-02-26 18:23:43 +01001420/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001421 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001422 */
1423 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001424generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001425{
1426 isn_T *isn;
1427
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001428 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001429 return FAIL;
1430 isn->isn_arg.number = count;
1431
1432 return OK;
1433}
1434
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001435 static int
1436generate_EXEC(cctx_T *cctx, char_u *line)
1437{
1438 isn_T *isn;
1439
Bram Moolenaar080457c2020-03-03 21:53:32 +01001440 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001441 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1442 return FAIL;
1443 isn->isn_arg.string = vim_strsave(line);
1444 return OK;
1445}
1446
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001447 static int
1448generate_EXECCONCAT(cctx_T *cctx, int count)
1449{
1450 isn_T *isn;
1451
1452 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1453 return FAIL;
1454 isn->isn_arg.number = count;
1455 return OK;
1456}
1457
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001458/*
1459 * Reserve space for a local variable.
1460 * Return the index or -1 if it failed.
1461 */
1462 static int
1463reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1464{
1465 int idx;
1466 lvar_T *lvar;
1467
1468 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1469 {
1470 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1471 return -1;
1472 }
1473
1474 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1475 return -1;
1476 idx = cctx->ctx_locals.ga_len;
1477 if (cctx->ctx_max_local < idx + 1)
1478 cctx->ctx_max_local = idx + 1;
1479 ++cctx->ctx_locals.ga_len;
1480
1481 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1482 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1483 lvar->lv_const = isConst;
1484 lvar->lv_type = type;
1485
1486 return idx;
1487}
1488
1489/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001490 * Remove local variables above "new_top".
1491 */
1492 static void
1493unwind_locals(cctx_T *cctx, int new_top)
1494{
1495 if (cctx->ctx_locals.ga_len > new_top)
1496 {
1497 int idx;
1498 lvar_T *lvar;
1499
1500 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1501 {
1502 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1503 vim_free(lvar->lv_name);
1504 }
1505 }
1506 cctx->ctx_locals.ga_len = new_top;
1507}
1508
1509/*
1510 * Free all local variables.
1511 */
1512 static void
1513free_local(cctx_T *cctx)
1514{
1515 unwind_locals(cctx, 0);
1516 ga_clear(&cctx->ctx_locals);
1517}
1518
1519/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001520 * Skip over a type definition and return a pointer to just after it.
1521 */
1522 char_u *
1523skip_type(char_u *start)
1524{
1525 char_u *p = start;
1526
1527 while (ASCII_ISALNUM(*p) || *p == '_')
1528 ++p;
1529
1530 // Skip over "<type>"; this is permissive about white space.
1531 if (*skipwhite(p) == '<')
1532 {
1533 p = skipwhite(p);
1534 p = skip_type(skipwhite(p + 1));
1535 p = skipwhite(p);
1536 if (*p == '>')
1537 ++p;
1538 }
1539 return p;
1540}
1541
1542/*
1543 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001544 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001545 * Returns NULL in case of failure.
1546 */
1547 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001548parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001549{
1550 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001551 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001552
1553 if (**arg != '<')
1554 {
1555 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001556 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001557 else
1558 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001559 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001560 }
1561 *arg = skipwhite(*arg + 1);
1562
Bram Moolenaard77a8522020-04-03 21:59:57 +02001563 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001564
1565 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001566 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001567 {
1568 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001569 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001570 }
1571 ++*arg;
1572
1573 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001574 return get_list_type(member_type, type_gap);
1575 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001576}
1577
1578/*
1579 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001580 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001581 */
1582 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001583parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001584{
1585 char_u *p = *arg;
1586 size_t len;
1587
1588 // skip over the first word
1589 while (ASCII_ISALNUM(*p) || *p == '_')
1590 ++p;
1591 len = p - *arg;
1592
1593 switch (**arg)
1594 {
1595 case 'a':
1596 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1597 {
1598 *arg += len;
1599 return &t_any;
1600 }
1601 break;
1602 case 'b':
1603 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1604 {
1605 *arg += len;
1606 return &t_bool;
1607 }
1608 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1609 {
1610 *arg += len;
1611 return &t_blob;
1612 }
1613 break;
1614 case 'c':
1615 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1616 {
1617 *arg += len;
1618 return &t_channel;
1619 }
1620 break;
1621 case 'd':
1622 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1623 {
1624 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001625 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001626 }
1627 break;
1628 case 'f':
1629 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1630 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001631#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001632 *arg += len;
1633 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001634#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001635 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001636 return &t_any;
1637#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001638 }
1639 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1640 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001641 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001642 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001643 int argcount = -1;
1644 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001645 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001646 type_T *arg_type[MAX_FUNC_ARGS + 1];
1647
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001648 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001649 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001650 if (**arg == '(')
1651 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001652 // "func" may or may not return a value, "func()" does
1653 // not return a value.
1654 ret_type = &t_void;
1655
Bram Moolenaard77a8522020-04-03 21:59:57 +02001656 p = ++*arg;
1657 argcount = 0;
1658 while (*p != NUL && *p != ')')
1659 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001660 if (*p == '?')
1661 {
1662 if (first_optional == -1)
1663 first_optional = argcount;
1664 ++p;
1665 }
1666 else if (first_optional != -1)
1667 {
1668 emsg(_("E1007: mandatory argument after optional argument"));
1669 return &t_any;
1670 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001671 else if (STRNCMP(p, "...", 3) == 0)
1672 {
1673 flags |= TTFLAG_VARARGS;
1674 p += 3;
1675 }
1676
1677 arg_type[argcount++] = parse_type(&p, type_gap);
1678
1679 // Nothing comes after "...{type}".
1680 if (flags & TTFLAG_VARARGS)
1681 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001682
Bram Moolenaard77a8522020-04-03 21:59:57 +02001683 if (*p != ',' && *skipwhite(p) == ',')
1684 {
1685 semsg(_(e_no_white_before), ",");
1686 return &t_any;
1687 }
1688 if (*p == ',')
1689 {
1690 ++p;
1691 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001692 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001693 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001694 return &t_any;
1695 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001696 }
1697 p = skipwhite(p);
1698 if (argcount == MAX_FUNC_ARGS)
1699 {
1700 emsg(_("E740: Too many argument types"));
1701 return &t_any;
1702 }
1703 }
1704
1705 p = skipwhite(p);
1706 if (*p != ')')
1707 {
1708 emsg(_(e_missing_close));
1709 return &t_any;
1710 }
1711 *arg = p + 1;
1712 }
1713 if (**arg == ':')
1714 {
1715 // parse return type
1716 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001717 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001718 semsg(_(e_white_after), ":");
1719 *arg = skipwhite(*arg);
1720 ret_type = parse_type(arg, type_gap);
1721 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001722 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001723 type = get_func_type(ret_type, argcount, type_gap);
1724 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001725 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001726 type = alloc_func_type(ret_type, argcount, type_gap);
1727 type->tt_flags = flags;
1728 if (argcount > 0)
1729 {
1730 type->tt_argcount = argcount;
1731 type->tt_min_argcount = first_optional == -1
1732 ? argcount : first_optional;
1733 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001734 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001735 return &t_any;
1736 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001737 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001738 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001739 }
1740 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001741 }
1742 break;
1743 case 'j':
1744 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1745 {
1746 *arg += len;
1747 return &t_job;
1748 }
1749 break;
1750 case 'l':
1751 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1752 {
1753 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001754 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001755 }
1756 break;
1757 case 'n':
1758 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1759 {
1760 *arg += len;
1761 return &t_number;
1762 }
1763 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001764 case 's':
1765 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1766 {
1767 *arg += len;
1768 return &t_string;
1769 }
1770 break;
1771 case 'v':
1772 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1773 {
1774 *arg += len;
1775 return &t_void;
1776 }
1777 break;
1778 }
1779
1780 semsg(_("E1010: Type not recognized: %s"), *arg);
1781 return &t_any;
1782}
1783
1784/*
1785 * Check if "type1" and "type2" are exactly the same.
1786 */
1787 static int
1788equal_type(type_T *type1, type_T *type2)
1789{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001790 int i;
1791
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001792 if (type1->tt_type != type2->tt_type)
1793 return FALSE;
1794 switch (type1->tt_type)
1795 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001796 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001797 case VAR_ANY:
1798 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001799 case VAR_SPECIAL:
1800 case VAR_BOOL:
1801 case VAR_NUMBER:
1802 case VAR_FLOAT:
1803 case VAR_STRING:
1804 case VAR_BLOB:
1805 case VAR_JOB:
1806 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001807 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001808 case VAR_LIST:
1809 case VAR_DICT:
1810 return equal_type(type1->tt_member, type2->tt_member);
1811 case VAR_FUNC:
1812 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001813 if (!equal_type(type1->tt_member, type2->tt_member)
1814 || type1->tt_argcount != type2->tt_argcount)
1815 return FALSE;
1816 if (type1->tt_argcount < 0
1817 || type1->tt_args == NULL || type2->tt_args == NULL)
1818 return TRUE;
1819 for (i = 0; i < type1->tt_argcount; ++i)
1820 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1821 return FALSE;
1822 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001823 }
1824 return TRUE;
1825}
1826
1827/*
1828 * Find the common type of "type1" and "type2" and put it in "dest".
1829 * "type2" and "dest" may be the same.
1830 */
1831 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001832common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001833{
1834 if (equal_type(type1, type2))
1835 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001836 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001837 return;
1838 }
1839
1840 if (type1->tt_type == type2->tt_type)
1841 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001842 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1843 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001844 type_T *common;
1845
Bram Moolenaard77a8522020-04-03 21:59:57 +02001846 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001847 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001848 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001849 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001850 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001851 return;
1852 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001853 if (type1->tt_type == VAR_FUNC)
1854 {
1855 type_T *common;
1856
1857 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1858 if (type1->tt_argcount == type2->tt_argcount
1859 && type1->tt_argcount >= 0)
1860 {
1861 int argcount = type1->tt_argcount;
1862 int i;
1863
1864 *dest = alloc_func_type(common, argcount, type_gap);
1865 if (type1->tt_args != NULL && type2->tt_args != NULL)
1866 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001867 if (func_type_add_arg_types(*dest, argcount,
1868 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001869 for (i = 0; i < argcount; ++i)
1870 common_type(type1->tt_args[i], type2->tt_args[i],
1871 &(*dest)->tt_args[i], type_gap);
1872 }
1873 }
1874 else
1875 *dest = alloc_func_type(common, -1, type_gap);
1876 return;
1877 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001878 }
1879
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001880 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001881}
1882
1883 char *
1884vartype_name(vartype_T type)
1885{
1886 switch (type)
1887 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001888 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001889 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001890 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001891 case VAR_SPECIAL: return "special";
1892 case VAR_BOOL: return "bool";
1893 case VAR_NUMBER: return "number";
1894 case VAR_FLOAT: return "float";
1895 case VAR_STRING: return "string";
1896 case VAR_BLOB: return "blob";
1897 case VAR_JOB: return "job";
1898 case VAR_CHANNEL: return "channel";
1899 case VAR_LIST: return "list";
1900 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001901
1902 case VAR_FUNC:
1903 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001904 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001905 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001906}
1907
1908/*
1909 * Return the name of a type.
1910 * The result may be in allocated memory, in which case "tofree" is set.
1911 */
1912 char *
1913type_name(type_T *type, char **tofree)
1914{
1915 char *name = vartype_name(type->tt_type);
1916
1917 *tofree = NULL;
1918 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1919 {
1920 char *member_free;
1921 char *member_name = type_name(type->tt_member, &member_free);
1922 size_t len;
1923
1924 len = STRLEN(name) + STRLEN(member_name) + 3;
1925 *tofree = alloc(len);
1926 if (*tofree != NULL)
1927 {
1928 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1929 vim_free(member_free);
1930 return *tofree;
1931 }
1932 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001933 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001934 {
1935 garray_T ga;
1936 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001937 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001938
1939 ga_init2(&ga, 1, 100);
1940 if (ga_grow(&ga, 20) == FAIL)
1941 return "[unknown]";
1942 *tofree = ga.ga_data;
1943 STRCPY(ga.ga_data, "func(");
1944 ga.ga_len += 5;
1945
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001946 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001947 {
1948 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001949 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001950 int len;
1951
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001952 if (type->tt_args == NULL)
1953 arg_type = "[unknown]";
1954 else
1955 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001956 if (i > 0)
1957 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001958 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001959 ga.ga_len += 2;
1960 }
1961 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001962 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001963 {
1964 vim_free(arg_free);
1965 return "[unknown]";
1966 }
1967 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001968 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001969 {
1970 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1971 ga.ga_len += 3;
1972 }
1973 else if (i >= type->tt_min_argcount)
1974 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001975 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001976 ga.ga_len += len;
1977 vim_free(arg_free);
1978 }
1979
1980 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001981 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001982 else
1983 {
1984 char *ret_free;
1985 char *ret_name = type_name(type->tt_member, &ret_free);
1986 int len;
1987
1988 len = (int)STRLEN(ret_name) + 4;
1989 if (ga_grow(&ga, len) == FAIL)
1990 {
1991 vim_free(ret_free);
1992 return "[unknown]";
1993 }
1994 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001995 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1996 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001997 vim_free(ret_free);
1998 }
1999 return ga.ga_data;
2000 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002001
2002 return name;
2003}
2004
2005/*
2006 * Find "name" in script-local items of script "sid".
2007 * Returns the index in "sn_var_vals" if found.
2008 * If found but not in "sn_var_vals" returns -1.
2009 * If not found returns -2.
2010 */
2011 int
2012get_script_item_idx(int sid, char_u *name, int check_writable)
2013{
2014 hashtab_T *ht;
2015 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002016 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002017 int idx;
2018
2019 // First look the name up in the hashtable.
2020 if (sid <= 0 || sid > script_items.ga_len)
2021 return -1;
2022 ht = &SCRIPT_VARS(sid);
2023 di = find_var_in_ht(ht, 0, name, TRUE);
2024 if (di == NULL)
2025 return -2;
2026
2027 // Now find the svar_T index in sn_var_vals.
2028 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2029 {
2030 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2031
2032 if (sv->sv_tv == &di->di_tv)
2033 {
2034 if (check_writable && sv->sv_const)
2035 semsg(_(e_readonlyvar), name);
2036 return idx;
2037 }
2038 }
2039 return -1;
2040}
2041
2042/*
2043 * Find "name" in imported items of the current script/
2044 */
2045 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002046find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002047{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002048 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002049 int idx;
2050
2051 if (cctx != NULL)
2052 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2053 {
2054 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2055 + idx;
2056
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002057 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2058 : STRLEN(import->imp_name) == len
2059 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002060 return import;
2061 }
2062
2063 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2064 {
2065 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2066
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002067 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2068 : STRLEN(import->imp_name) == len
2069 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002070 return import;
2071 }
2072 return NULL;
2073}
2074
2075/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002076 * Free all imported variables.
2077 */
2078 static void
2079free_imported(cctx_T *cctx)
2080{
2081 int idx;
2082
2083 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2084 {
2085 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2086
2087 vim_free(import->imp_name);
2088 }
2089 ga_clear(&cctx->ctx_imports);
2090}
2091
2092/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002093 * Get the next line of the function from "cctx".
2094 * Returns NULL when at the end.
2095 */
2096 static char_u *
2097next_line_from_context(cctx_T *cctx)
2098{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002099 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002100
2101 do
2102 {
2103 ++cctx->ctx_lnum;
2104 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002105 {
2106 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002107 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002108 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002109 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002110 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002111 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2112 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002113 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002114 return line;
2115}
2116
2117/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002118 * Return TRUE if "p" points at a "#" but not at "#{".
2119 */
2120 static int
2121comment_start(char_u *p)
2122{
2123 return p[0] == '#' && p[1] != '{';
2124}
2125
2126/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002127 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002128 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002129 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2130 */
2131 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002132may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002133{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002134 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002135 {
2136 char_u *next = next_line_from_context(cctx);
2137
2138 if (next == NULL)
2139 return FAIL;
2140 *arg = skipwhite(next);
2141 }
2142 return OK;
2143}
2144
2145/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002146 * Generate an instruction to load script-local variable "name", without the
2147 * leading "s:".
2148 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002149 */
2150 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002151compile_load_scriptvar(
2152 cctx_T *cctx,
2153 char_u *name, // variable NUL terminated
2154 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002155 char_u **end, // end of variable
2156 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002157{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002158 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002159 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2160 imported_T *import;
2161
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002162 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002163 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002164 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002165 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2166 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002167 }
2168 if (idx >= 0)
2169 {
2170 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2171
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002172 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002173 current_sctx.sc_sid, idx, sv->sv_type);
2174 return OK;
2175 }
2176
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002177 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002178 if (import != NULL)
2179 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002180 if (import->imp_all)
2181 {
2182 char_u *p = skipwhite(*end);
2183 int name_len;
2184 ufunc_T *ufunc;
2185 type_T *type;
2186
2187 // Used "import * as Name", need to lookup the member.
2188 if (*p != '.')
2189 {
2190 semsg(_("E1060: expected dot after name: %s"), start);
2191 return FAIL;
2192 }
2193 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002194 if (VIM_ISWHITE(*p))
2195 {
2196 emsg(_("E1074: no white space allowed after dot"));
2197 return FAIL;
2198 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002199
2200 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2201 // TODO: what if it is a function?
2202 if (idx < 0)
2203 return FAIL;
2204 *end = p;
2205
2206 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2207 import->imp_sid,
2208 idx,
2209 type);
2210 }
2211 else
2212 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002213 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002214 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2215 import->imp_sid,
2216 import->imp_var_vals_idx,
2217 import->imp_type);
2218 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002219 return OK;
2220 }
2221
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002222 if (error)
2223 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002224 return FAIL;
2225}
2226
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002227 static int
2228generate_funcref(cctx_T *cctx, char_u *name)
2229{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002230 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002231
2232 if (ufunc == NULL)
2233 return FAIL;
2234
2235 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2236}
2237
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002238/*
2239 * Compile a variable name into a load instruction.
2240 * "end" points to just after the name.
2241 * When "error" is FALSE do not give an error when not found.
2242 */
2243 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002244compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002245{
2246 type_T *type;
2247 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002248 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002249 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002250 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002251
2252 if (*(*arg + 1) == ':')
2253 {
2254 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002255 if (end <= *arg + 2)
2256 name = vim_strsave((char_u *)"[empty]");
2257 else
2258 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002259 if (name == NULL)
2260 return FAIL;
2261
2262 if (**arg == 'v')
2263 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002264 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002265 }
2266 else if (**arg == 'g')
2267 {
2268 // Global variables can be defined later, thus we don't check if it
2269 // exists, give error at runtime.
2270 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2271 }
2272 else if (**arg == 's')
2273 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002274 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002275 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002276 else if (**arg == 'b')
2277 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002278 // Buffer-local variables can be defined later, thus we don't check
2279 // if it exists, give error at runtime.
2280 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002281 }
2282 else if (**arg == 'w')
2283 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002284 // Window-local variables can be defined later, thus we don't check
2285 // if it exists, give error at runtime.
2286 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002287 }
2288 else if (**arg == 't')
2289 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002290 // Tabpage-local variables can be defined later, thus we don't
2291 // check if it exists, give error at runtime.
2292 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002293 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002294 else
2295 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002296 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002297 goto theend;
2298 }
2299 }
2300 else
2301 {
2302 size_t len = end - *arg;
2303 int idx;
2304 int gen_load = FALSE;
2305
2306 name = vim_strnsave(*arg, end - *arg);
2307 if (name == NULL)
2308 return FAIL;
2309
2310 idx = lookup_arg(*arg, len, cctx);
2311 if (idx >= 0)
2312 {
2313 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2314 type = cctx->ctx_ufunc->uf_arg_types[idx];
2315 else
2316 type = &t_any;
2317
2318 // Arguments are located above the frame pointer.
2319 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2320 if (cctx->ctx_ufunc->uf_va_name != NULL)
2321 --idx;
2322 gen_load = TRUE;
2323 }
2324 else if (lookup_vararg(*arg, len, cctx))
2325 {
2326 // varargs is always the last argument
2327 idx = -STACK_FRAME_SIZE - 1;
2328 type = cctx->ctx_ufunc->uf_va_type;
2329 gen_load = TRUE;
2330 }
2331 else
2332 {
2333 idx = lookup_local(*arg, len, cctx);
2334 if (idx >= 0)
2335 {
2336 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2337 gen_load = TRUE;
2338 }
2339 else
2340 {
2341 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2342 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2343 res = generate_PUSHBOOL(cctx, **arg == 't'
2344 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002345 else
2346 {
2347 // "var" can be script-local even without using "s:" if it
2348 // already exists.
2349 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2350 == SCRIPT_VERSION_VIM9
2351 || lookup_script(*arg, len) == OK)
2352 res = compile_load_scriptvar(cctx, name, *arg, &end,
2353 FALSE);
2354
2355 // When the name starts with an uppercase letter or "x:" it
2356 // can be a user defined function.
2357 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2358 res = generate_funcref(cctx, name);
2359 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002360 }
2361 }
2362 if (gen_load)
2363 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2364 }
2365
2366 *arg = end;
2367
2368theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002369 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002370 semsg(_(e_var_notfound), name);
2371 vim_free(name);
2372 return res;
2373}
2374
2375/*
2376 * Compile the argument expressions.
2377 * "arg" points to just after the "(" and is advanced to after the ")"
2378 */
2379 static int
2380compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2381{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002382 char_u *p = *arg;
2383 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002384
Bram Moolenaare6085c52020-04-12 20:19:16 +02002385 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002386 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002387 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002388 {
2389 p = next_line_from_context(cctx);
2390 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002391 goto failret;
2392 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002393 p = skipwhite(p);
2394 }
2395 if (*p == ')')
2396 {
2397 *arg = p + 1;
2398 return OK;
2399 }
2400
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002401 if (compile_expr1(&p, cctx) == FAIL)
2402 return FAIL;
2403 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002404
2405 if (*p != ',' && *skipwhite(p) == ',')
2406 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002407 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002408 p = skipwhite(p);
2409 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002410 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002411 {
2412 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002413 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002414 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002415 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002416 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002417 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002418 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002419failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002420 emsg(_(e_missing_close));
2421 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002422}
2423
2424/*
2425 * Compile a function call: name(arg1, arg2)
2426 * "arg" points to "name", "arg + varlen" to the "(".
2427 * "argcount_init" is 1 for "value->method()"
2428 * Instructions:
2429 * EVAL arg1
2430 * EVAL arg2
2431 * BCALL / DCALL / UCALL
2432 */
2433 static int
2434compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2435{
2436 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002437 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002438 int argcount = argcount_init;
2439 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002440 char_u fname_buf[FLEN_FIXED + 1];
2441 char_u *tofree = NULL;
2442 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002443 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002444 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002445
2446 if (varlen >= sizeof(namebuf))
2447 {
2448 semsg(_("E1011: name too long: %s"), name);
2449 return FAIL;
2450 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002451 vim_strncpy(namebuf, *arg, varlen);
2452 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002453
2454 *arg = skipwhite(*arg + varlen + 1);
2455 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002456 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002457
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002458 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002459 {
2460 int idx;
2461
2462 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002463 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002464 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002465 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002466 else
2467 semsg(_(e_unknownfunc), namebuf);
2468 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002469 }
2470
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002471 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002472 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002473 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002474 {
2475 res = generate_CALL(cctx, ufunc, argcount);
2476 goto theend;
2477 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002478
2479 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002480 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002481 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002482 if (STRNCMP(namebuf, "g:", 2) != 0
2483 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002484 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002485 garray_T *stack = &cctx->ctx_type_stack;
2486 type_T *type;
2487
2488 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2489 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002490 goto theend;
2491 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002492
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002493 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002494 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002495 if (STRNCMP(namebuf, "g:", 2) == 0)
2496 res = generate_UCALL(cctx, name, argcount);
2497 else
2498 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002499
2500theend:
2501 vim_free(tofree);
2502 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002503}
2504
2505// like NAMESPACE_CHAR but with 'a' and 'l'.
2506#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2507
2508/*
2509 * Find the end of a variable or function name. Unlike find_name_end() this
2510 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002511 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002512 * Return a pointer to just after the name. Equal to "arg" if there is no
2513 * valid name.
2514 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002515 static char_u *
2516to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002517{
2518 char_u *p;
2519
2520 // Quick check for valid starting character.
2521 if (!eval_isnamec1(*arg))
2522 return arg;
2523
2524 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2525 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2526 // and can be used in slice "[n:]".
2527 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002528 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002529 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2530 break;
2531 return p;
2532}
2533
2534/*
2535 * Like to_name_end() but also skip over a list or dict constant.
2536 */
2537 char_u *
2538to_name_const_end(char_u *arg)
2539{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002540 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002541 typval_T rettv;
2542
2543 if (p == arg && *arg == '[')
2544 {
2545
2546 // Can be "[1, 2, 3]->Func()".
2547 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2548 p = arg;
2549 }
2550 else if (p == arg && *arg == '#' && arg[1] == '{')
2551 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002552 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002553 ++p;
2554 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2555 p = arg;
2556 }
2557 else if (p == arg && *arg == '{')
2558 {
2559 int ret = get_lambda_tv(&p, &rettv, FALSE);
2560
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002561 // Can be "{x -> ret}()".
2562 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002563 if (ret == NOTDONE)
2564 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2565 if (ret != OK)
2566 p = arg;
2567 }
2568
2569 return p;
2570}
2571
2572 static void
2573type_mismatch(type_T *expected, type_T *actual)
2574{
2575 char *tofree1, *tofree2;
2576
2577 semsg(_("E1013: type mismatch, expected %s but got %s"),
2578 type_name(expected, &tofree1), type_name(actual, &tofree2));
2579 vim_free(tofree1);
2580 vim_free(tofree2);
2581}
2582
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002583 static void
2584arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2585{
2586 char *tofree1, *tofree2;
2587
2588 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2589 argidx,
2590 type_name(expected, &tofree1), type_name(actual, &tofree2));
2591 vim_free(tofree1);
2592 vim_free(tofree2);
2593}
2594
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002595/*
2596 * Check if the expected and actual types match.
2597 */
2598 static int
2599check_type(type_T *expected, type_T *actual, int give_msg)
2600{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002601 int ret = OK;
2602
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002603 // When expected is "unknown" we accept any actual type.
2604 // When expected is "any" we accept any actual type except "void".
2605 if (expected->tt_type != VAR_UNKNOWN
2606 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002607 {
2608 if (expected->tt_type != actual->tt_type)
2609 {
2610 if (give_msg)
2611 type_mismatch(expected, actual);
2612 return FAIL;
2613 }
2614 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2615 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002616 // "unknown" is used for an empty list or dict
2617 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002618 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002619 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002620 else if (expected->tt_type == VAR_FUNC)
2621 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002622 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002623 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2624 if (ret == OK && expected->tt_argcount != -1
2625 && (actual->tt_argcount < expected->tt_min_argcount
2626 || actual->tt_argcount > expected->tt_argcount))
2627 ret = FAIL;
2628 }
2629 if (ret == FAIL && give_msg)
2630 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002631 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002632 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002633}
2634
2635/*
2636 * Check that
2637 * - "actual" is "expected" type or
2638 * - "actual" is a type that can be "expected" type: add a runtime check; or
2639 * - return FAIL.
2640 */
2641 static int
2642need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2643{
Bram Moolenaar89228602020-04-05 22:14:54 +02002644 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002645 return OK;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002646 if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002647 {
2648 type_mismatch(expected, actual);
2649 return FAIL;
2650 }
2651 generate_TYPECHECK(cctx, expected, offset);
2652 return OK;
2653}
2654
2655/*
2656 * parse a list: [expr, expr]
2657 * "*arg" points to the '['.
2658 */
2659 static int
2660compile_list(char_u **arg, cctx_T *cctx)
2661{
2662 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002663 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002664 int count = 0;
2665
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002666 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002667 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002668 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002669 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002670 p = next_line_from_context(cctx);
2671 if (p == NULL)
2672 {
2673 semsg(_(e_list_end), *arg);
2674 return FAIL;
2675 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002676 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002677 p = skipwhite(p);
2678 }
2679 if (*p == ']')
2680 {
2681 ++p;
2682 // Allow for following comment, after at least one space.
2683 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2684 p += STRLEN(p);
2685 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002686 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002687 if (compile_expr1(&p, cctx) == FAIL)
2688 break;
2689 ++count;
2690 if (*p == ',')
2691 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002692 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002693 p = skipwhite(p);
2694 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002695 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002696
2697 generate_NEWLIST(cctx, count);
2698 return OK;
2699}
2700
2701/*
2702 * parse a lambda: {arg, arg -> expr}
2703 * "*arg" points to the '{'.
2704 */
2705 static int
2706compile_lambda(char_u **arg, cctx_T *cctx)
2707{
2708 garray_T *instr = &cctx->ctx_instr;
2709 typval_T rettv;
2710 ufunc_T *ufunc;
2711
2712 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002713 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002714 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002715
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002716 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002717 ++ufunc->uf_refcount;
2718 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002719 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002720
2721 // The function will have one line: "return {expr}".
2722 // Compile it into instructions.
2723 compile_def_function(ufunc, TRUE);
2724
2725 if (ufunc->uf_dfunc_idx >= 0)
2726 {
2727 if (ga_grow(instr, 1) == FAIL)
2728 return FAIL;
2729 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2730 return OK;
2731 }
2732 return FAIL;
2733}
2734
2735/*
2736 * Compile a lamda call: expr->{lambda}(args)
2737 * "arg" points to the "{".
2738 */
2739 static int
2740compile_lambda_call(char_u **arg, cctx_T *cctx)
2741{
2742 ufunc_T *ufunc;
2743 typval_T rettv;
2744 int argcount = 1;
2745 int ret = FAIL;
2746
2747 // Get the funcref in "rettv".
2748 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2749 return FAIL;
2750
2751 if (**arg != '(')
2752 {
2753 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002754 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002755 else
2756 semsg(_(e_missing_paren), "lambda");
2757 clear_tv(&rettv);
2758 return FAIL;
2759 }
2760
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002761 ufunc = rettv.vval.v_partial->pt_func;
2762 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002763 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002764 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002765
2766 // The function will have one line: "return {expr}".
2767 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002768 compile_def_function(ufunc, TRUE);
2769
2770 // compile the arguments
2771 *arg = skipwhite(*arg + 1);
2772 if (compile_arguments(arg, cctx, &argcount) == OK)
2773 // call the compiled function
2774 ret = generate_CALL(cctx, ufunc, argcount);
2775
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002776 return ret;
2777}
2778
2779/*
2780 * parse a dict: {'key': val} or #{key: val}
2781 * "*arg" points to the '{'.
2782 */
2783 static int
2784compile_dict(char_u **arg, cctx_T *cctx, int literal)
2785{
2786 garray_T *instr = &cctx->ctx_instr;
2787 int count = 0;
2788 dict_T *d = dict_alloc();
2789 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002790 char_u *whitep = *arg;
2791 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002792
2793 if (d == NULL)
2794 return FAIL;
2795 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002796 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002797 {
2798 char_u *key = NULL;
2799
Bram Moolenaar2c330432020-04-13 14:41:35 +02002800 while (**arg == NUL || (literal && **arg == '"')
2801 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002802 {
2803 *arg = next_line_from_context(cctx);
2804 if (*arg == NULL)
2805 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002806 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002807 *arg = skipwhite(*arg);
2808 }
2809
2810 if (**arg == '}')
2811 break;
2812
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002813 if (literal)
2814 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002815 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002816
Bram Moolenaar2c330432020-04-13 14:41:35 +02002817 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002818 {
2819 semsg(_("E1014: Invalid key: %s"), *arg);
2820 return FAIL;
2821 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002822 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002823 if (generate_PUSHS(cctx, key) == FAIL)
2824 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002825 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002826 }
2827 else
2828 {
2829 isn_T *isn;
2830
2831 if (compile_expr1(arg, cctx) == FAIL)
2832 return FAIL;
2833 // TODO: check type is string
2834 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2835 if (isn->isn_type == ISN_PUSHS)
2836 key = isn->isn_arg.string;
2837 }
2838
2839 // Check for duplicate keys, if using string keys.
2840 if (key != NULL)
2841 {
2842 item = dict_find(d, key, -1);
2843 if (item != NULL)
2844 {
2845 semsg(_(e_duplicate_key), key);
2846 goto failret;
2847 }
2848 item = dictitem_alloc(key);
2849 if (item != NULL)
2850 {
2851 item->di_tv.v_type = VAR_UNKNOWN;
2852 item->di_tv.v_lock = 0;
2853 if (dict_add(d, item) == FAIL)
2854 dictitem_free(item);
2855 }
2856 }
2857
2858 *arg = skipwhite(*arg);
2859 if (**arg != ':')
2860 {
2861 semsg(_(e_missing_dict_colon), *arg);
2862 return FAIL;
2863 }
2864
Bram Moolenaar2c330432020-04-13 14:41:35 +02002865 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002866 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002867 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002868 {
2869 *arg = next_line_from_context(cctx);
2870 if (*arg == NULL)
2871 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002872 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002873 *arg = skipwhite(*arg);
2874 }
2875
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002876 if (compile_expr1(arg, cctx) == FAIL)
2877 return FAIL;
2878 ++count;
2879
Bram Moolenaar2c330432020-04-13 14:41:35 +02002880 whitep = *arg;
2881 p = skipwhite(*arg);
2882 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002883 {
2884 *arg = next_line_from_context(cctx);
2885 if (*arg == NULL)
2886 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002887 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002888 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002889 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002890 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002891 if (**arg == '}')
2892 break;
2893 if (**arg != ',')
2894 {
2895 semsg(_(e_missing_dict_comma), *arg);
2896 goto failret;
2897 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002898 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002899 *arg = skipwhite(*arg + 1);
2900 }
2901
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002902 *arg = *arg + 1;
2903
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002904 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002905 p = skipwhite(*arg);
2906 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002907 *arg += STRLEN(*arg);
2908
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002909 dict_unref(d);
2910 return generate_NEWDICT(cctx, count);
2911
2912failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002913 if (*arg == NULL)
2914 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002915 dict_unref(d);
2916 return FAIL;
2917}
2918
2919/*
2920 * Compile "&option".
2921 */
2922 static int
2923compile_get_option(char_u **arg, cctx_T *cctx)
2924{
2925 typval_T rettv;
2926 char_u *start = *arg;
2927 int ret;
2928
2929 // parse the option and get the current value to get the type.
2930 rettv.v_type = VAR_UNKNOWN;
2931 ret = get_option_tv(arg, &rettv, TRUE);
2932 if (ret == OK)
2933 {
2934 // include the '&' in the name, get_option_tv() expects it.
2935 char_u *name = vim_strnsave(start, *arg - start);
2936 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2937
2938 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2939 vim_free(name);
2940 }
2941 clear_tv(&rettv);
2942
2943 return ret;
2944}
2945
2946/*
2947 * Compile "$VAR".
2948 */
2949 static int
2950compile_get_env(char_u **arg, cctx_T *cctx)
2951{
2952 char_u *start = *arg;
2953 int len;
2954 int ret;
2955 char_u *name;
2956
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002957 ++*arg;
2958 len = get_env_len(arg);
2959 if (len == 0)
2960 {
2961 semsg(_(e_syntax_at), start - 1);
2962 return FAIL;
2963 }
2964
2965 // include the '$' in the name, get_env_tv() expects it.
2966 name = vim_strnsave(start, len + 1);
2967 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2968 vim_free(name);
2969 return ret;
2970}
2971
2972/*
2973 * Compile "@r".
2974 */
2975 static int
2976compile_get_register(char_u **arg, cctx_T *cctx)
2977{
2978 int ret;
2979
2980 ++*arg;
2981 if (**arg == NUL)
2982 {
2983 semsg(_(e_syntax_at), *arg - 1);
2984 return FAIL;
2985 }
2986 if (!valid_yank_reg(**arg, TRUE))
2987 {
2988 emsg_invreg(**arg);
2989 return FAIL;
2990 }
2991 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2992 ++*arg;
2993 return ret;
2994}
2995
2996/*
2997 * Apply leading '!', '-' and '+' to constant "rettv".
2998 */
2999 static int
3000apply_leader(typval_T *rettv, char_u *start, char_u *end)
3001{
3002 char_u *p = end;
3003
3004 // this works from end to start
3005 while (p > start)
3006 {
3007 --p;
3008 if (*p == '-' || *p == '+')
3009 {
3010 // only '-' has an effect, for '+' we only check the type
3011#ifdef FEAT_FLOAT
3012 if (rettv->v_type == VAR_FLOAT)
3013 {
3014 if (*p == '-')
3015 rettv->vval.v_float = -rettv->vval.v_float;
3016 }
3017 else
3018#endif
3019 {
3020 varnumber_T val;
3021 int error = FALSE;
3022
3023 // tv_get_number_chk() accepts a string, but we don't want that
3024 // here
3025 if (check_not_string(rettv) == FAIL)
3026 return FAIL;
3027 val = tv_get_number_chk(rettv, &error);
3028 clear_tv(rettv);
3029 if (error)
3030 return FAIL;
3031 if (*p == '-')
3032 val = -val;
3033 rettv->v_type = VAR_NUMBER;
3034 rettv->vval.v_number = val;
3035 }
3036 }
3037 else
3038 {
3039 int v = tv2bool(rettv);
3040
3041 // '!' is permissive in the type.
3042 clear_tv(rettv);
3043 rettv->v_type = VAR_BOOL;
3044 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3045 }
3046 }
3047 return OK;
3048}
3049
3050/*
3051 * Recognize v: variables that are constants and set "rettv".
3052 */
3053 static void
3054get_vim_constant(char_u **arg, typval_T *rettv)
3055{
3056 if (STRNCMP(*arg, "v:true", 6) == 0)
3057 {
3058 rettv->v_type = VAR_BOOL;
3059 rettv->vval.v_number = VVAL_TRUE;
3060 *arg += 6;
3061 }
3062 else if (STRNCMP(*arg, "v:false", 7) == 0)
3063 {
3064 rettv->v_type = VAR_BOOL;
3065 rettv->vval.v_number = VVAL_FALSE;
3066 *arg += 7;
3067 }
3068 else if (STRNCMP(*arg, "v:null", 6) == 0)
3069 {
3070 rettv->v_type = VAR_SPECIAL;
3071 rettv->vval.v_number = VVAL_NULL;
3072 *arg += 6;
3073 }
3074 else if (STRNCMP(*arg, "v:none", 6) == 0)
3075 {
3076 rettv->v_type = VAR_SPECIAL;
3077 rettv->vval.v_number = VVAL_NONE;
3078 *arg += 6;
3079 }
3080}
3081
3082/*
3083 * Compile code to apply '-', '+' and '!'.
3084 */
3085 static int
3086compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3087{
3088 char_u *p = end;
3089
3090 // this works from end to start
3091 while (p > start)
3092 {
3093 --p;
3094 if (*p == '-' || *p == '+')
3095 {
3096 int negate = *p == '-';
3097 isn_T *isn;
3098
3099 // TODO: check type
3100 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3101 {
3102 --p;
3103 if (*p == '-')
3104 negate = !negate;
3105 }
3106 // only '-' has an effect, for '+' we only check the type
3107 if (negate)
3108 isn = generate_instr(cctx, ISN_NEGATENR);
3109 else
3110 isn = generate_instr(cctx, ISN_CHECKNR);
3111 if (isn == NULL)
3112 return FAIL;
3113 }
3114 else
3115 {
3116 int invert = TRUE;
3117
3118 while (p > start && p[-1] == '!')
3119 {
3120 --p;
3121 invert = !invert;
3122 }
3123 if (generate_2BOOL(cctx, invert) == FAIL)
3124 return FAIL;
3125 }
3126 }
3127 return OK;
3128}
3129
3130/*
3131 * Compile whatever comes after "name" or "name()".
3132 */
3133 static int
3134compile_subscript(
3135 char_u **arg,
3136 cctx_T *cctx,
3137 char_u **start_leader,
3138 char_u *end_leader)
3139{
3140 for (;;)
3141 {
3142 if (**arg == '(')
3143 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003144 garray_T *stack = &cctx->ctx_type_stack;
3145 type_T *type;
3146 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003147
3148 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003149 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3150
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003151 *arg = skipwhite(*arg + 1);
3152 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3153 return FAIL;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003154 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003155 return FAIL;
3156 }
3157 else if (**arg == '-' && (*arg)[1] == '>')
3158 {
3159 char_u *p;
3160
3161 // something->method()
3162 // Apply the '!', '-' and '+' first:
3163 // -1.0->func() works like (-1.0)->func()
3164 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3165 return FAIL;
3166 *start_leader = end_leader; // don't apply again later
3167
3168 *arg = skipwhite(*arg + 2);
3169 if (**arg == '{')
3170 {
3171 // lambda call: list->{lambda}
3172 if (compile_lambda_call(arg, cctx) == FAIL)
3173 return FAIL;
3174 }
3175 else
3176 {
3177 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003178 p = *arg;
3179 if (ASCII_ISALPHA(*p) && p[1] == ':')
3180 p += 2;
3181 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003182 ;
3183 if (*p != '(')
3184 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003185 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003186 return FAIL;
3187 }
3188 // TODO: base value may not be the first argument
3189 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3190 return FAIL;
3191 }
3192 }
3193 else if (**arg == '[')
3194 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003195 garray_T *stack;
3196 type_T **typep;
3197
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003198 // list index: list[123]
3199 // TODO: more arguments
3200 // TODO: dict member dict['name']
3201 *arg = skipwhite(*arg + 1);
3202 if (compile_expr1(arg, cctx) == FAIL)
3203 return FAIL;
3204
3205 if (**arg != ']')
3206 {
3207 emsg(_(e_missbrac));
3208 return FAIL;
3209 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003210 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003211
3212 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3213 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003214 stack = &cctx->ctx_type_stack;
3215 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3216 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3217 {
3218 emsg(_(e_listreq));
3219 return FAIL;
3220 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003221 if ((*typep)->tt_type == VAR_LIST)
3222 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003223 }
3224 else if (**arg == '.' && (*arg)[1] != '.')
3225 {
3226 char_u *p;
3227
3228 ++*arg;
3229 p = *arg;
3230 // dictionary member: dict.name
3231 if (eval_isnamec1(*p))
3232 while (eval_isnamec(*p))
3233 MB_PTR_ADV(p);
3234 if (p == *arg)
3235 {
3236 semsg(_(e_syntax_at), *arg);
3237 return FAIL;
3238 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003239 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3240 return FAIL;
3241 *arg = p;
3242 }
3243 else
3244 break;
3245 }
3246
3247 // TODO - see handle_subscript():
3248 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3249 // Don't do this when "Func" is already a partial that was bound
3250 // explicitly (pt_auto is FALSE).
3251
3252 return OK;
3253}
3254
3255/*
3256 * Compile an expression at "*p" and add instructions to "instr".
3257 * "p" is advanced until after the expression, skipping white space.
3258 *
3259 * This is the equivalent of eval1(), eval2(), etc.
3260 */
3261
3262/*
3263 * number number constant
3264 * 0zFFFFFFFF Blob constant
3265 * "string" string constant
3266 * 'string' literal string constant
3267 * &option-name option value
3268 * @r register contents
3269 * identifier variable value
3270 * function() function call
3271 * $VAR environment variable
3272 * (expression) nested expression
3273 * [expr, expr] List
3274 * {key: val, key: val} Dictionary
3275 * #{key: val, key: val} Dictionary with literal keys
3276 *
3277 * Also handle:
3278 * ! in front logical NOT
3279 * - in front unary minus
3280 * + in front unary plus (ignored)
3281 * trailing (arg) funcref/partial call
3282 * trailing [] subscript in String or List
3283 * trailing .name entry in Dictionary
3284 * trailing ->name() method call
3285 */
3286 static int
3287compile_expr7(char_u **arg, cctx_T *cctx)
3288{
3289 typval_T rettv;
3290 char_u *start_leader, *end_leader;
3291 int ret = OK;
3292
3293 /*
3294 * Skip '!', '-' and '+' characters. They are handled later.
3295 */
3296 start_leader = *arg;
3297 while (**arg == '!' || **arg == '-' || **arg == '+')
3298 *arg = skipwhite(*arg + 1);
3299 end_leader = *arg;
3300
3301 rettv.v_type = VAR_UNKNOWN;
3302 switch (**arg)
3303 {
3304 /*
3305 * Number constant.
3306 */
3307 case '0': // also for blob starting with 0z
3308 case '1':
3309 case '2':
3310 case '3':
3311 case '4':
3312 case '5':
3313 case '6':
3314 case '7':
3315 case '8':
3316 case '9':
3317 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3318 return FAIL;
3319 break;
3320
3321 /*
3322 * String constant: "string".
3323 */
3324 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3325 return FAIL;
3326 break;
3327
3328 /*
3329 * Literal string constant: 'str''ing'.
3330 */
3331 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3332 return FAIL;
3333 break;
3334
3335 /*
3336 * Constant Vim variable.
3337 */
3338 case 'v': get_vim_constant(arg, &rettv);
3339 ret = NOTDONE;
3340 break;
3341
3342 /*
3343 * List: [expr, expr]
3344 */
3345 case '[': ret = compile_list(arg, cctx);
3346 break;
3347
3348 /*
3349 * Dictionary: #{key: val, key: val}
3350 */
3351 case '#': if ((*arg)[1] == '{')
3352 {
3353 ++*arg;
3354 ret = compile_dict(arg, cctx, TRUE);
3355 }
3356 else
3357 ret = NOTDONE;
3358 break;
3359
3360 /*
3361 * Lambda: {arg, arg -> expr}
3362 * Dictionary: {'key': val, 'key': val}
3363 */
3364 case '{': {
3365 char_u *start = skipwhite(*arg + 1);
3366
3367 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003368 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003369 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003370 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003371 if (ret != FAIL && *start == '>')
3372 ret = compile_lambda(arg, cctx);
3373 else
3374 ret = compile_dict(arg, cctx, FALSE);
3375 }
3376 break;
3377
3378 /*
3379 * Option value: &name
3380 */
3381 case '&': ret = compile_get_option(arg, cctx);
3382 break;
3383
3384 /*
3385 * Environment variable: $VAR.
3386 */
3387 case '$': ret = compile_get_env(arg, cctx);
3388 break;
3389
3390 /*
3391 * Register contents: @r.
3392 */
3393 case '@': ret = compile_get_register(arg, cctx);
3394 break;
3395 /*
3396 * nested expression: (expression).
3397 */
3398 case '(': *arg = skipwhite(*arg + 1);
3399 ret = compile_expr1(arg, cctx); // recursive!
3400 *arg = skipwhite(*arg);
3401 if (**arg == ')')
3402 ++*arg;
3403 else if (ret == OK)
3404 {
3405 emsg(_(e_missing_close));
3406 ret = FAIL;
3407 }
3408 break;
3409
3410 default: ret = NOTDONE;
3411 break;
3412 }
3413 if (ret == FAIL)
3414 return FAIL;
3415
3416 if (rettv.v_type != VAR_UNKNOWN)
3417 {
3418 // apply the '!', '-' and '+' before the constant
3419 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3420 {
3421 clear_tv(&rettv);
3422 return FAIL;
3423 }
3424 start_leader = end_leader; // don't apply again below
3425
3426 // push constant
3427 switch (rettv.v_type)
3428 {
3429 case VAR_BOOL:
3430 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3431 break;
3432 case VAR_SPECIAL:
3433 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3434 break;
3435 case VAR_NUMBER:
3436 generate_PUSHNR(cctx, rettv.vval.v_number);
3437 break;
3438#ifdef FEAT_FLOAT
3439 case VAR_FLOAT:
3440 generate_PUSHF(cctx, rettv.vval.v_float);
3441 break;
3442#endif
3443 case VAR_BLOB:
3444 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3445 rettv.vval.v_blob = NULL;
3446 break;
3447 case VAR_STRING:
3448 generate_PUSHS(cctx, rettv.vval.v_string);
3449 rettv.vval.v_string = NULL;
3450 break;
3451 default:
3452 iemsg("constant type missing");
3453 return FAIL;
3454 }
3455 }
3456 else if (ret == NOTDONE)
3457 {
3458 char_u *p;
3459 int r;
3460
3461 if (!eval_isnamec1(**arg))
3462 {
3463 semsg(_("E1015: Name expected: %s"), *arg);
3464 return FAIL;
3465 }
3466
3467 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003468 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003469 if (*p == '(')
3470 r = compile_call(arg, p - *arg, cctx, 0);
3471 else
3472 r = compile_load(arg, p, cctx, TRUE);
3473 if (r == FAIL)
3474 return FAIL;
3475 }
3476
3477 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3478 return FAIL;
3479
3480 // Now deal with prefixed '-', '+' and '!', if not done already.
3481 return compile_leader(cctx, start_leader, end_leader);
3482}
3483
3484/*
3485 * * number multiplication
3486 * / number division
3487 * % number modulo
3488 */
3489 static int
3490compile_expr6(char_u **arg, cctx_T *cctx)
3491{
3492 char_u *op;
3493
3494 // get the first variable
3495 if (compile_expr7(arg, cctx) == FAIL)
3496 return FAIL;
3497
3498 /*
3499 * Repeat computing, until no "*", "/" or "%" is following.
3500 */
3501 for (;;)
3502 {
3503 op = skipwhite(*arg);
3504 if (*op != '*' && *op != '/' && *op != '%')
3505 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003506 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003507 {
3508 char_u buf[3];
3509
3510 vim_strncpy(buf, op, 1);
3511 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003512 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003513 }
3514 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003515 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003516 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003517
3518 // get the second variable
3519 if (compile_expr7(arg, cctx) == FAIL)
3520 return FAIL;
3521
3522 generate_two_op(cctx, op);
3523 }
3524
3525 return OK;
3526}
3527
3528/*
3529 * + number addition
3530 * - number subtraction
3531 * .. string concatenation
3532 */
3533 static int
3534compile_expr5(char_u **arg, cctx_T *cctx)
3535{
3536 char_u *op;
3537 int oplen;
3538
3539 // get the first variable
3540 if (compile_expr6(arg, cctx) == FAIL)
3541 return FAIL;
3542
3543 /*
3544 * Repeat computing, until no "+", "-" or ".." is following.
3545 */
3546 for (;;)
3547 {
3548 op = skipwhite(*arg);
3549 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3550 break;
3551 oplen = (*op == '.' ? 2 : 1);
3552
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003553 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003554 {
3555 char_u buf[3];
3556
3557 vim_strncpy(buf, op, oplen);
3558 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003559 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003560 }
3561
3562 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003563 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003564 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003565
3566 // get the second variable
3567 if (compile_expr6(arg, cctx) == FAIL)
3568 return FAIL;
3569
3570 if (*op == '.')
3571 {
3572 if (may_generate_2STRING(-2, cctx) == FAIL
3573 || may_generate_2STRING(-1, cctx) == FAIL)
3574 return FAIL;
3575 generate_instr_drop(cctx, ISN_CONCAT, 1);
3576 }
3577 else
3578 generate_two_op(cctx, op);
3579 }
3580
3581 return OK;
3582}
3583
Bram Moolenaar080457c2020-03-03 21:53:32 +01003584 static exptype_T
3585get_compare_type(char_u *p, int *len, int *type_is)
3586{
3587 exptype_T type = EXPR_UNKNOWN;
3588 int i;
3589
3590 switch (p[0])
3591 {
3592 case '=': if (p[1] == '=')
3593 type = EXPR_EQUAL;
3594 else if (p[1] == '~')
3595 type = EXPR_MATCH;
3596 break;
3597 case '!': if (p[1] == '=')
3598 type = EXPR_NEQUAL;
3599 else if (p[1] == '~')
3600 type = EXPR_NOMATCH;
3601 break;
3602 case '>': if (p[1] != '=')
3603 {
3604 type = EXPR_GREATER;
3605 *len = 1;
3606 }
3607 else
3608 type = EXPR_GEQUAL;
3609 break;
3610 case '<': if (p[1] != '=')
3611 {
3612 type = EXPR_SMALLER;
3613 *len = 1;
3614 }
3615 else
3616 type = EXPR_SEQUAL;
3617 break;
3618 case 'i': if (p[1] == 's')
3619 {
3620 // "is" and "isnot"; but not a prefix of a name
3621 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3622 *len = 5;
3623 i = p[*len];
3624 if (!isalnum(i) && i != '_')
3625 {
3626 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3627 *type_is = TRUE;
3628 }
3629 }
3630 break;
3631 }
3632 return type;
3633}
3634
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003635/*
3636 * expr5a == expr5b
3637 * expr5a =~ expr5b
3638 * expr5a != expr5b
3639 * expr5a !~ expr5b
3640 * expr5a > expr5b
3641 * expr5a >= expr5b
3642 * expr5a < expr5b
3643 * expr5a <= expr5b
3644 * expr5a is expr5b
3645 * expr5a isnot expr5b
3646 *
3647 * Produces instructions:
3648 * EVAL expr5a Push result of "expr5a"
3649 * EVAL expr5b Push result of "expr5b"
3650 * COMPARE one of the compare instructions
3651 */
3652 static int
3653compile_expr4(char_u **arg, cctx_T *cctx)
3654{
3655 exptype_T type = EXPR_UNKNOWN;
3656 char_u *p;
3657 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003658 int type_is = FALSE;
3659
3660 // get the first variable
3661 if (compile_expr5(arg, cctx) == FAIL)
3662 return FAIL;
3663
3664 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003665 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003666
3667 /*
3668 * If there is a comparative operator, use it.
3669 */
3670 if (type != EXPR_UNKNOWN)
3671 {
3672 int ic = FALSE; // Default: do not ignore case
3673
3674 if (type_is && (p[len] == '?' || p[len] == '#'))
3675 {
3676 semsg(_(e_invexpr2), *arg);
3677 return FAIL;
3678 }
3679 // extra question mark appended: ignore case
3680 if (p[len] == '?')
3681 {
3682 ic = TRUE;
3683 ++len;
3684 }
3685 // extra '#' appended: match case (ignored)
3686 else if (p[len] == '#')
3687 ++len;
3688 // nothing appended: match case
3689
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003690 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003691 {
3692 char_u buf[7];
3693
3694 vim_strncpy(buf, p, len);
3695 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003696 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003697 }
3698
3699 // get the second variable
3700 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003701 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003702 return FAIL;
3703
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003704 if (compile_expr5(arg, cctx) == FAIL)
3705 return FAIL;
3706
3707 generate_COMPARE(cctx, type, ic);
3708 }
3709
3710 return OK;
3711}
3712
3713/*
3714 * Compile || or &&.
3715 */
3716 static int
3717compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3718{
3719 char_u *p = skipwhite(*arg);
3720 int opchar = *op;
3721
3722 if (p[0] == opchar && p[1] == opchar)
3723 {
3724 garray_T *instr = &cctx->ctx_instr;
3725 garray_T end_ga;
3726
3727 /*
3728 * Repeat until there is no following "||" or "&&"
3729 */
3730 ga_init2(&end_ga, sizeof(int), 10);
3731 while (p[0] == opchar && p[1] == opchar)
3732 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003733 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3734 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003735 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003736 return FAIL;
3737 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003738
3739 if (ga_grow(&end_ga, 1) == FAIL)
3740 {
3741 ga_clear(&end_ga);
3742 return FAIL;
3743 }
3744 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3745 ++end_ga.ga_len;
3746 generate_JUMP(cctx, opchar == '|'
3747 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3748
3749 // eval the next expression
3750 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003751 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003752 return FAIL;
3753
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003754 if ((opchar == '|' ? compile_expr3(arg, cctx)
3755 : compile_expr4(arg, cctx)) == FAIL)
3756 {
3757 ga_clear(&end_ga);
3758 return FAIL;
3759 }
3760 p = skipwhite(*arg);
3761 }
3762
3763 // Fill in the end label in all jumps.
3764 while (end_ga.ga_len > 0)
3765 {
3766 isn_T *isn;
3767
3768 --end_ga.ga_len;
3769 isn = ((isn_T *)instr->ga_data)
3770 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3771 isn->isn_arg.jump.jump_where = instr->ga_len;
3772 }
3773 ga_clear(&end_ga);
3774 }
3775
3776 return OK;
3777}
3778
3779/*
3780 * expr4a && expr4a && expr4a logical AND
3781 *
3782 * Produces instructions:
3783 * EVAL expr4a Push result of "expr4a"
3784 * JUMP_AND_KEEP_IF_FALSE end
3785 * EVAL expr4b Push result of "expr4b"
3786 * JUMP_AND_KEEP_IF_FALSE end
3787 * EVAL expr4c Push result of "expr4c"
3788 * end:
3789 */
3790 static int
3791compile_expr3(char_u **arg, cctx_T *cctx)
3792{
3793 // get the first variable
3794 if (compile_expr4(arg, cctx) == FAIL)
3795 return FAIL;
3796
3797 // || and && work almost the same
3798 return compile_and_or(arg, cctx, "&&");
3799}
3800
3801/*
3802 * expr3a || expr3b || expr3c logical OR
3803 *
3804 * Produces instructions:
3805 * EVAL expr3a Push result of "expr3a"
3806 * JUMP_AND_KEEP_IF_TRUE end
3807 * EVAL expr3b Push result of "expr3b"
3808 * JUMP_AND_KEEP_IF_TRUE end
3809 * EVAL expr3c Push result of "expr3c"
3810 * end:
3811 */
3812 static int
3813compile_expr2(char_u **arg, cctx_T *cctx)
3814{
3815 // eval the first expression
3816 if (compile_expr3(arg, cctx) == FAIL)
3817 return FAIL;
3818
3819 // || and && work almost the same
3820 return compile_and_or(arg, cctx, "||");
3821}
3822
3823/*
3824 * Toplevel expression: expr2 ? expr1a : expr1b
3825 *
3826 * Produces instructions:
3827 * EVAL expr2 Push result of "expr"
3828 * JUMP_IF_FALSE alt jump if false
3829 * EVAL expr1a
3830 * JUMP_ALWAYS end
3831 * alt: EVAL expr1b
3832 * end:
3833 */
3834 static int
3835compile_expr1(char_u **arg, cctx_T *cctx)
3836{
3837 char_u *p;
3838
3839 // evaluate the first expression
3840 if (compile_expr2(arg, cctx) == FAIL)
3841 return FAIL;
3842
3843 p = skipwhite(*arg);
3844 if (*p == '?')
3845 {
3846 garray_T *instr = &cctx->ctx_instr;
3847 garray_T *stack = &cctx->ctx_type_stack;
3848 int alt_idx = instr->ga_len;
3849 int end_idx;
3850 isn_T *isn;
3851 type_T *type1;
3852 type_T *type2;
3853
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003854 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3855 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003856 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003857 return FAIL;
3858 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003859
3860 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3861
3862 // evaluate the second expression; any type is accepted
3863 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003864 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003865 return FAIL;
3866
Bram Moolenaara6d53682020-01-28 23:04:06 +01003867 if (compile_expr1(arg, cctx) == FAIL)
3868 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003869
3870 // remember the type and drop it
3871 --stack->ga_len;
3872 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3873
3874 end_idx = instr->ga_len;
3875 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3876
3877 // jump here from JUMP_IF_FALSE
3878 isn = ((isn_T *)instr->ga_data) + alt_idx;
3879 isn->isn_arg.jump.jump_where = instr->ga_len;
3880
3881 // Check for the ":".
3882 p = skipwhite(*arg);
3883 if (*p != ':')
3884 {
3885 emsg(_(e_missing_colon));
3886 return FAIL;
3887 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003888 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3889 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003890 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003891 return FAIL;
3892 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003893
3894 // evaluate the third expression
3895 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003896 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003897 return FAIL;
3898
Bram Moolenaara6d53682020-01-28 23:04:06 +01003899 if (compile_expr1(arg, cctx) == FAIL)
3900 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003901
3902 // If the types differ, the result has a more generic type.
3903 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003904 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003905
3906 // jump here from JUMP_ALWAYS
3907 isn = ((isn_T *)instr->ga_data) + end_idx;
3908 isn->isn_arg.jump.jump_where = instr->ga_len;
3909 }
3910 return OK;
3911}
3912
3913/*
3914 * compile "return [expr]"
3915 */
3916 static char_u *
3917compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3918{
3919 char_u *p = arg;
3920 garray_T *stack = &cctx->ctx_type_stack;
3921 type_T *stack_type;
3922
3923 if (*p != NUL && *p != '|' && *p != '\n')
3924 {
3925 // compile return argument into instructions
3926 if (compile_expr1(&p, cctx) == FAIL)
3927 return NULL;
3928
3929 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3930 if (set_return_type)
3931 cctx->ctx_ufunc->uf_ret_type = stack_type;
3932 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3933 == FAIL)
3934 return NULL;
3935 }
3936 else
3937 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003938 // "set_return_type" cannot be TRUE, only used for a lambda which
3939 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003940 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3941 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003942 {
3943 emsg(_("E1003: Missing return value"));
3944 return NULL;
3945 }
3946
3947 // No argument, return zero.
3948 generate_PUSHNR(cctx, 0);
3949 }
3950
3951 if (generate_instr(cctx, ISN_RETURN) == NULL)
3952 return NULL;
3953
3954 // "return val | endif" is possible
3955 return skipwhite(p);
3956}
3957
3958/*
3959 * Return the length of an assignment operator, or zero if there isn't one.
3960 */
3961 int
3962assignment_len(char_u *p, int *heredoc)
3963{
3964 if (*p == '=')
3965 {
3966 if (p[1] == '<' && p[2] == '<')
3967 {
3968 *heredoc = TRUE;
3969 return 3;
3970 }
3971 return 1;
3972 }
3973 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3974 return 2;
3975 if (STRNCMP(p, "..=", 3) == 0)
3976 return 3;
3977 return 0;
3978}
3979
3980// words that cannot be used as a variable
3981static char *reserved[] = {
3982 "true",
3983 "false",
3984 NULL
3985};
3986
3987/*
3988 * Get a line for "=<<".
3989 * Return a pointer to the line in allocated memory.
3990 * Return NULL for end-of-file or some error.
3991 */
3992 static char_u *
3993heredoc_getline(
3994 int c UNUSED,
3995 void *cookie,
3996 int indent UNUSED,
3997 int do_concat UNUSED)
3998{
3999 cctx_T *cctx = (cctx_T *)cookie;
4000
4001 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004002 {
4003 iemsg("Heredoc got to end");
4004 return NULL;
4005 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004006 ++cctx->ctx_lnum;
4007 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4008 [cctx->ctx_lnum]);
4009}
4010
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004011typedef enum {
4012 dest_local,
4013 dest_option,
4014 dest_env,
4015 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004016 dest_buffer,
4017 dest_window,
4018 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004019 dest_vimvar,
4020 dest_script,
4021 dest_reg,
4022} assign_dest_T;
4023
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004024/*
4025 * compile "let var [= expr]", "const var = expr" and "var = expr"
4026 * "arg" points to "var".
4027 */
4028 static char_u *
4029compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4030{
4031 char_u *p;
4032 char_u *ret = NULL;
4033 int var_count = 0;
4034 int semicolon = 0;
4035 size_t varlen;
4036 garray_T *instr = &cctx->ctx_instr;
4037 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004038 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004039 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004040 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004041 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004042 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004043 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004044 int oplen = 0;
4045 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004046 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004047 lvar_T *lvar;
4048 char_u *name;
4049 char_u *sp;
4050 int has_type = FALSE;
4051 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4052 int instr_count = -1;
4053
4054 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4055 if (p == NULL)
4056 return NULL;
4057 if (var_count > 0)
4058 {
4059 // TODO: let [var, var] = list
4060 emsg("Cannot handle a list yet");
4061 return NULL;
4062 }
4063
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004064 // "a: type" is declaring variable "a" with a type, not "a:".
4065 if (is_decl && p == arg + 2 && p[-1] == ':')
4066 --p;
4067
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004068 varlen = p - arg;
4069 name = vim_strnsave(arg, (int)varlen);
4070 if (name == NULL)
4071 return NULL;
4072
Bram Moolenaar080457c2020-03-03 21:53:32 +01004073 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004074 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004075 if (*arg == '&')
4076 {
4077 int cc;
4078 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004079
Bram Moolenaar080457c2020-03-03 21:53:32 +01004080 dest = dest_option;
4081 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004082 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004083 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004084 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004085 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004086 if (is_decl)
4087 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004088 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004089 goto theend;
4090 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004091 p = arg;
4092 p = find_option_end(&p, &opt_flags);
4093 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004094 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004095 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004096 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004097 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004098 }
4099 cc = *p;
4100 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004101 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004102 *p = cc;
4103 if (opt_type == -3)
4104 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004105 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004106 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004107 }
4108 if (opt_type == -2 || opt_type == 0)
4109 type = &t_string;
4110 else
4111 type = &t_number; // both number and boolean option
4112 }
4113 else if (*arg == '$')
4114 {
4115 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004116 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004117 if (is_decl)
4118 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004119 semsg(_("E1065: Cannot declare an environment variable: %s"),
4120 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004121 goto theend;
4122 }
4123 }
4124 else if (*arg == '@')
4125 {
4126 if (!valid_yank_reg(arg[1], TRUE))
4127 {
4128 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004129 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004130 }
4131 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004132 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004133 if (is_decl)
4134 {
4135 semsg(_("E1066: Cannot declare a register: %s"), name);
4136 goto theend;
4137 }
4138 }
4139 else if (STRNCMP(arg, "g:", 2) == 0)
4140 {
4141 dest = dest_global;
4142 if (is_decl)
4143 {
4144 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4145 goto theend;
4146 }
4147 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004148 else if (STRNCMP(arg, "b:", 2) == 0)
4149 {
4150 dest = dest_buffer;
4151 if (is_decl)
4152 {
4153 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4154 goto theend;
4155 }
4156 }
4157 else if (STRNCMP(arg, "w:", 2) == 0)
4158 {
4159 dest = dest_window;
4160 if (is_decl)
4161 {
4162 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4163 goto theend;
4164 }
4165 }
4166 else if (STRNCMP(arg, "t:", 2) == 0)
4167 {
4168 dest = dest_tab;
4169 if (is_decl)
4170 {
4171 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4172 goto theend;
4173 }
4174 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004175 else if (STRNCMP(arg, "v:", 2) == 0)
4176 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004177 typval_T *vtv;
4178 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004179
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004180 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004181 if (vimvaridx < 0)
4182 {
4183 semsg(_(e_var_notfound), arg);
4184 goto theend;
4185 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004186 // We use the current value of "sandbox" here, is that OK?
4187 if (var_check_ro(di_flags, name, FALSE))
4188 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004189 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004190 vtv = get_vim_var_tv(vimvaridx);
4191 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004192 if (is_decl)
4193 {
4194 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4195 goto theend;
4196 }
4197 }
4198 else
4199 {
4200 for (idx = 0; reserved[idx] != NULL; ++idx)
4201 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004202 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004203 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004204 goto theend;
4205 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004206
4207 idx = lookup_local(arg, varlen, cctx);
4208 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004209 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004210 if (is_decl)
4211 {
4212 semsg(_("E1017: Variable already declared: %s"), name);
4213 goto theend;
4214 }
4215 else
4216 {
4217 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4218 if (lvar->lv_const)
4219 {
4220 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4221 goto theend;
4222 }
4223 }
4224 }
4225 else if (STRNCMP(arg, "s:", 2) == 0
4226 || lookup_script(arg, varlen) == OK
4227 || find_imported(arg, varlen, cctx) != NULL)
4228 {
4229 dest = dest_script;
4230 if (is_decl)
4231 {
4232 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004233 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004234 goto theend;
4235 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004236 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004237 else if (name[1] == ':' && name[2] != NUL)
4238 {
4239 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4240 goto theend;
4241 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004242 }
4243 }
4244
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004245 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004246 {
4247 if (is_decl && *p == ':')
4248 {
4249 // parse optional type: "let var: type = expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004250 if (!VIM_ISWHITE(p[1]))
4251 {
4252 semsg(_(e_white_after), ":");
4253 goto theend;
4254 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004255 p = skipwhite(p + 1);
4256 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004257 has_type = TRUE;
4258 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004259 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004260 {
4261 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4262 type = lvar->lv_type;
4263 }
4264 }
4265
4266 sp = p;
4267 p = skipwhite(p);
4268 op = p;
4269 oplen = assignment_len(p, &heredoc);
4270 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4271 {
4272 char_u buf[4];
4273
4274 vim_strncpy(buf, op, oplen);
4275 semsg(_(e_white_both), buf);
4276 }
4277
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004278 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004279 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004280 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004281 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004282 goto theend;
4283 }
4284
Bram Moolenaar080457c2020-03-03 21:53:32 +01004285 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004286 {
4287 if (oplen > 1 && !heredoc)
4288 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004289 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004290 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4291 name);
4292 goto theend;
4293 }
4294
4295 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004296 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004297 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004298 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4299 if (idx < 0)
4300 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004301 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004302 }
4303
4304 if (heredoc)
4305 {
4306 list_T *l;
4307 listitem_T *li;
4308
4309 // [let] varname =<< [trim] {end}
4310 eap->getline = heredoc_getline;
4311 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004312 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004313
4314 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004315 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004316 {
4317 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4318 li->li_tv.vval.v_string = NULL;
4319 }
4320 generate_NEWLIST(cctx, l->lv_len);
4321 type = &t_list_string;
4322 list_free(l);
4323 p += STRLEN(p);
4324 }
4325 else if (oplen > 0)
4326 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004327 int r;
4328 type_T *stacktype;
4329 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004330
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004331 // for "+=", "*=", "..=" etc. first load the current value
4332 if (*op != '=')
4333 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004334 switch (dest)
4335 {
4336 case dest_option:
4337 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004338 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004339 break;
4340 case dest_global:
4341 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4342 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004343 case dest_buffer:
4344 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4345 break;
4346 case dest_window:
4347 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4348 break;
4349 case dest_tab:
4350 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4351 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004352 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004353 compile_load_scriptvar(cctx,
4354 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004355 break;
4356 case dest_env:
4357 // Include $ in the name here
4358 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4359 break;
4360 case dest_reg:
4361 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4362 break;
4363 case dest_vimvar:
4364 generate_LOADV(cctx, name + 2, TRUE);
4365 break;
4366 case dest_local:
4367 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4368 break;
4369 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004370 }
4371
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004372 // Compile the expression. Temporarily hide the new local variable
4373 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004374 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004375 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004376 instr_count = instr->ga_len;
4377 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004378 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004379 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004380 ++cctx->ctx_locals.ga_len;
4381 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004382 goto theend;
4383
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004384 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004385 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004386 stack = &cctx->ctx_type_stack;
4387 stacktype = stack->ga_len == 0 ? &t_void
4388 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4389 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004390 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004391 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4392 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004393 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004394 if (stacktype->tt_type == VAR_VOID)
4395 {
4396 emsg(_("E1031: Cannot use void value"));
4397 goto theend;
4398 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004399 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004400 {
4401 // An empty list or dict has a &t_void member, for a
4402 // variable that implies &t_any.
4403 if (stacktype == &t_list_empty)
4404 lvar->lv_type = &t_list_any;
4405 else if (stacktype == &t_dict_empty)
4406 lvar->lv_type = &t_dict_any;
4407 else
4408 lvar->lv_type = stacktype;
4409 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004410 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004411 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4412 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004413 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004414 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004415 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004416 }
4417 }
4418 else if (cmdidx == CMD_const)
4419 {
4420 emsg(_("E1021: const requires a value"));
4421 goto theend;
4422 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004423 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004424 {
4425 emsg(_("E1022: type or initialization required"));
4426 goto theend;
4427 }
4428 else
4429 {
4430 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004431 if (ga_grow(instr, 1) == FAIL)
4432 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004433 switch (type->tt_type)
4434 {
4435 case VAR_BOOL:
4436 generate_PUSHBOOL(cctx, VVAL_FALSE);
4437 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004438 case VAR_FLOAT:
4439#ifdef FEAT_FLOAT
4440 generate_PUSHF(cctx, 0.0);
4441#endif
4442 break;
4443 case VAR_STRING:
4444 generate_PUSHS(cctx, NULL);
4445 break;
4446 case VAR_BLOB:
4447 generate_PUSHBLOB(cctx, NULL);
4448 break;
4449 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004450 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004451 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004452 case VAR_LIST:
4453 generate_NEWLIST(cctx, 0);
4454 break;
4455 case VAR_DICT:
4456 generate_NEWDICT(cctx, 0);
4457 break;
4458 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004459 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004460 break;
4461 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004462 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004463 break;
4464 case VAR_NUMBER:
4465 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004466 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004467 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004468 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004469 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004470 generate_PUSHNR(cctx, 0);
4471 break;
4472 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004473 }
4474
4475 if (oplen > 0 && *op != '=')
4476 {
4477 type_T *expected = &t_number;
4478 garray_T *stack = &cctx->ctx_type_stack;
4479 type_T *stacktype;
4480
4481 // TODO: if type is known use float or any operation
4482
4483 if (*op == '.')
4484 expected = &t_string;
4485 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4486 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4487 goto theend;
4488
4489 if (*op == '.')
4490 generate_instr_drop(cctx, ISN_CONCAT, 1);
4491 else
4492 {
4493 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4494
4495 if (isn == NULL)
4496 goto theend;
4497 switch (*op)
4498 {
4499 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4500 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4501 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4502 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4503 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4504 }
4505 }
4506 }
4507
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004508 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004509 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004510 case dest_option:
4511 generate_STOREOPT(cctx, name + 1, opt_flags);
4512 break;
4513 case dest_global:
4514 // include g: with the name, easier to execute that way
4515 generate_STORE(cctx, ISN_STOREG, 0, name);
4516 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004517 case dest_buffer:
4518 // include b: with the name, easier to execute that way
4519 generate_STORE(cctx, ISN_STOREB, 0, name);
4520 break;
4521 case dest_window:
4522 // include w: with the name, easier to execute that way
4523 generate_STORE(cctx, ISN_STOREW, 0, name);
4524 break;
4525 case dest_tab:
4526 // include t: with the name, easier to execute that way
4527 generate_STORE(cctx, ISN_STORET, 0, name);
4528 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004529 case dest_env:
4530 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4531 break;
4532 case dest_reg:
4533 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4534 break;
4535 case dest_vimvar:
4536 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4537 break;
4538 case dest_script:
4539 {
4540 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4541 imported_T *import = NULL;
4542 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004543
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004544 if (name[1] != ':')
4545 {
4546 import = find_imported(name, 0, cctx);
4547 if (import != NULL)
4548 sid = import->imp_sid;
4549 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004550
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004551 idx = get_script_item_idx(sid, rawname, TRUE);
4552 // TODO: specific type
4553 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004554 {
4555 char_u *name_s = name;
4556
4557 // Include s: in the name for store_var()
4558 if (name[1] != ':')
4559 {
4560 int len = (int)STRLEN(name) + 3;
4561
4562 name_s = alloc(len);
4563 if (name_s == NULL)
4564 name_s = name;
4565 else
4566 vim_snprintf((char *)name_s, len, "s:%s", name);
4567 }
4568 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4569 if (name_s != name)
4570 vim_free(name_s);
4571 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004572 else
4573 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4574 sid, idx, &t_any);
4575 }
4576 break;
4577 case dest_local:
4578 {
4579 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004580
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004581 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4582 // into ISN_STORENR
4583 if (instr->ga_len == instr_count + 1
4584 && isn->isn_type == ISN_PUSHNR)
4585 {
4586 varnumber_T val = isn->isn_arg.number;
4587 garray_T *stack = &cctx->ctx_type_stack;
4588
4589 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004590 isn->isn_arg.storenr.stnr_idx = idx;
4591 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004592 if (stack->ga_len > 0)
4593 --stack->ga_len;
4594 }
4595 else
4596 generate_STORE(cctx, ISN_STORE, idx, NULL);
4597 }
4598 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004599 }
4600 ret = p;
4601
4602theend:
4603 vim_free(name);
4604 return ret;
4605}
4606
4607/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004608 * Check if "name" can be "unlet".
4609 */
4610 int
4611check_vim9_unlet(char_u *name)
4612{
4613 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
4614 {
4615 semsg(_("E1081: Cannot unlet %s"), name);
4616 return FAIL;
4617 }
4618 return OK;
4619}
4620
4621/*
4622 * Callback passed to ex_unletlock().
4623 */
4624 static int
4625compile_unlet(
4626 lval_T *lvp,
4627 char_u *name_end,
4628 exarg_T *eap,
4629 int deep UNUSED,
4630 void *coookie)
4631{
4632 cctx_T *cctx = coookie;
4633
4634 if (lvp->ll_tv == NULL)
4635 {
4636 char_u *p = lvp->ll_name;
4637 int cc = *name_end;
4638 int ret = OK;
4639
4640 // Normal name. Only supports g:, w:, t: and b: namespaces.
4641 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004642 if (*p == '$')
4643 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
4644 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004645 ret = FAIL;
4646 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004647 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004648
4649 *name_end = cc;
4650 return ret;
4651 }
4652
4653 // TODO: unlet {list}[idx]
4654 // TODO: unlet {dict}[key]
4655 emsg("Sorry, :unlet not fully implemented yet");
4656 return FAIL;
4657}
4658
4659/*
4660 * compile "unlet var", "lock var" and "unlock var"
4661 * "arg" points to "var".
4662 */
4663 static char_u *
4664compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
4665{
4666 char_u *p = arg;
4667
4668 if (eap->cmdidx != CMD_unlet)
4669 {
4670 emsg("Sorry, :lock and unlock not implemented yet");
4671 return NULL;
4672 }
4673
4674 if (*p == '!')
4675 {
4676 p = skipwhite(p + 1);
4677 eap->forceit = TRUE;
4678 }
4679
4680 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
4681 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
4682}
4683
4684/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004685 * Compile an :import command.
4686 */
4687 static char_u *
4688compile_import(char_u *arg, cctx_T *cctx)
4689{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004690 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004691}
4692
4693/*
4694 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4695 */
4696 static int
4697compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4698{
4699 garray_T *instr = &cctx->ctx_instr;
4700 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4701
4702 if (endlabel == NULL)
4703 return FAIL;
4704 endlabel->el_next = *el;
4705 *el = endlabel;
4706 endlabel->el_end_label = instr->ga_len;
4707
4708 generate_JUMP(cctx, when, 0);
4709 return OK;
4710}
4711
4712 static void
4713compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4714{
4715 garray_T *instr = &cctx->ctx_instr;
4716
4717 while (*el != NULL)
4718 {
4719 endlabel_T *cur = (*el);
4720 isn_T *isn;
4721
4722 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4723 isn->isn_arg.jump.jump_where = instr->ga_len;
4724 *el = cur->el_next;
4725 vim_free(cur);
4726 }
4727}
4728
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004729 static void
4730compile_free_jump_to_end(endlabel_T **el)
4731{
4732 while (*el != NULL)
4733 {
4734 endlabel_T *cur = (*el);
4735
4736 *el = cur->el_next;
4737 vim_free(cur);
4738 }
4739}
4740
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004741/*
4742 * Create a new scope and set up the generic items.
4743 */
4744 static scope_T *
4745new_scope(cctx_T *cctx, scopetype_T type)
4746{
4747 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4748
4749 if (scope == NULL)
4750 return NULL;
4751 scope->se_outer = cctx->ctx_scope;
4752 cctx->ctx_scope = scope;
4753 scope->se_type = type;
4754 scope->se_local_count = cctx->ctx_locals.ga_len;
4755 return scope;
4756}
4757
4758/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004759 * Free the current scope and go back to the outer scope.
4760 */
4761 static void
4762drop_scope(cctx_T *cctx)
4763{
4764 scope_T *scope = cctx->ctx_scope;
4765
4766 if (scope == NULL)
4767 {
4768 iemsg("calling drop_scope() without a scope");
4769 return;
4770 }
4771 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004772 switch (scope->se_type)
4773 {
4774 case IF_SCOPE:
4775 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4776 case FOR_SCOPE:
4777 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4778 case WHILE_SCOPE:
4779 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4780 case TRY_SCOPE:
4781 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4782 case NO_SCOPE:
4783 case BLOCK_SCOPE:
4784 break;
4785 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004786 vim_free(scope);
4787}
4788
4789/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004790 * Evaluate an expression that is a constant:
4791 * has(arg)
4792 *
4793 * Also handle:
4794 * ! in front logical NOT
4795 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004796 * Return FAIL if the expression is not a constant.
4797 */
4798 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004799evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004800{
4801 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004802 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004803 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004804
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004805 /*
4806 * Skip '!' characters. They are handled later.
4807 */
4808 start_leader = *arg;
4809 while (**arg == '!')
4810 *arg = skipwhite(*arg + 1);
4811 end_leader = *arg;
4812
4813 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004814 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004815 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004816 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4817 {
4818 tv->v_type = VAR_SPECIAL;
4819 tv->vval.v_number = VVAL_TRUE;
4820 *arg += 4;
4821 return OK;
4822 }
4823 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4824 {
4825 tv->v_type = VAR_SPECIAL;
4826 tv->vval.v_number = VVAL_FALSE;
4827 *arg += 5;
4828 return OK;
4829 }
4830
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004831 if (STRNCMP("has(", *arg, 4) == 0)
4832 {
4833 has_call = TRUE;
4834 *arg = skipwhite(*arg + 4);
4835 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004836
4837 if (**arg == '"')
4838 {
4839 if (get_string_tv(arg, tv, TRUE) == FAIL)
4840 return FAIL;
4841 }
4842 else if (**arg == '\'')
4843 {
4844 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4845 return FAIL;
4846 }
4847 else
4848 return FAIL;
4849
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004850 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004851 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004852 *arg = skipwhite(*arg);
4853 if (**arg != ')')
4854 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004855 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004856
4857 argvars[0] = *tv;
4858 argvars[1].v_type = VAR_UNKNOWN;
4859 tv->v_type = VAR_NUMBER;
4860 tv->vval.v_number = 0;
4861 f_has(argvars, tv);
4862 clear_tv(&argvars[0]);
4863
4864 while (start_leader < end_leader)
4865 {
4866 if (*start_leader == '!')
4867 tv->vval.v_number = !tv->vval.v_number;
4868 ++start_leader;
4869 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004870 }
4871
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004872 return OK;
4873}
4874
Bram Moolenaar080457c2020-03-03 21:53:32 +01004875 static int
4876evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4877{
4878 exptype_T type = EXPR_UNKNOWN;
4879 char_u *p;
4880 int len = 2;
4881 int type_is = FALSE;
4882
4883 // get the first variable
4884 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4885 return FAIL;
4886
4887 p = skipwhite(*arg);
4888 type = get_compare_type(p, &len, &type_is);
4889
4890 /*
4891 * If there is a comparative operator, use it.
4892 */
4893 if (type != EXPR_UNKNOWN)
4894 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004895 typval_T tv2;
4896 char_u *s1, *s2;
4897 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4898 int n;
4899
4900 // TODO: Only string == string is supported now
4901 if (tv->v_type != VAR_STRING)
4902 return FAIL;
4903 if (type != EXPR_EQUAL)
4904 return FAIL;
4905
4906 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004907 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004908 *arg = skipwhite(p + len);
4909 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4910 || tv2.v_type != VAR_STRING)
4911 {
4912 clear_tv(&tv2);
4913 return FAIL;
4914 }
4915 s1 = tv_get_string_buf(tv, buf1);
4916 s2 = tv_get_string_buf(&tv2, buf2);
4917 n = STRCMP(s1, s2);
4918 clear_tv(tv);
4919 clear_tv(&tv2);
4920 tv->v_type = VAR_BOOL;
4921 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004922 }
4923
4924 return OK;
4925}
4926
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004927static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4928
4929/*
4930 * Compile constant || or &&.
4931 */
4932 static int
4933evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4934{
4935 char_u *p = skipwhite(*arg);
4936 int opchar = *op;
4937
4938 if (p[0] == opchar && p[1] == opchar)
4939 {
4940 int val = tv2bool(tv);
4941
4942 /*
4943 * Repeat until there is no following "||" or "&&"
4944 */
4945 while (p[0] == opchar && p[1] == opchar)
4946 {
4947 typval_T tv2;
4948
4949 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4950 return FAIL;
4951
4952 // eval the next expression
4953 *arg = skipwhite(p + 2);
4954 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004955 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004956 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004957 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004958 {
4959 clear_tv(&tv2);
4960 return FAIL;
4961 }
4962 if ((opchar == '&') == val)
4963 {
4964 // false || tv2 or true && tv2: use tv2
4965 clear_tv(tv);
4966 *tv = tv2;
4967 val = tv2bool(tv);
4968 }
4969 else
4970 clear_tv(&tv2);
4971 p = skipwhite(*arg);
4972 }
4973 }
4974
4975 return OK;
4976}
4977
4978/*
4979 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4980 * Return FAIL if the expression is not a constant.
4981 */
4982 static int
4983evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4984{
4985 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004986 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004987 return FAIL;
4988
4989 // || and && work almost the same
4990 return evaluate_const_and_or(arg, cctx, "&&", tv);
4991}
4992
4993/*
4994 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4995 * Return FAIL if the expression is not a constant.
4996 */
4997 static int
4998evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4999{
5000 // evaluate the first expression
5001 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
5002 return FAIL;
5003
5004 // || and && work almost the same
5005 return evaluate_const_and_or(arg, cctx, "||", tv);
5006}
5007
5008/*
5009 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
5010 * E.g. for "has('feature')".
5011 * This does not produce error messages. "tv" should be cleared afterwards.
5012 * Return FAIL if the expression is not a constant.
5013 */
5014 static int
5015evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
5016{
5017 char_u *p;
5018
5019 // evaluate the first expression
5020 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
5021 return FAIL;
5022
5023 p = skipwhite(*arg);
5024 if (*p == '?')
5025 {
5026 int val = tv2bool(tv);
5027 typval_T tv2;
5028
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005029 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005030 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5031 return FAIL;
5032
5033 // evaluate the second expression; any type is accepted
5034 clear_tv(tv);
5035 *arg = skipwhite(p + 1);
5036 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
5037 return FAIL;
5038
5039 // Check for the ":".
5040 p = skipwhite(*arg);
5041 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5042 return FAIL;
5043
5044 // evaluate the third expression
5045 *arg = skipwhite(p + 1);
5046 tv2.v_type = VAR_UNKNOWN;
5047 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
5048 {
5049 clear_tv(&tv2);
5050 return FAIL;
5051 }
5052 if (val)
5053 {
5054 // use the expr after "?"
5055 clear_tv(&tv2);
5056 }
5057 else
5058 {
5059 // use the expr after ":"
5060 clear_tv(tv);
5061 *tv = tv2;
5062 }
5063 }
5064 return OK;
5065}
5066
5067/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005068 * compile "if expr"
5069 *
5070 * "if expr" Produces instructions:
5071 * EVAL expr Push result of "expr"
5072 * JUMP_IF_FALSE end
5073 * ... body ...
5074 * end:
5075 *
5076 * "if expr | else" Produces instructions:
5077 * EVAL expr Push result of "expr"
5078 * JUMP_IF_FALSE else
5079 * ... body ...
5080 * JUMP_ALWAYS end
5081 * else:
5082 * ... body ...
5083 * end:
5084 *
5085 * "if expr1 | elseif expr2 | else" Produces instructions:
5086 * EVAL expr Push result of "expr"
5087 * JUMP_IF_FALSE elseif
5088 * ... body ...
5089 * JUMP_ALWAYS end
5090 * elseif:
5091 * EVAL expr Push result of "expr"
5092 * JUMP_IF_FALSE else
5093 * ... body ...
5094 * JUMP_ALWAYS end
5095 * else:
5096 * ... body ...
5097 * end:
5098 */
5099 static char_u *
5100compile_if(char_u *arg, cctx_T *cctx)
5101{
5102 char_u *p = arg;
5103 garray_T *instr = &cctx->ctx_instr;
5104 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005105 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005106
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005107 // compile "expr"; if we know it evaluates to FALSE skip the block
5108 tv.v_type = VAR_UNKNOWN;
5109 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5110 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5111 else
5112 cctx->ctx_skip = MAYBE;
5113 clear_tv(&tv);
5114 if (cctx->ctx_skip == MAYBE)
5115 {
5116 p = arg;
5117 if (compile_expr1(&p, cctx) == FAIL)
5118 return NULL;
5119 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005120
5121 scope = new_scope(cctx, IF_SCOPE);
5122 if (scope == NULL)
5123 return NULL;
5124
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005125 if (cctx->ctx_skip == MAYBE)
5126 {
5127 // "where" is set when ":elseif", "else" or ":endif" is found
5128 scope->se_u.se_if.is_if_label = instr->ga_len;
5129 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5130 }
5131 else
5132 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005133
5134 return p;
5135}
5136
5137 static char_u *
5138compile_elseif(char_u *arg, cctx_T *cctx)
5139{
5140 char_u *p = arg;
5141 garray_T *instr = &cctx->ctx_instr;
5142 isn_T *isn;
5143 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005144 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005145
5146 if (scope == NULL || scope->se_type != IF_SCOPE)
5147 {
5148 emsg(_(e_elseif_without_if));
5149 return NULL;
5150 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005151 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005152
Bram Moolenaar158906c2020-02-06 20:39:45 +01005153 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005154 {
5155 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005156 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005157 return NULL;
5158 // previous "if" or "elseif" jumps here
5159 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5160 isn->isn_arg.jump.jump_where = instr->ga_len;
5161 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005162
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005163 // compile "expr"; if we know it evaluates to FALSE skip the block
5164 tv.v_type = VAR_UNKNOWN;
5165 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5166 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5167 else
5168 cctx->ctx_skip = MAYBE;
5169 clear_tv(&tv);
5170 if (cctx->ctx_skip == MAYBE)
5171 {
5172 p = arg;
5173 if (compile_expr1(&p, cctx) == FAIL)
5174 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005175
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005176 // "where" is set when ":elseif", "else" or ":endif" is found
5177 scope->se_u.se_if.is_if_label = instr->ga_len;
5178 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5179 }
5180 else
5181 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005182
5183 return p;
5184}
5185
5186 static char_u *
5187compile_else(char_u *arg, cctx_T *cctx)
5188{
5189 char_u *p = arg;
5190 garray_T *instr = &cctx->ctx_instr;
5191 isn_T *isn;
5192 scope_T *scope = cctx->ctx_scope;
5193
5194 if (scope == NULL || scope->se_type != IF_SCOPE)
5195 {
5196 emsg(_(e_else_without_if));
5197 return NULL;
5198 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005199 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005200
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005201 // jump from previous block to the end, unless the else block is empty
5202 if (cctx->ctx_skip == MAYBE)
5203 {
5204 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005205 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005206 return NULL;
5207 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005208
Bram Moolenaar158906c2020-02-06 20:39:45 +01005209 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005210 {
5211 if (scope->se_u.se_if.is_if_label >= 0)
5212 {
5213 // previous "if" or "elseif" jumps here
5214 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5215 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005216 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005217 }
5218 }
5219
5220 if (cctx->ctx_skip != MAYBE)
5221 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005222
5223 return p;
5224}
5225
5226 static char_u *
5227compile_endif(char_u *arg, cctx_T *cctx)
5228{
5229 scope_T *scope = cctx->ctx_scope;
5230 ifscope_T *ifscope;
5231 garray_T *instr = &cctx->ctx_instr;
5232 isn_T *isn;
5233
5234 if (scope == NULL || scope->se_type != IF_SCOPE)
5235 {
5236 emsg(_(e_endif_without_if));
5237 return NULL;
5238 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005239 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005240 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005241
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005242 if (scope->se_u.se_if.is_if_label >= 0)
5243 {
5244 // previous "if" or "elseif" jumps here
5245 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5246 isn->isn_arg.jump.jump_where = instr->ga_len;
5247 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005248 // Fill in the "end" label in jumps at the end of the blocks.
5249 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005250 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005251
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005252 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005253 return arg;
5254}
5255
5256/*
5257 * compile "for var in expr"
5258 *
5259 * Produces instructions:
5260 * PUSHNR -1
5261 * STORE loop-idx Set index to -1
5262 * EVAL expr Push result of "expr"
5263 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5264 * - if beyond end, jump to "end"
5265 * - otherwise get item from list and push it
5266 * STORE var Store item in "var"
5267 * ... body ...
5268 * JUMP top Jump back to repeat
5269 * end: DROP Drop the result of "expr"
5270 *
5271 */
5272 static char_u *
5273compile_for(char_u *arg, cctx_T *cctx)
5274{
5275 char_u *p;
5276 size_t varlen;
5277 garray_T *instr = &cctx->ctx_instr;
5278 garray_T *stack = &cctx->ctx_type_stack;
5279 scope_T *scope;
5280 int loop_idx; // index of loop iteration variable
5281 int var_idx; // index of "var"
5282 type_T *vartype;
5283
5284 // TODO: list of variables: "for [key, value] in dict"
5285 // parse "var"
5286 for (p = arg; eval_isnamec1(*p); ++p)
5287 ;
5288 varlen = p - arg;
5289 var_idx = lookup_local(arg, varlen, cctx);
5290 if (var_idx >= 0)
5291 {
5292 semsg(_("E1023: variable already defined: %s"), arg);
5293 return NULL;
5294 }
5295
5296 // consume "in"
5297 p = skipwhite(p);
5298 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5299 {
5300 emsg(_(e_missing_in));
5301 return NULL;
5302 }
5303 p = skipwhite(p + 2);
5304
5305
5306 scope = new_scope(cctx, FOR_SCOPE);
5307 if (scope == NULL)
5308 return NULL;
5309
5310 // Reserve a variable to store the loop iteration counter.
5311 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5312 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005313 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005314 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005315 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005316 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005317 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005318
5319 // Reserve a variable to store "var"
5320 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5321 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005322 {
5323 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005324 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005325 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005326
5327 generate_STORENR(cctx, loop_idx, -1);
5328
5329 // compile "expr", it remains on the stack until "endfor"
5330 arg = p;
5331 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005332 {
5333 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005334 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005335 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005336
5337 // now we know the type of "var"
5338 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5339 if (vartype->tt_type != VAR_LIST)
5340 {
5341 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005342 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005343 return NULL;
5344 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005345 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005346 {
5347 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
5348
5349 lvar->lv_type = vartype->tt_member;
5350 }
5351
5352 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005353 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005354
5355 generate_FOR(cctx, loop_idx);
5356 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
5357
5358 return arg;
5359}
5360
5361/*
5362 * compile "endfor"
5363 */
5364 static char_u *
5365compile_endfor(char_u *arg, cctx_T *cctx)
5366{
5367 garray_T *instr = &cctx->ctx_instr;
5368 scope_T *scope = cctx->ctx_scope;
5369 forscope_T *forscope;
5370 isn_T *isn;
5371
5372 if (scope == NULL || scope->se_type != FOR_SCOPE)
5373 {
5374 emsg(_(e_for));
5375 return NULL;
5376 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005377 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005378 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005379 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005380
5381 // At end of ":for" scope jump back to the FOR instruction.
5382 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5383
5384 // Fill in the "end" label in the FOR statement so it can jump here
5385 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5386 isn->isn_arg.forloop.for_end = instr->ga_len;
5387
5388 // Fill in the "end" label any BREAK statements
5389 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5390
5391 // Below the ":for" scope drop the "expr" list from the stack.
5392 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5393 return NULL;
5394
5395 vim_free(scope);
5396
5397 return arg;
5398}
5399
5400/*
5401 * compile "while expr"
5402 *
5403 * Produces instructions:
5404 * top: EVAL expr Push result of "expr"
5405 * JUMP_IF_FALSE end jump if false
5406 * ... body ...
5407 * JUMP top Jump back to repeat
5408 * end:
5409 *
5410 */
5411 static char_u *
5412compile_while(char_u *arg, cctx_T *cctx)
5413{
5414 char_u *p = arg;
5415 garray_T *instr = &cctx->ctx_instr;
5416 scope_T *scope;
5417
5418 scope = new_scope(cctx, WHILE_SCOPE);
5419 if (scope == NULL)
5420 return NULL;
5421
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005422 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005423
5424 // compile "expr"
5425 if (compile_expr1(&p, cctx) == FAIL)
5426 return NULL;
5427
5428 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005429 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005430 JUMP_IF_FALSE, cctx) == FAIL)
5431 return FAIL;
5432
5433 return p;
5434}
5435
5436/*
5437 * compile "endwhile"
5438 */
5439 static char_u *
5440compile_endwhile(char_u *arg, cctx_T *cctx)
5441{
5442 scope_T *scope = cctx->ctx_scope;
5443
5444 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5445 {
5446 emsg(_(e_while));
5447 return NULL;
5448 }
5449 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005450 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005451
5452 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005453 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005454
5455 // Fill in the "end" label in the WHILE statement so it can jump here.
5456 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005457 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005458
5459 vim_free(scope);
5460
5461 return arg;
5462}
5463
5464/*
5465 * compile "continue"
5466 */
5467 static char_u *
5468compile_continue(char_u *arg, cctx_T *cctx)
5469{
5470 scope_T *scope = cctx->ctx_scope;
5471
5472 for (;;)
5473 {
5474 if (scope == NULL)
5475 {
5476 emsg(_(e_continue));
5477 return NULL;
5478 }
5479 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5480 break;
5481 scope = scope->se_outer;
5482 }
5483
5484 // Jump back to the FOR or WHILE instruction.
5485 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005486 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5487 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005488 return arg;
5489}
5490
5491/*
5492 * compile "break"
5493 */
5494 static char_u *
5495compile_break(char_u *arg, cctx_T *cctx)
5496{
5497 scope_T *scope = cctx->ctx_scope;
5498 endlabel_T **el;
5499
5500 for (;;)
5501 {
5502 if (scope == NULL)
5503 {
5504 emsg(_(e_break));
5505 return NULL;
5506 }
5507 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5508 break;
5509 scope = scope->se_outer;
5510 }
5511
5512 // Jump to the end of the FOR or WHILE loop.
5513 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005514 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005515 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005516 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005517 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5518 return FAIL;
5519
5520 return arg;
5521}
5522
5523/*
5524 * compile "{" start of block
5525 */
5526 static char_u *
5527compile_block(char_u *arg, cctx_T *cctx)
5528{
5529 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5530 return NULL;
5531 return skipwhite(arg + 1);
5532}
5533
5534/*
5535 * compile end of block: drop one scope
5536 */
5537 static void
5538compile_endblock(cctx_T *cctx)
5539{
5540 scope_T *scope = cctx->ctx_scope;
5541
5542 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005543 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005544 vim_free(scope);
5545}
5546
5547/*
5548 * compile "try"
5549 * Creates a new scope for the try-endtry, pointing to the first catch and
5550 * finally.
5551 * Creates another scope for the "try" block itself.
5552 * TRY instruction sets up exception handling at runtime.
5553 *
5554 * "try"
5555 * TRY -> catch1, -> finally push trystack entry
5556 * ... try block
5557 * "throw {exception}"
5558 * EVAL {exception}
5559 * THROW create exception
5560 * ... try block
5561 * " catch {expr}"
5562 * JUMP -> finally
5563 * catch1: PUSH exeception
5564 * EVAL {expr}
5565 * MATCH
5566 * JUMP nomatch -> catch2
5567 * CATCH remove exception
5568 * ... catch block
5569 * " catch"
5570 * JUMP -> finally
5571 * catch2: CATCH remove exception
5572 * ... catch block
5573 * " finally"
5574 * finally:
5575 * ... finally block
5576 * " endtry"
5577 * ENDTRY pop trystack entry, may rethrow
5578 */
5579 static char_u *
5580compile_try(char_u *arg, cctx_T *cctx)
5581{
5582 garray_T *instr = &cctx->ctx_instr;
5583 scope_T *try_scope;
5584 scope_T *scope;
5585
5586 // scope that holds the jumps that go to catch/finally/endtry
5587 try_scope = new_scope(cctx, TRY_SCOPE);
5588 if (try_scope == NULL)
5589 return NULL;
5590
5591 // "catch" is set when the first ":catch" is found.
5592 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005593 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005594 if (generate_instr(cctx, ISN_TRY) == NULL)
5595 return NULL;
5596
5597 // scope for the try block itself
5598 scope = new_scope(cctx, BLOCK_SCOPE);
5599 if (scope == NULL)
5600 return NULL;
5601
5602 return arg;
5603}
5604
5605/*
5606 * compile "catch {expr}"
5607 */
5608 static char_u *
5609compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5610{
5611 scope_T *scope = cctx->ctx_scope;
5612 garray_T *instr = &cctx->ctx_instr;
5613 char_u *p;
5614 isn_T *isn;
5615
5616 // end block scope from :try or :catch
5617 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5618 compile_endblock(cctx);
5619 scope = cctx->ctx_scope;
5620
5621 // Error if not in a :try scope
5622 if (scope == NULL || scope->se_type != TRY_SCOPE)
5623 {
5624 emsg(_(e_catch));
5625 return NULL;
5626 }
5627
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005628 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005629 {
5630 emsg(_("E1033: catch unreachable after catch-all"));
5631 return NULL;
5632 }
5633
5634 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005635 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005636 JUMP_ALWAYS, cctx) == FAIL)
5637 return NULL;
5638
5639 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005640 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005641 if (isn->isn_arg.try.try_catch == 0)
5642 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005643 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005644 {
5645 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005646 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005647 isn->isn_arg.jump.jump_where = instr->ga_len;
5648 }
5649
5650 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005651 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005652 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005653 scope->se_u.se_try.ts_caught_all = TRUE;
5654 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005655 }
5656 else
5657 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005658 char_u *end;
5659 char_u *pat;
5660 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005661 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005662 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005663
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005664 // Push v:exception, push {expr} and MATCH
5665 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5666
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005667 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005668 if (*end != *p)
5669 {
5670 semsg(_("E1067: Separator mismatch: %s"), p);
5671 vim_free(tofree);
5672 return FAIL;
5673 }
5674 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005675 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005676 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005677 len = (int)(end - tofree);
5678 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005679 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005680 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005681 if (pat == NULL)
5682 return FAIL;
5683 if (generate_PUSHS(cctx, pat) == FAIL)
5684 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005685
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005686 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5687 return NULL;
5688
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005689 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005690 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5691 return NULL;
5692 }
5693
5694 if (generate_instr(cctx, ISN_CATCH) == NULL)
5695 return NULL;
5696
5697 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5698 return NULL;
5699 return p;
5700}
5701
5702 static char_u *
5703compile_finally(char_u *arg, cctx_T *cctx)
5704{
5705 scope_T *scope = cctx->ctx_scope;
5706 garray_T *instr = &cctx->ctx_instr;
5707 isn_T *isn;
5708
5709 // end block scope from :try or :catch
5710 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5711 compile_endblock(cctx);
5712 scope = cctx->ctx_scope;
5713
5714 // Error if not in a :try scope
5715 if (scope == NULL || scope->se_type != TRY_SCOPE)
5716 {
5717 emsg(_(e_finally));
5718 return NULL;
5719 }
5720
5721 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005722 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005723 if (isn->isn_arg.try.try_finally != 0)
5724 {
5725 emsg(_(e_finally_dup));
5726 return NULL;
5727 }
5728
5729 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005730 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005731
Bram Moolenaar585fea72020-04-02 22:33:21 +02005732 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005733 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005734 {
5735 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005736 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005737 isn->isn_arg.jump.jump_where = instr->ga_len;
5738 }
5739
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005740 // TODO: set index in ts_finally_label jumps
5741
5742 return arg;
5743}
5744
5745 static char_u *
5746compile_endtry(char_u *arg, cctx_T *cctx)
5747{
5748 scope_T *scope = cctx->ctx_scope;
5749 garray_T *instr = &cctx->ctx_instr;
5750 isn_T *isn;
5751
5752 // end block scope from :catch or :finally
5753 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5754 compile_endblock(cctx);
5755 scope = cctx->ctx_scope;
5756
5757 // Error if not in a :try scope
5758 if (scope == NULL || scope->se_type != TRY_SCOPE)
5759 {
5760 if (scope == NULL)
5761 emsg(_(e_no_endtry));
5762 else if (scope->se_type == WHILE_SCOPE)
5763 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005764 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005765 emsg(_(e_endfor));
5766 else
5767 emsg(_(e_endif));
5768 return NULL;
5769 }
5770
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005771 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005772 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5773 {
5774 emsg(_("E1032: missing :catch or :finally"));
5775 return NULL;
5776 }
5777
5778 // Fill in the "end" label in jumps at the end of the blocks, if not done
5779 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005780 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005781
5782 // End :catch or :finally scope: set value in ISN_TRY instruction
5783 if (isn->isn_arg.try.try_finally == 0)
5784 isn->isn_arg.try.try_finally = instr->ga_len;
5785 compile_endblock(cctx);
5786
5787 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5788 return NULL;
5789 return arg;
5790}
5791
5792/*
5793 * compile "throw {expr}"
5794 */
5795 static char_u *
5796compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5797{
5798 char_u *p = skipwhite(arg);
5799
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005800 if (compile_expr1(&p, cctx) == FAIL)
5801 return NULL;
5802 if (may_generate_2STRING(-1, cctx) == FAIL)
5803 return NULL;
5804 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5805 return NULL;
5806
5807 return p;
5808}
5809
5810/*
5811 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005812 * compile "echomsg expr"
5813 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01005814 * compile "execute expr"
5815 */
5816 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005817compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01005818{
5819 char_u *p = arg;
5820 int count = 0;
5821
5822 for (;;)
5823 {
5824 if (compile_expr1(&p, cctx) == FAIL)
5825 return NULL;
5826 ++count;
5827 p = skipwhite(p);
5828 if (ends_excmd(*p))
5829 break;
5830 }
5831
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005832 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
5833 generate_ECHO(cctx, cmdidx == CMD_echo, count);
5834 else if (cmdidx == CMD_execute)
5835 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
5836 else if (cmdidx == CMD_echomsg)
5837 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
5838 else
5839 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005840 return p;
5841}
5842
5843/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005844 * A command that is not compiled, execute with legacy code.
5845 */
5846 static char_u *
5847compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
5848{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005849 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005850 int has_expr = FALSE;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005851
5852 if (cctx->ctx_skip == TRUE)
5853 goto theend;
5854
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005855 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
5856 has_expr = (excmd_get_argt(eap->cmdidx) & (EX_XFILE | EX_EXPAND));
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005857 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
5858 {
5859 // expand filename in "syntax include [@group] filename"
5860 has_expr = TRUE;
5861 eap->arg = skipwhite(eap->arg + 7);
5862 if (*eap->arg == '@')
5863 eap->arg = skiptowhite(eap->arg);
5864 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005865
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005866 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005867 {
5868 int count = 0;
5869 char_u *start = skipwhite(line);
5870
5871 // :cmd xxx`=expr1`yyy`=expr2`zzz
5872 // PUSHS ":cmd xxx"
5873 // eval expr1
5874 // PUSHS "yyy"
5875 // eval expr2
5876 // PUSHS "zzz"
5877 // EXECCONCAT 5
5878 for (;;)
5879 {
5880 if (p > start)
5881 {
5882 generate_PUSHS(cctx, vim_strnsave(start, (int)(p - start)));
5883 ++count;
5884 }
5885 p += 2;
5886 if (compile_expr1(&p, cctx) == FAIL)
5887 return NULL;
5888 may_generate_2STRING(-1, cctx);
5889 ++count;
5890 p = skipwhite(p);
5891 if (*p != '`')
5892 {
5893 emsg(_("E1083: missing backtick"));
5894 return NULL;
5895 }
5896 start = p + 1;
5897
5898 p = (char_u *)strstr((char *)start, "`=");
5899 if (p == NULL)
5900 {
5901 if (*skipwhite(start) != NUL)
5902 {
5903 generate_PUSHS(cctx, vim_strsave(start));
5904 ++count;
5905 }
5906 break;
5907 }
5908 }
5909 generate_EXECCONCAT(cctx, count);
5910 }
5911 else
5912 generate_EXEC(cctx, line);
5913
5914theend:
5915 return (char_u *)"";
5916}
5917
5918/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005919 * After ex_function() has collected all the function lines: parse and compile
5920 * the lines into instructions.
5921 * Adds the function to "def_functions".
5922 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5923 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005924 * This can be used recursively through compile_lambda(), which may reallocate
5925 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005926 */
5927 void
5928compile_def_function(ufunc_T *ufunc, int set_return_type)
5929{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005930 char_u *line = NULL;
5931 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005932 char *errormsg = NULL; // error message
5933 int had_return = FALSE;
5934 cctx_T cctx;
5935 garray_T *instr;
5936 int called_emsg_before = called_emsg;
5937 int ret = FAIL;
5938 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005939 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005940
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005941 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005942 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005943
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005944 if (ufunc->uf_dfunc_idx >= 0)
5945 {
5946 // Redefining a function that was compiled before.
5947 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5948
5949 // Free old instructions.
5950 delete_def_function_contents(dfunc);
5951 }
5952 else
5953 {
5954 // Add the function to "def_functions".
5955 if (ga_grow(&def_functions, 1) == FAIL)
5956 return;
5957 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005958 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005959 dfunc->df_idx = def_functions.ga_len;
5960 ufunc->uf_dfunc_idx = dfunc->df_idx;
5961 dfunc->df_ufunc = ufunc;
5962 ++def_functions.ga_len;
5963 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005964 }
5965
Bram Moolenaara80faa82020-04-12 19:37:17 +02005966 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005967 cctx.ctx_ufunc = ufunc;
5968 cctx.ctx_lnum = -1;
5969 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5970 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5971 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5972 cctx.ctx_type_list = &ufunc->uf_type_list;
5973 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5974 instr = &cctx.ctx_instr;
5975
5976 // Most modern script version.
5977 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5978
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005979 if (ufunc->uf_def_args.ga_len > 0)
5980 {
5981 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005982 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005983 int i;
5984 char_u *arg;
5985 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5986
5987 // Produce instructions for the default values of optional arguments.
5988 // Store the instruction index in uf_def_arg_idx[] so that we know
5989 // where to start when the function is called, depending on the number
5990 // of arguments.
5991 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5992 if (ufunc->uf_def_arg_idx == NULL)
5993 goto erret;
5994 for (i = 0; i < count; ++i)
5995 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005996 garray_T *stack = &cctx.ctx_type_stack;
5997 type_T *val_type;
5998 int arg_idx = first_def_arg + i;
5999
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006000 ufunc->uf_def_arg_idx[i] = instr->ga_len;
6001 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006002 if (compile_expr1(&arg, &cctx) == FAIL)
6003 goto erret;
6004
6005 // If no type specified use the type of the default value.
6006 // Otherwise check that the default value type matches the
6007 // specified type.
6008 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6009 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
6010 ufunc->uf_arg_types[arg_idx] = val_type;
6011 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
6012 == FAIL)
6013 {
6014 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
6015 arg_idx + 1);
6016 goto erret;
6017 }
6018
6019 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006020 goto erret;
6021 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006022 ufunc->uf_def_arg_idx[count] = instr->ga_len;
6023 }
6024
6025 /*
6026 * Loop over all the lines of the function and generate instructions.
6027 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006028 for (;;)
6029 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006030 exarg_T ea;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006031 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006032
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006033 // Bail out on the first error to avoid a flood of errors and report
6034 // the right line number when inside try/catch.
6035 if (emsg_before != called_emsg)
6036 goto erret;
6037
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006038 if (line != NULL && *line == '|')
6039 // the line continues after a '|'
6040 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02006041 else if (line != NULL && *line != NUL
6042 && !(*line == '#' && (line == cctx.ctx_line_start
6043 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006044 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006045 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006046 goto erret;
6047 }
6048 else
6049 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006050 line = next_line_from_context(&cctx);
6051 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006052 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006053 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006054 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006055 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006056
6057 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006058 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006059 ea.cmdlinep = &line;
6060 ea.cmd = skipwhite(line);
6061
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006062 // Some things can be recognized by the first character.
6063 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006064 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006065 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006066 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006067 if (ea.cmd[1] != '{')
6068 {
6069 line = (char_u *)"";
6070 continue;
6071 }
6072 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006073
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006074 case '}':
6075 {
6076 // "}" ends a block scope
6077 scopetype_T stype = cctx.ctx_scope == NULL
6078 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006079
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006080 if (stype == BLOCK_SCOPE)
6081 {
6082 compile_endblock(&cctx);
6083 line = ea.cmd;
6084 }
6085 else
6086 {
6087 emsg(_("E1025: using } outside of a block scope"));
6088 goto erret;
6089 }
6090 if (line != NULL)
6091 line = skipwhite(ea.cmd + 1);
6092 continue;
6093 }
6094
6095 case '{':
6096 // "{" starts a block scope
6097 // "{'a': 1}->func() is something else
6098 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6099 {
6100 line = compile_block(ea.cmd, &cctx);
6101 continue;
6102 }
6103 break;
6104
6105 case ':':
6106 is_ex_command = TRUE;
6107 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006108 }
6109
6110 /*
6111 * COMMAND MODIFIERS
6112 */
6113 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6114 {
6115 if (errormsg != NULL)
6116 goto erret;
6117 // empty line or comment
6118 line = (char_u *)"";
6119 continue;
6120 }
6121
6122 // Skip ":call" to get to the function name.
6123 if (checkforcmd(&ea.cmd, "call", 3))
6124 ea.cmd = skipwhite(ea.cmd);
6125
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006126 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006127 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006128 // Assuming the command starts with a variable or function name,
6129 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6130 // val".
6131 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6132 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006133 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006134 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006135 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006136 int oplen;
6137 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006138
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006139 oplen = assignment_len(skipwhite(p), &heredoc);
6140 if (oplen > 0)
6141 {
6142 // Recognize an assignment if we recognize the variable
6143 // name:
6144 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006145 // "local = expr" where "local" is a local var.
6146 // "script = expr" where "script" is a script-local var.
6147 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006148 // "&opt = expr"
6149 // "$ENV = expr"
6150 // "@r = expr"
6151 if (*ea.cmd == '&'
6152 || *ea.cmd == '$'
6153 || *ea.cmd == '@'
6154 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
6155 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
6156 || lookup_script(ea.cmd, p - ea.cmd) == OK
6157 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6158 {
6159 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6160 if (line == NULL)
6161 goto erret;
6162 continue;
6163 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006164 }
6165 }
6166 }
6167
6168 /*
6169 * COMMAND after range
6170 */
6171 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006172 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
6173 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006174
6175 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6176 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006177 if (cctx.ctx_skip == TRUE)
6178 {
6179 line += STRLEN(line);
6180 continue;
6181 }
6182
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006183 // Expression or function call.
6184 if (ea.cmdidx == CMD_eval)
6185 {
6186 p = ea.cmd;
6187 if (compile_expr1(&p, &cctx) == FAIL)
6188 goto erret;
6189
6190 // drop the return value
6191 generate_instr_drop(&cctx, ISN_DROP, 1);
6192 line = p;
6193 continue;
6194 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006195 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006196 iemsg("Command from find_ex_command() not handled");
6197 goto erret;
6198 }
6199
6200 p = skipwhite(p);
6201
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006202 if (cctx.ctx_skip == TRUE
6203 && ea.cmdidx != CMD_elseif
6204 && ea.cmdidx != CMD_else
6205 && ea.cmdidx != CMD_endif)
6206 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006207 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006208 continue;
6209 }
6210
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006211 switch (ea.cmdidx)
6212 {
6213 case CMD_def:
6214 case CMD_function:
6215 // TODO: Nested function
6216 emsg("Nested function not implemented yet");
6217 goto erret;
6218
6219 case CMD_return:
6220 line = compile_return(p, set_return_type, &cctx);
6221 had_return = TRUE;
6222 break;
6223
6224 case CMD_let:
6225 case CMD_const:
6226 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6227 break;
6228
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006229 case CMD_unlet:
6230 case CMD_unlockvar:
6231 case CMD_lockvar:
6232 line = compile_unletlock(p, &ea, &cctx);
6233 break;
6234
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006235 case CMD_import:
6236 line = compile_import(p, &cctx);
6237 break;
6238
6239 case CMD_if:
6240 line = compile_if(p, &cctx);
6241 break;
6242 case CMD_elseif:
6243 line = compile_elseif(p, &cctx);
6244 break;
6245 case CMD_else:
6246 line = compile_else(p, &cctx);
6247 break;
6248 case CMD_endif:
6249 line = compile_endif(p, &cctx);
6250 break;
6251
6252 case CMD_while:
6253 line = compile_while(p, &cctx);
6254 break;
6255 case CMD_endwhile:
6256 line = compile_endwhile(p, &cctx);
6257 break;
6258
6259 case CMD_for:
6260 line = compile_for(p, &cctx);
6261 break;
6262 case CMD_endfor:
6263 line = compile_endfor(p, &cctx);
6264 break;
6265 case CMD_continue:
6266 line = compile_continue(p, &cctx);
6267 break;
6268 case CMD_break:
6269 line = compile_break(p, &cctx);
6270 break;
6271
6272 case CMD_try:
6273 line = compile_try(p, &cctx);
6274 break;
6275 case CMD_catch:
6276 line = compile_catch(p, &cctx);
6277 break;
6278 case CMD_finally:
6279 line = compile_finally(p, &cctx);
6280 break;
6281 case CMD_endtry:
6282 line = compile_endtry(p, &cctx);
6283 break;
6284 case CMD_throw:
6285 line = compile_throw(p, &cctx);
6286 break;
6287
6288 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006289 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006290 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006291 case CMD_echomsg:
6292 case CMD_echoerr:
6293 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006294 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006295
6296 default:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006297 // TODO: other commands with an expression argument
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006298 // Not recognized, execute with do_cmdline_cmd().
6299 ea.arg = p;
6300 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006301 break;
6302 }
6303 if (line == NULL)
6304 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006305 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006306
6307 if (cctx.ctx_type_stack.ga_len < 0)
6308 {
6309 iemsg("Type stack underflow");
6310 goto erret;
6311 }
6312 }
6313
6314 if (cctx.ctx_scope != NULL)
6315 {
6316 if (cctx.ctx_scope->se_type == IF_SCOPE)
6317 emsg(_(e_endif));
6318 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6319 emsg(_(e_endwhile));
6320 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6321 emsg(_(e_endfor));
6322 else
6323 emsg(_("E1026: Missing }"));
6324 goto erret;
6325 }
6326
6327 if (!had_return)
6328 {
6329 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6330 {
6331 emsg(_("E1027: Missing return statement"));
6332 goto erret;
6333 }
6334
6335 // Return zero if there is no return at the end.
6336 generate_PUSHNR(&cctx, 0);
6337 generate_instr(&cctx, ISN_RETURN);
6338 }
6339
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006340 {
6341 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6342 + ufunc->uf_dfunc_idx;
6343 dfunc->df_deleted = FALSE;
6344 dfunc->df_instr = instr->ga_data;
6345 dfunc->df_instr_count = instr->ga_len;
6346 dfunc->df_varcount = cctx.ctx_max_local;
6347 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006348
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006349 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006350 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006351 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006352
6353 // Create a type for the function, with the return type and any
6354 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006355 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6356 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006357 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006358 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006359 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6360 argcount, &ufunc->uf_type_list);
6361 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006362 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006363 argcount + varargs,
6364 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006365 {
6366 ret = FAIL;
6367 goto erret;
6368 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006369 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6370 ufunc->uf_func_type->tt_min_argcount =
6371 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006372 if (ufunc->uf_arg_types == NULL)
6373 {
6374 int i;
6375
6376 // lambda does not have argument types.
6377 for (i = 0; i < argcount; ++i)
6378 ufunc->uf_func_type->tt_args[i] = &t_any;
6379 }
6380 else
6381 mch_memmove(ufunc->uf_func_type->tt_args,
6382 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006383 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006384 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006385 ufunc->uf_func_type->tt_args[argcount] =
6386 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006387 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6388 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006389 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006390 else
6391 // No arguments, can use a predefined type.
6392 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6393 argcount, &ufunc->uf_type_list);
6394
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006395 }
6396
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006397 ret = OK;
6398
6399erret:
6400 if (ret == FAIL)
6401 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006402 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006403 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6404 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006405
6406 for (idx = 0; idx < instr->ga_len; ++idx)
6407 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006408 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006409
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006410 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006411 if (!dfunc->df_deleted)
6412 --def_functions.ga_len;
6413
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006414 while (cctx.ctx_scope != NULL)
6415 drop_scope(&cctx);
6416
Bram Moolenaar20431c92020-03-20 18:39:46 +01006417 // Don't execute this function body.
6418 ga_clear_strings(&ufunc->uf_lines);
6419
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006420 if (errormsg != NULL)
6421 emsg(errormsg);
6422 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006423 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006424 }
6425
6426 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006427 free_imported(&cctx);
6428 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006429 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006430}
6431
6432/*
6433 * Delete an instruction, free what it contains.
6434 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006435 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006436delete_instr(isn_T *isn)
6437{
6438 switch (isn->isn_type)
6439 {
6440 case ISN_EXEC:
6441 case ISN_LOADENV:
6442 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006443 case ISN_LOADB:
6444 case ISN_LOADW:
6445 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006446 case ISN_LOADOPT:
6447 case ISN_MEMBER:
6448 case ISN_PUSHEXC:
6449 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006450 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006451 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006452 case ISN_STOREB:
6453 case ISN_STOREW:
6454 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006455 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006456 vim_free(isn->isn_arg.string);
6457 break;
6458
6459 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006460 case ISN_STORES:
6461 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006462 break;
6463
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006464 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006465 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006466 vim_free(isn->isn_arg.unlet.ul_name);
6467 break;
6468
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006469 case ISN_STOREOPT:
6470 vim_free(isn->isn_arg.storeopt.so_name);
6471 break;
6472
6473 case ISN_PUSHBLOB: // push blob isn_arg.blob
6474 blob_unref(isn->isn_arg.blob);
6475 break;
6476
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006477 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006478#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006479 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006480#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006481 break;
6482
6483 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006484#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006485 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006486#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006487 break;
6488
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006489 case ISN_UCALL:
6490 vim_free(isn->isn_arg.ufunc.cuf_name);
6491 break;
6492
6493 case ISN_2BOOL:
6494 case ISN_2STRING:
6495 case ISN_ADDBLOB:
6496 case ISN_ADDLIST:
6497 case ISN_BCALL:
6498 case ISN_CATCH:
6499 case ISN_CHECKNR:
6500 case ISN_CHECKTYPE:
6501 case ISN_COMPAREANY:
6502 case ISN_COMPAREBLOB:
6503 case ISN_COMPAREBOOL:
6504 case ISN_COMPAREDICT:
6505 case ISN_COMPAREFLOAT:
6506 case ISN_COMPAREFUNC:
6507 case ISN_COMPARELIST:
6508 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006509 case ISN_COMPARESPECIAL:
6510 case ISN_COMPARESTRING:
6511 case ISN_CONCAT:
6512 case ISN_DCALL:
6513 case ISN_DROP:
6514 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006515 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006516 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006517 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006518 case ISN_EXECCONCAT:
6519 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006520 case ISN_FOR:
6521 case ISN_FUNCREF:
6522 case ISN_INDEX:
6523 case ISN_JUMP:
6524 case ISN_LOAD:
6525 case ISN_LOADSCRIPT:
6526 case ISN_LOADREG:
6527 case ISN_LOADV:
6528 case ISN_NEGATENR:
6529 case ISN_NEWDICT:
6530 case ISN_NEWLIST:
6531 case ISN_OPNR:
6532 case ISN_OPFLOAT:
6533 case ISN_OPANY:
6534 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006535 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006536 case ISN_PUSHF:
6537 case ISN_PUSHNR:
6538 case ISN_PUSHBOOL:
6539 case ISN_PUSHSPEC:
6540 case ISN_RETURN:
6541 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006542 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006543 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006544 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006545 case ISN_STORESCRIPT:
6546 case ISN_THROW:
6547 case ISN_TRY:
6548 // nothing allocated
6549 break;
6550 }
6551}
6552
6553/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006554 * Free all instructions for "dfunc".
6555 */
6556 static void
6557delete_def_function_contents(dfunc_T *dfunc)
6558{
6559 int idx;
6560
6561 ga_clear(&dfunc->df_def_args_isn);
6562
6563 if (dfunc->df_instr != NULL)
6564 {
6565 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6566 delete_instr(dfunc->df_instr + idx);
6567 VIM_CLEAR(dfunc->df_instr);
6568 }
6569
6570 dfunc->df_deleted = TRUE;
6571}
6572
6573/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006574 * When a user function is deleted, delete any associated def function.
6575 */
6576 void
6577delete_def_function(ufunc_T *ufunc)
6578{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006579 if (ufunc->uf_dfunc_idx >= 0)
6580 {
6581 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6582 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006583
Bram Moolenaar20431c92020-03-20 18:39:46 +01006584 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006585 }
6586}
6587
6588#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006589/*
6590 * Free all functions defined with ":def".
6591 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006592 void
6593free_def_functions(void)
6594{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006595 int idx;
6596
6597 for (idx = 0; idx < def_functions.ga_len; ++idx)
6598 {
6599 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6600
6601 delete_def_function_contents(dfunc);
6602 }
6603
6604 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006605}
6606#endif
6607
6608
6609#endif // FEAT_EVAL