blob: 7b433a3b158dc12dbce95dc33ede0b9cbc702339 [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;
Bram Moolenaar939b5db2020-04-28 22:49:08 +0200727 // TODO: whole type, e.g. for a function also arg and return types
728 isn->isn_arg.type.ct_type = vartype->tt_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100729 isn->isn_arg.type.ct_off = offset;
730
731 // type becomes vartype
732 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
733
734 return OK;
735}
736
737/*
738 * Generate an ISN_PUSHNR instruction.
739 */
740 static int
741generate_PUSHNR(cctx_T *cctx, varnumber_T number)
742{
743 isn_T *isn;
744
Bram Moolenaar080457c2020-03-03 21:53:32 +0100745 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100746 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
747 return FAIL;
748 isn->isn_arg.number = number;
749
750 return OK;
751}
752
753/*
754 * Generate an ISN_PUSHBOOL instruction.
755 */
756 static int
757generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
758{
759 isn_T *isn;
760
Bram Moolenaar080457c2020-03-03 21:53:32 +0100761 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100762 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
763 return FAIL;
764 isn->isn_arg.number = number;
765
766 return OK;
767}
768
769/*
770 * Generate an ISN_PUSHSPEC instruction.
771 */
772 static int
773generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
774{
775 isn_T *isn;
776
Bram Moolenaar080457c2020-03-03 21:53:32 +0100777 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100778 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
779 return FAIL;
780 isn->isn_arg.number = number;
781
782 return OK;
783}
784
785#ifdef FEAT_FLOAT
786/*
787 * Generate an ISN_PUSHF instruction.
788 */
789 static int
790generate_PUSHF(cctx_T *cctx, float_T fnumber)
791{
792 isn_T *isn;
793
Bram Moolenaar080457c2020-03-03 21:53:32 +0100794 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100795 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
796 return FAIL;
797 isn->isn_arg.fnumber = fnumber;
798
799 return OK;
800}
801#endif
802
803/*
804 * Generate an ISN_PUSHS instruction.
805 * Consumes "str".
806 */
807 static int
808generate_PUSHS(cctx_T *cctx, char_u *str)
809{
810 isn_T *isn;
811
Bram Moolenaar080457c2020-03-03 21:53:32 +0100812 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100813 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
814 return FAIL;
815 isn->isn_arg.string = str;
816
817 return OK;
818}
819
820/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100821 * Generate an ISN_PUSHCHANNEL instruction.
822 * Consumes "channel".
823 */
824 static int
825generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
826{
827 isn_T *isn;
828
Bram Moolenaar080457c2020-03-03 21:53:32 +0100829 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100830 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
831 return FAIL;
832 isn->isn_arg.channel = channel;
833
834 return OK;
835}
836
837/*
838 * Generate an ISN_PUSHJOB instruction.
839 * Consumes "job".
840 */
841 static int
842generate_PUSHJOB(cctx_T *cctx, job_T *job)
843{
844 isn_T *isn;
845
Bram Moolenaar080457c2020-03-03 21:53:32 +0100846 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100847 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100848 return FAIL;
849 isn->isn_arg.job = job;
850
851 return OK;
852}
853
854/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100855 * Generate an ISN_PUSHBLOB instruction.
856 * Consumes "blob".
857 */
858 static int
859generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
860{
861 isn_T *isn;
862
Bram Moolenaar080457c2020-03-03 21:53:32 +0100863 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100864 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
865 return FAIL;
866 isn->isn_arg.blob = blob;
867
868 return OK;
869}
870
871/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100872 * Generate an ISN_PUSHFUNC instruction with name "name".
873 * Consumes "name".
874 */
875 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200876generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100877{
878 isn_T *isn;
879
Bram Moolenaar080457c2020-03-03 21:53:32 +0100880 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200881 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100882 return FAIL;
883 isn->isn_arg.string = name;
884
885 return OK;
886}
887
888/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100889 * Generate an ISN_STORE instruction.
890 */
891 static int
892generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
893{
894 isn_T *isn;
895
Bram Moolenaar080457c2020-03-03 21:53:32 +0100896 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100897 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
898 return FAIL;
899 if (name != NULL)
900 isn->isn_arg.string = vim_strsave(name);
901 else
902 isn->isn_arg.number = idx;
903
904 return OK;
905}
906
907/*
908 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
909 */
910 static int
911generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
912{
913 isn_T *isn;
914
Bram Moolenaar080457c2020-03-03 21:53:32 +0100915 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100916 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
917 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100918 isn->isn_arg.storenr.stnr_idx = idx;
919 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100920
921 return OK;
922}
923
924/*
925 * Generate an ISN_STOREOPT instruction
926 */
927 static int
928generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
929{
930 isn_T *isn;
931
Bram Moolenaar080457c2020-03-03 21:53:32 +0100932 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100933 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
934 return FAIL;
935 isn->isn_arg.storeopt.so_name = vim_strsave(name);
936 isn->isn_arg.storeopt.so_flags = opt_flags;
937
938 return OK;
939}
940
941/*
942 * Generate an ISN_LOAD or similar instruction.
943 */
944 static int
945generate_LOAD(
946 cctx_T *cctx,
947 isntype_T isn_type,
948 int idx,
949 char_u *name,
950 type_T *type)
951{
952 isn_T *isn;
953
Bram Moolenaar080457c2020-03-03 21:53:32 +0100954 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100955 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
956 return FAIL;
957 if (name != NULL)
958 isn->isn_arg.string = vim_strsave(name);
959 else
960 isn->isn_arg.number = idx;
961
962 return OK;
963}
964
965/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200966 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100967 */
968 static int
969generate_LOADV(
970 cctx_T *cctx,
971 char_u *name,
972 int error)
973{
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200974 int di_flags;
975 int vidx = find_vim_var(name, &di_flags);
976 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100977
Bram Moolenaar080457c2020-03-03 21:53:32 +0100978 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100979 if (vidx < 0)
980 {
981 if (error)
982 semsg(_(e_var_notfound), name);
983 return FAIL;
984 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200985 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100986
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200987 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100988}
989
990/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200991 * Generate an ISN_UNLET instruction.
992 */
993 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200994generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200995{
996 isn_T *isn;
997
998 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200999 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001000 return FAIL;
1001 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1002 isn->isn_arg.unlet.ul_forceit = forceit;
1003
1004 return OK;
1005}
1006
1007/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001008 * Generate an ISN_LOADS instruction.
1009 */
1010 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001011generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001012 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001013 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001014 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001015 int sid,
1016 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001017{
1018 isn_T *isn;
1019
Bram Moolenaar080457c2020-03-03 21:53:32 +01001020 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001021 if (isn_type == ISN_LOADS)
1022 isn = generate_instr_type(cctx, isn_type, type);
1023 else
1024 isn = generate_instr_drop(cctx, isn_type, 1);
1025 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001026 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001027 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1028 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001029
1030 return OK;
1031}
1032
1033/*
1034 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1035 */
1036 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001037generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001038 cctx_T *cctx,
1039 isntype_T isn_type,
1040 int sid,
1041 int idx,
1042 type_T *type)
1043{
1044 isn_T *isn;
1045
Bram Moolenaar080457c2020-03-03 21:53:32 +01001046 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001047 if (isn_type == ISN_LOADSCRIPT)
1048 isn = generate_instr_type(cctx, isn_type, type);
1049 else
1050 isn = generate_instr_drop(cctx, isn_type, 1);
1051 if (isn == NULL)
1052 return FAIL;
1053 isn->isn_arg.script.script_sid = sid;
1054 isn->isn_arg.script.script_idx = idx;
1055 return OK;
1056}
1057
1058/*
1059 * Generate an ISN_NEWLIST instruction.
1060 */
1061 static int
1062generate_NEWLIST(cctx_T *cctx, int count)
1063{
1064 isn_T *isn;
1065 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001066 type_T *type;
1067 type_T *member;
1068
Bram Moolenaar080457c2020-03-03 21:53:32 +01001069 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001070 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1071 return FAIL;
1072 isn->isn_arg.number = count;
1073
1074 // drop the value types
1075 stack->ga_len -= count;
1076
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001077 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001078 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001079 if (count > 0)
1080 member = ((type_T **)stack->ga_data)[stack->ga_len];
1081 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001082 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001083 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001084
1085 // add the list type to the type stack
1086 if (ga_grow(stack, 1) == FAIL)
1087 return FAIL;
1088 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1089 ++stack->ga_len;
1090
1091 return OK;
1092}
1093
1094/*
1095 * Generate an ISN_NEWDICT instruction.
1096 */
1097 static int
1098generate_NEWDICT(cctx_T *cctx, int count)
1099{
1100 isn_T *isn;
1101 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001102 type_T *type;
1103 type_T *member;
1104
Bram Moolenaar080457c2020-03-03 21:53:32 +01001105 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001106 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1107 return FAIL;
1108 isn->isn_arg.number = count;
1109
1110 // drop the key and value types
1111 stack->ga_len -= 2 * count;
1112
Bram Moolenaar436472f2020-02-20 22:54:43 +01001113 // Use the first value type for the list member type. Use "void" for an
1114 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001115 if (count > 0)
1116 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1117 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001118 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001119 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001120
1121 // add the dict type to the type stack
1122 if (ga_grow(stack, 1) == FAIL)
1123 return FAIL;
1124 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1125 ++stack->ga_len;
1126
1127 return OK;
1128}
1129
1130/*
1131 * Generate an ISN_FUNCREF instruction.
1132 */
1133 static int
1134generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1135{
1136 isn_T *isn;
1137 garray_T *stack = &cctx->ctx_type_stack;
1138
Bram Moolenaar080457c2020-03-03 21:53:32 +01001139 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001140 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1141 return FAIL;
1142 isn->isn_arg.number = dfunc_idx;
1143
1144 if (ga_grow(stack, 1) == FAIL)
1145 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001146 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001147 // TODO: argument and return types
1148 ++stack->ga_len;
1149
1150 return OK;
1151}
1152
1153/*
1154 * Generate an ISN_JUMP instruction.
1155 */
1156 static int
1157generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1158{
1159 isn_T *isn;
1160 garray_T *stack = &cctx->ctx_type_stack;
1161
Bram Moolenaar080457c2020-03-03 21:53:32 +01001162 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001163 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1164 return FAIL;
1165 isn->isn_arg.jump.jump_when = when;
1166 isn->isn_arg.jump.jump_where = where;
1167
1168 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1169 --stack->ga_len;
1170
1171 return OK;
1172}
1173
1174 static int
1175generate_FOR(cctx_T *cctx, int loop_idx)
1176{
1177 isn_T *isn;
1178 garray_T *stack = &cctx->ctx_type_stack;
1179
Bram Moolenaar080457c2020-03-03 21:53:32 +01001180 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001181 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1182 return FAIL;
1183 isn->isn_arg.forloop.for_idx = loop_idx;
1184
1185 if (ga_grow(stack, 1) == FAIL)
1186 return FAIL;
1187 // type doesn't matter, will be stored next
1188 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1189 ++stack->ga_len;
1190
1191 return OK;
1192}
1193
1194/*
1195 * Generate an ISN_BCALL instruction.
1196 * Return FAIL if the number of arguments is wrong.
1197 */
1198 static int
1199generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1200{
1201 isn_T *isn;
1202 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001203 type_T *argtypes[MAX_FUNC_ARGS];
1204 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001205
Bram Moolenaar080457c2020-03-03 21:53:32 +01001206 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001207 if (check_internal_func(func_idx, argcount) == FAIL)
1208 return FAIL;
1209
1210 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1211 return FAIL;
1212 isn->isn_arg.bfunc.cbf_idx = func_idx;
1213 isn->isn_arg.bfunc.cbf_argcount = argcount;
1214
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001215 for (i = 0; i < argcount; ++i)
1216 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1217
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001218 stack->ga_len -= argcount; // drop the arguments
1219 if (ga_grow(stack, 1) == FAIL)
1220 return FAIL;
1221 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001222 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001223 ++stack->ga_len; // add return value
1224
1225 return OK;
1226}
1227
1228/*
1229 * Generate an ISN_DCALL or ISN_UCALL instruction.
1230 * Return FAIL if the number of arguments is wrong.
1231 */
1232 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001233generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001234{
1235 isn_T *isn;
1236 garray_T *stack = &cctx->ctx_type_stack;
1237 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001238 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001239
Bram Moolenaar080457c2020-03-03 21:53:32 +01001240 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001241 if (argcount > regular_args && !has_varargs(ufunc))
1242 {
1243 semsg(_(e_toomanyarg), ufunc->uf_name);
1244 return FAIL;
1245 }
1246 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1247 {
1248 semsg(_(e_toofewarg), ufunc->uf_name);
1249 return FAIL;
1250 }
1251
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001252 if (ufunc->uf_dfunc_idx >= 0)
1253 {
1254 int i;
1255
1256 for (i = 0; i < argcount; ++i)
1257 {
1258 type_T *expected;
1259 type_T *actual;
1260
1261 if (i < regular_args)
1262 {
1263 if (ufunc->uf_arg_types == NULL)
1264 continue;
1265 expected = ufunc->uf_arg_types[i];
1266 }
1267 else
1268 expected = ufunc->uf_va_type->tt_member;
1269 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1270 if (check_type(expected, actual, FALSE) == FAIL)
1271 {
1272 arg_type_mismatch(expected, actual, i + 1);
1273 return FAIL;
1274 }
1275 }
1276 }
1277
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001278 if ((isn = generate_instr(cctx,
1279 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1280 return FAIL;
1281 if (ufunc->uf_dfunc_idx >= 0)
1282 {
1283 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1284 isn->isn_arg.dfunc.cdf_argcount = argcount;
1285 }
1286 else
1287 {
1288 // A user function may be deleted and redefined later, can't use the
1289 // ufunc pointer, need to look it up again at runtime.
1290 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1291 isn->isn_arg.ufunc.cuf_argcount = argcount;
1292 }
1293
1294 stack->ga_len -= argcount; // drop the arguments
1295 if (ga_grow(stack, 1) == FAIL)
1296 return FAIL;
1297 // add return value
1298 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1299 ++stack->ga_len;
1300
1301 return OK;
1302}
1303
1304/*
1305 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1306 */
1307 static int
1308generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1309{
1310 isn_T *isn;
1311 garray_T *stack = &cctx->ctx_type_stack;
1312
Bram Moolenaar080457c2020-03-03 21:53:32 +01001313 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001314 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1315 return FAIL;
1316 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1317 isn->isn_arg.ufunc.cuf_argcount = argcount;
1318
1319 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001320 if (ga_grow(stack, 1) == FAIL)
1321 return FAIL;
1322 // add return value
1323 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1324 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001325
1326 return OK;
1327}
1328
1329/*
1330 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001331 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001332 */
1333 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001334generate_PCALL(
1335 cctx_T *cctx,
1336 int argcount,
1337 char_u *name,
1338 type_T *type,
1339 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001340{
1341 isn_T *isn;
1342 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001343 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001344
Bram Moolenaar080457c2020-03-03 21:53:32 +01001345 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001346
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001347 if (type->tt_type == VAR_ANY)
1348 ret_type = &t_any;
1349 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
1350 ret_type = type->tt_member;
1351 else
1352 {
1353 semsg(_("E1085: Not a callable type: %s"), name);
1354 return FAIL;
1355 }
1356
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001357 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1358 return FAIL;
1359 isn->isn_arg.pfunc.cpf_top = at_top;
1360 isn->isn_arg.pfunc.cpf_argcount = argcount;
1361
1362 stack->ga_len -= argcount; // drop the arguments
1363
1364 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001365 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001366
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001367 // If partial is above the arguments it must be cleared and replaced with
1368 // the return value.
1369 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1370 return FAIL;
1371
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001372 return OK;
1373}
1374
1375/*
1376 * Generate an ISN_MEMBER instruction.
1377 */
1378 static int
1379generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1380{
1381 isn_T *isn;
1382 garray_T *stack = &cctx->ctx_type_stack;
1383 type_T *type;
1384
Bram Moolenaar080457c2020-03-03 21:53:32 +01001385 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001386 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1387 return FAIL;
1388 isn->isn_arg.string = vim_strnsave(name, (int)len);
1389
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001390 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001391 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001392 if (type->tt_type != VAR_DICT && type != &t_any)
1393 {
1394 emsg(_(e_dictreq));
1395 return FAIL;
1396 }
1397 // change dict type to dict member type
1398 if (type->tt_type == VAR_DICT)
1399 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001400
1401 return OK;
1402}
1403
1404/*
1405 * Generate an ISN_ECHO instruction.
1406 */
1407 static int
1408generate_ECHO(cctx_T *cctx, int with_white, int count)
1409{
1410 isn_T *isn;
1411
Bram Moolenaar080457c2020-03-03 21:53:32 +01001412 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001413 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1414 return FAIL;
1415 isn->isn_arg.echo.echo_with_white = with_white;
1416 isn->isn_arg.echo.echo_count = count;
1417
1418 return OK;
1419}
1420
Bram Moolenaarad39c092020-02-26 18:23:43 +01001421/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001422 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001423 */
1424 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001425generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001426{
1427 isn_T *isn;
1428
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001429 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001430 return FAIL;
1431 isn->isn_arg.number = count;
1432
1433 return OK;
1434}
1435
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001436 static int
1437generate_EXEC(cctx_T *cctx, char_u *line)
1438{
1439 isn_T *isn;
1440
Bram Moolenaar080457c2020-03-03 21:53:32 +01001441 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001442 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1443 return FAIL;
1444 isn->isn_arg.string = vim_strsave(line);
1445 return OK;
1446}
1447
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001448 static int
1449generate_EXECCONCAT(cctx_T *cctx, int count)
1450{
1451 isn_T *isn;
1452
1453 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1454 return FAIL;
1455 isn->isn_arg.number = count;
1456 return OK;
1457}
1458
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001459/*
1460 * Reserve space for a local variable.
1461 * Return the index or -1 if it failed.
1462 */
1463 static int
1464reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1465{
1466 int idx;
1467 lvar_T *lvar;
1468
1469 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1470 {
1471 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1472 return -1;
1473 }
1474
1475 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1476 return -1;
1477 idx = cctx->ctx_locals.ga_len;
1478 if (cctx->ctx_max_local < idx + 1)
1479 cctx->ctx_max_local = idx + 1;
1480 ++cctx->ctx_locals.ga_len;
1481
1482 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1483 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1484 lvar->lv_const = isConst;
1485 lvar->lv_type = type;
1486
1487 return idx;
1488}
1489
1490/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001491 * Remove local variables above "new_top".
1492 */
1493 static void
1494unwind_locals(cctx_T *cctx, int new_top)
1495{
1496 if (cctx->ctx_locals.ga_len > new_top)
1497 {
1498 int idx;
1499 lvar_T *lvar;
1500
1501 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1502 {
1503 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1504 vim_free(lvar->lv_name);
1505 }
1506 }
1507 cctx->ctx_locals.ga_len = new_top;
1508}
1509
1510/*
1511 * Free all local variables.
1512 */
1513 static void
1514free_local(cctx_T *cctx)
1515{
1516 unwind_locals(cctx, 0);
1517 ga_clear(&cctx->ctx_locals);
1518}
1519
1520/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001521 * Skip over a type definition and return a pointer to just after it.
1522 */
1523 char_u *
1524skip_type(char_u *start)
1525{
1526 char_u *p = start;
1527
1528 while (ASCII_ISALNUM(*p) || *p == '_')
1529 ++p;
1530
1531 // Skip over "<type>"; this is permissive about white space.
1532 if (*skipwhite(p) == '<')
1533 {
1534 p = skipwhite(p);
1535 p = skip_type(skipwhite(p + 1));
1536 p = skipwhite(p);
1537 if (*p == '>')
1538 ++p;
1539 }
1540 return p;
1541}
1542
1543/*
1544 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001545 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001546 * Returns NULL in case of failure.
1547 */
1548 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001549parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001550{
1551 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001552 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001553
1554 if (**arg != '<')
1555 {
1556 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001557 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001558 else
1559 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001560 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001561 }
1562 *arg = skipwhite(*arg + 1);
1563
Bram Moolenaard77a8522020-04-03 21:59:57 +02001564 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001565
1566 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001567 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001568 {
1569 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001570 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001571 }
1572 ++*arg;
1573
1574 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001575 return get_list_type(member_type, type_gap);
1576 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001577}
1578
1579/*
1580 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001581 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001582 */
1583 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001584parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001585{
1586 char_u *p = *arg;
1587 size_t len;
1588
1589 // skip over the first word
1590 while (ASCII_ISALNUM(*p) || *p == '_')
1591 ++p;
1592 len = p - *arg;
1593
1594 switch (**arg)
1595 {
1596 case 'a':
1597 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1598 {
1599 *arg += len;
1600 return &t_any;
1601 }
1602 break;
1603 case 'b':
1604 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1605 {
1606 *arg += len;
1607 return &t_bool;
1608 }
1609 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1610 {
1611 *arg += len;
1612 return &t_blob;
1613 }
1614 break;
1615 case 'c':
1616 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1617 {
1618 *arg += len;
1619 return &t_channel;
1620 }
1621 break;
1622 case 'd':
1623 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1624 {
1625 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001626 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001627 }
1628 break;
1629 case 'f':
1630 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1631 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001632#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001633 *arg += len;
1634 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001635#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001636 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001637 return &t_any;
1638#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001639 }
1640 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1641 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001642 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001643 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001644 int argcount = -1;
1645 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001646 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001647 type_T *arg_type[MAX_FUNC_ARGS + 1];
1648
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001649 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001650 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001651 if (**arg == '(')
1652 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001653 // "func" may or may not return a value, "func()" does
1654 // not return a value.
1655 ret_type = &t_void;
1656
Bram Moolenaard77a8522020-04-03 21:59:57 +02001657 p = ++*arg;
1658 argcount = 0;
1659 while (*p != NUL && *p != ')')
1660 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001661 if (*p == '?')
1662 {
1663 if (first_optional == -1)
1664 first_optional = argcount;
1665 ++p;
1666 }
1667 else if (first_optional != -1)
1668 {
1669 emsg(_("E1007: mandatory argument after optional argument"));
1670 return &t_any;
1671 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001672 else if (STRNCMP(p, "...", 3) == 0)
1673 {
1674 flags |= TTFLAG_VARARGS;
1675 p += 3;
1676 }
1677
1678 arg_type[argcount++] = parse_type(&p, type_gap);
1679
1680 // Nothing comes after "...{type}".
1681 if (flags & TTFLAG_VARARGS)
1682 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001683
Bram Moolenaard77a8522020-04-03 21:59:57 +02001684 if (*p != ',' && *skipwhite(p) == ',')
1685 {
1686 semsg(_(e_no_white_before), ",");
1687 return &t_any;
1688 }
1689 if (*p == ',')
1690 {
1691 ++p;
1692 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001693 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001694 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001695 return &t_any;
1696 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001697 }
1698 p = skipwhite(p);
1699 if (argcount == MAX_FUNC_ARGS)
1700 {
1701 emsg(_("E740: Too many argument types"));
1702 return &t_any;
1703 }
1704 }
1705
1706 p = skipwhite(p);
1707 if (*p != ')')
1708 {
1709 emsg(_(e_missing_close));
1710 return &t_any;
1711 }
1712 *arg = p + 1;
1713 }
1714 if (**arg == ':')
1715 {
1716 // parse return type
1717 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001718 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001719 semsg(_(e_white_after), ":");
1720 *arg = skipwhite(*arg);
1721 ret_type = parse_type(arg, type_gap);
1722 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001723 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001724 type = get_func_type(ret_type, argcount, type_gap);
1725 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001726 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001727 type = alloc_func_type(ret_type, argcount, type_gap);
1728 type->tt_flags = flags;
1729 if (argcount > 0)
1730 {
1731 type->tt_argcount = argcount;
1732 type->tt_min_argcount = first_optional == -1
1733 ? argcount : first_optional;
1734 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001735 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001736 return &t_any;
1737 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001738 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001739 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001740 }
1741 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001742 }
1743 break;
1744 case 'j':
1745 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1746 {
1747 *arg += len;
1748 return &t_job;
1749 }
1750 break;
1751 case 'l':
1752 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1753 {
1754 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001755 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001756 }
1757 break;
1758 case 'n':
1759 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1760 {
1761 *arg += len;
1762 return &t_number;
1763 }
1764 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001765 case 's':
1766 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1767 {
1768 *arg += len;
1769 return &t_string;
1770 }
1771 break;
1772 case 'v':
1773 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1774 {
1775 *arg += len;
1776 return &t_void;
1777 }
1778 break;
1779 }
1780
1781 semsg(_("E1010: Type not recognized: %s"), *arg);
1782 return &t_any;
1783}
1784
1785/*
1786 * Check if "type1" and "type2" are exactly the same.
1787 */
1788 static int
1789equal_type(type_T *type1, type_T *type2)
1790{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001791 int i;
1792
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001793 if (type1->tt_type != type2->tt_type)
1794 return FALSE;
1795 switch (type1->tt_type)
1796 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001797 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001798 case VAR_ANY:
1799 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001800 case VAR_SPECIAL:
1801 case VAR_BOOL:
1802 case VAR_NUMBER:
1803 case VAR_FLOAT:
1804 case VAR_STRING:
1805 case VAR_BLOB:
1806 case VAR_JOB:
1807 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001808 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001809 case VAR_LIST:
1810 case VAR_DICT:
1811 return equal_type(type1->tt_member, type2->tt_member);
1812 case VAR_FUNC:
1813 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001814 if (!equal_type(type1->tt_member, type2->tt_member)
1815 || type1->tt_argcount != type2->tt_argcount)
1816 return FALSE;
1817 if (type1->tt_argcount < 0
1818 || type1->tt_args == NULL || type2->tt_args == NULL)
1819 return TRUE;
1820 for (i = 0; i < type1->tt_argcount; ++i)
1821 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1822 return FALSE;
1823 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001824 }
1825 return TRUE;
1826}
1827
1828/*
1829 * Find the common type of "type1" and "type2" and put it in "dest".
1830 * "type2" and "dest" may be the same.
1831 */
1832 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001833common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001834{
1835 if (equal_type(type1, type2))
1836 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001837 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001838 return;
1839 }
1840
1841 if (type1->tt_type == type2->tt_type)
1842 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001843 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1844 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001845 type_T *common;
1846
Bram Moolenaard77a8522020-04-03 21:59:57 +02001847 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001848 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001849 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001850 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001851 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001852 return;
1853 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001854 if (type1->tt_type == VAR_FUNC)
1855 {
1856 type_T *common;
1857
1858 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1859 if (type1->tt_argcount == type2->tt_argcount
1860 && type1->tt_argcount >= 0)
1861 {
1862 int argcount = type1->tt_argcount;
1863 int i;
1864
1865 *dest = alloc_func_type(common, argcount, type_gap);
1866 if (type1->tt_args != NULL && type2->tt_args != NULL)
1867 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001868 if (func_type_add_arg_types(*dest, argcount,
1869 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001870 for (i = 0; i < argcount; ++i)
1871 common_type(type1->tt_args[i], type2->tt_args[i],
1872 &(*dest)->tt_args[i], type_gap);
1873 }
1874 }
1875 else
1876 *dest = alloc_func_type(common, -1, type_gap);
1877 return;
1878 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001879 }
1880
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001881 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001882}
1883
1884 char *
1885vartype_name(vartype_T type)
1886{
1887 switch (type)
1888 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001889 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001890 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001891 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001892 case VAR_SPECIAL: return "special";
1893 case VAR_BOOL: return "bool";
1894 case VAR_NUMBER: return "number";
1895 case VAR_FLOAT: return "float";
1896 case VAR_STRING: return "string";
1897 case VAR_BLOB: return "blob";
1898 case VAR_JOB: return "job";
1899 case VAR_CHANNEL: return "channel";
1900 case VAR_LIST: return "list";
1901 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001902
1903 case VAR_FUNC:
1904 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001905 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001906 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001907}
1908
1909/*
1910 * Return the name of a type.
1911 * The result may be in allocated memory, in which case "tofree" is set.
1912 */
1913 char *
1914type_name(type_T *type, char **tofree)
1915{
1916 char *name = vartype_name(type->tt_type);
1917
1918 *tofree = NULL;
1919 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1920 {
1921 char *member_free;
1922 char *member_name = type_name(type->tt_member, &member_free);
1923 size_t len;
1924
1925 len = STRLEN(name) + STRLEN(member_name) + 3;
1926 *tofree = alloc(len);
1927 if (*tofree != NULL)
1928 {
1929 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1930 vim_free(member_free);
1931 return *tofree;
1932 }
1933 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001934 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001935 {
1936 garray_T ga;
1937 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001938 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001939
1940 ga_init2(&ga, 1, 100);
1941 if (ga_grow(&ga, 20) == FAIL)
1942 return "[unknown]";
1943 *tofree = ga.ga_data;
1944 STRCPY(ga.ga_data, "func(");
1945 ga.ga_len += 5;
1946
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001947 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001948 {
1949 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001950 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001951 int len;
1952
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001953 if (type->tt_args == NULL)
1954 arg_type = "[unknown]";
1955 else
1956 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001957 if (i > 0)
1958 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001959 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001960 ga.ga_len += 2;
1961 }
1962 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001963 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001964 {
1965 vim_free(arg_free);
1966 return "[unknown]";
1967 }
1968 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001969 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001970 {
1971 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1972 ga.ga_len += 3;
1973 }
1974 else if (i >= type->tt_min_argcount)
1975 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001976 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001977 ga.ga_len += len;
1978 vim_free(arg_free);
1979 }
1980
1981 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001982 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001983 else
1984 {
1985 char *ret_free;
1986 char *ret_name = type_name(type->tt_member, &ret_free);
1987 int len;
1988
1989 len = (int)STRLEN(ret_name) + 4;
1990 if (ga_grow(&ga, len) == FAIL)
1991 {
1992 vim_free(ret_free);
1993 return "[unknown]";
1994 }
1995 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001996 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1997 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001998 vim_free(ret_free);
1999 }
2000 return ga.ga_data;
2001 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002002
2003 return name;
2004}
2005
2006/*
2007 * Find "name" in script-local items of script "sid".
2008 * Returns the index in "sn_var_vals" if found.
2009 * If found but not in "sn_var_vals" returns -1.
2010 * If not found returns -2.
2011 */
2012 int
2013get_script_item_idx(int sid, char_u *name, int check_writable)
2014{
2015 hashtab_T *ht;
2016 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002017 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002018 int idx;
2019
2020 // First look the name up in the hashtable.
2021 if (sid <= 0 || sid > script_items.ga_len)
2022 return -1;
2023 ht = &SCRIPT_VARS(sid);
2024 di = find_var_in_ht(ht, 0, name, TRUE);
2025 if (di == NULL)
2026 return -2;
2027
2028 // Now find the svar_T index in sn_var_vals.
2029 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2030 {
2031 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2032
2033 if (sv->sv_tv == &di->di_tv)
2034 {
2035 if (check_writable && sv->sv_const)
2036 semsg(_(e_readonlyvar), name);
2037 return idx;
2038 }
2039 }
2040 return -1;
2041}
2042
2043/*
2044 * Find "name" in imported items of the current script/
2045 */
2046 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002047find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002048{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002049 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002050 int idx;
2051
2052 if (cctx != NULL)
2053 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2054 {
2055 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2056 + idx;
2057
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002058 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2059 : STRLEN(import->imp_name) == len
2060 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002061 return import;
2062 }
2063
2064 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2065 {
2066 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2067
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002068 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2069 : STRLEN(import->imp_name) == len
2070 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002071 return import;
2072 }
2073 return NULL;
2074}
2075
2076/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002077 * Free all imported variables.
2078 */
2079 static void
2080free_imported(cctx_T *cctx)
2081{
2082 int idx;
2083
2084 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2085 {
2086 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2087
2088 vim_free(import->imp_name);
2089 }
2090 ga_clear(&cctx->ctx_imports);
2091}
2092
2093/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002094 * Get the next line of the function from "cctx".
2095 * Returns NULL when at the end.
2096 */
2097 static char_u *
2098next_line_from_context(cctx_T *cctx)
2099{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002100 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002101
2102 do
2103 {
2104 ++cctx->ctx_lnum;
2105 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002106 {
2107 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002108 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002109 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002110 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002111 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002112 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2113 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002114 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002115 return line;
2116}
2117
2118/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002119 * Return TRUE if "p" points at a "#" but not at "#{".
2120 */
2121 static int
2122comment_start(char_u *p)
2123{
2124 return p[0] == '#' && p[1] != '{';
2125}
2126
2127/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002128 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002129 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002130 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2131 */
2132 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002133may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002134{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002135 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002136 {
2137 char_u *next = next_line_from_context(cctx);
2138
2139 if (next == NULL)
2140 return FAIL;
2141 *arg = skipwhite(next);
2142 }
2143 return OK;
2144}
2145
2146/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002147 * Generate an instruction to load script-local variable "name", without the
2148 * leading "s:".
2149 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002150 */
2151 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002152compile_load_scriptvar(
2153 cctx_T *cctx,
2154 char_u *name, // variable NUL terminated
2155 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002156 char_u **end, // end of variable
2157 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002158{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002159 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002160 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2161 imported_T *import;
2162
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002163 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002164 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002165 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002166 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2167 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002168 }
2169 if (idx >= 0)
2170 {
2171 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2172
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002173 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002174 current_sctx.sc_sid, idx, sv->sv_type);
2175 return OK;
2176 }
2177
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002178 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002179 if (import != NULL)
2180 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002181 if (import->imp_all)
2182 {
2183 char_u *p = skipwhite(*end);
2184 int name_len;
2185 ufunc_T *ufunc;
2186 type_T *type;
2187
2188 // Used "import * as Name", need to lookup the member.
2189 if (*p != '.')
2190 {
2191 semsg(_("E1060: expected dot after name: %s"), start);
2192 return FAIL;
2193 }
2194 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002195 if (VIM_ISWHITE(*p))
2196 {
2197 emsg(_("E1074: no white space allowed after dot"));
2198 return FAIL;
2199 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002200
2201 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2202 // TODO: what if it is a function?
2203 if (idx < 0)
2204 return FAIL;
2205 *end = p;
2206
2207 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2208 import->imp_sid,
2209 idx,
2210 type);
2211 }
2212 else
2213 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002214 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002215 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2216 import->imp_sid,
2217 import->imp_var_vals_idx,
2218 import->imp_type);
2219 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002220 return OK;
2221 }
2222
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002223 if (error)
2224 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002225 return FAIL;
2226}
2227
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002228 static int
2229generate_funcref(cctx_T *cctx, char_u *name)
2230{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002231 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002232
2233 if (ufunc == NULL)
2234 return FAIL;
2235
2236 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2237}
2238
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002239/*
2240 * Compile a variable name into a load instruction.
2241 * "end" points to just after the name.
2242 * When "error" is FALSE do not give an error when not found.
2243 */
2244 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002245compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002246{
2247 type_T *type;
2248 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002249 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002250 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002251 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002252
2253 if (*(*arg + 1) == ':')
2254 {
2255 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002256 if (end <= *arg + 2)
2257 name = vim_strsave((char_u *)"[empty]");
2258 else
2259 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002260 if (name == NULL)
2261 return FAIL;
2262
2263 if (**arg == 'v')
2264 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002265 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002266 }
2267 else if (**arg == 'g')
2268 {
2269 // Global variables can be defined later, thus we don't check if it
2270 // exists, give error at runtime.
2271 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2272 }
2273 else if (**arg == 's')
2274 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002275 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002276 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002277 else if (**arg == 'b')
2278 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002279 // Buffer-local variables can be defined later, thus we don't check
2280 // if it exists, give error at runtime.
2281 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002282 }
2283 else if (**arg == 'w')
2284 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002285 // Window-local variables can be defined later, thus we don't check
2286 // if it exists, give error at runtime.
2287 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002288 }
2289 else if (**arg == 't')
2290 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002291 // Tabpage-local variables can be defined later, thus we don't
2292 // check if it exists, give error at runtime.
2293 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002294 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002295 else
2296 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002297 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002298 goto theend;
2299 }
2300 }
2301 else
2302 {
2303 size_t len = end - *arg;
2304 int idx;
2305 int gen_load = FALSE;
2306
2307 name = vim_strnsave(*arg, end - *arg);
2308 if (name == NULL)
2309 return FAIL;
2310
2311 idx = lookup_arg(*arg, len, cctx);
2312 if (idx >= 0)
2313 {
2314 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2315 type = cctx->ctx_ufunc->uf_arg_types[idx];
2316 else
2317 type = &t_any;
2318
2319 // Arguments are located above the frame pointer.
2320 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2321 if (cctx->ctx_ufunc->uf_va_name != NULL)
2322 --idx;
2323 gen_load = TRUE;
2324 }
2325 else if (lookup_vararg(*arg, len, cctx))
2326 {
2327 // varargs is always the last argument
2328 idx = -STACK_FRAME_SIZE - 1;
2329 type = cctx->ctx_ufunc->uf_va_type;
2330 gen_load = TRUE;
2331 }
2332 else
2333 {
2334 idx = lookup_local(*arg, len, cctx);
2335 if (idx >= 0)
2336 {
2337 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2338 gen_load = TRUE;
2339 }
2340 else
2341 {
2342 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2343 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2344 res = generate_PUSHBOOL(cctx, **arg == 't'
2345 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002346 else
2347 {
2348 // "var" can be script-local even without using "s:" if it
2349 // already exists.
2350 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2351 == SCRIPT_VERSION_VIM9
2352 || lookup_script(*arg, len) == OK)
2353 res = compile_load_scriptvar(cctx, name, *arg, &end,
2354 FALSE);
2355
2356 // When the name starts with an uppercase letter or "x:" it
2357 // can be a user defined function.
2358 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2359 res = generate_funcref(cctx, name);
2360 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002361 }
2362 }
2363 if (gen_load)
2364 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2365 }
2366
2367 *arg = end;
2368
2369theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002370 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002371 semsg(_(e_var_notfound), name);
2372 vim_free(name);
2373 return res;
2374}
2375
2376/*
2377 * Compile the argument expressions.
2378 * "arg" points to just after the "(" and is advanced to after the ")"
2379 */
2380 static int
2381compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2382{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002383 char_u *p = *arg;
2384 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002385
Bram Moolenaare6085c52020-04-12 20:19:16 +02002386 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002387 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002388 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002389 {
2390 p = next_line_from_context(cctx);
2391 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002392 goto failret;
2393 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002394 p = skipwhite(p);
2395 }
2396 if (*p == ')')
2397 {
2398 *arg = p + 1;
2399 return OK;
2400 }
2401
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002402 if (compile_expr1(&p, cctx) == FAIL)
2403 return FAIL;
2404 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002405
2406 if (*p != ',' && *skipwhite(p) == ',')
2407 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002408 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002409 p = skipwhite(p);
2410 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002411 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002412 {
2413 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002414 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002415 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002416 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002417 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002418 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002419 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002420failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002421 emsg(_(e_missing_close));
2422 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002423}
2424
2425/*
2426 * Compile a function call: name(arg1, arg2)
2427 * "arg" points to "name", "arg + varlen" to the "(".
2428 * "argcount_init" is 1 for "value->method()"
2429 * Instructions:
2430 * EVAL arg1
2431 * EVAL arg2
2432 * BCALL / DCALL / UCALL
2433 */
2434 static int
2435compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2436{
2437 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002438 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002439 int argcount = argcount_init;
2440 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002441 char_u fname_buf[FLEN_FIXED + 1];
2442 char_u *tofree = NULL;
2443 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002444 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002445 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002446
2447 if (varlen >= sizeof(namebuf))
2448 {
2449 semsg(_("E1011: name too long: %s"), name);
2450 return FAIL;
2451 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002452 vim_strncpy(namebuf, *arg, varlen);
2453 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002454
2455 *arg = skipwhite(*arg + varlen + 1);
2456 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002457 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002458
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002459 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002460 {
2461 int idx;
2462
2463 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002464 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002465 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002466 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002467 else
2468 semsg(_(e_unknownfunc), namebuf);
2469 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002470 }
2471
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002472 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002473 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002474 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002475 {
2476 res = generate_CALL(cctx, ufunc, argcount);
2477 goto theend;
2478 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002479
2480 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002481 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002482 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002483 if (STRNCMP(namebuf, "g:", 2) != 0
2484 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002485 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002486 garray_T *stack = &cctx->ctx_type_stack;
2487 type_T *type;
2488
2489 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2490 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002491 goto theend;
2492 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002493
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002494 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002495 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002496 if (STRNCMP(namebuf, "g:", 2) == 0)
2497 res = generate_UCALL(cctx, name, argcount);
2498 else
2499 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002500
2501theend:
2502 vim_free(tofree);
2503 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002504}
2505
2506// like NAMESPACE_CHAR but with 'a' and 'l'.
2507#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2508
2509/*
2510 * Find the end of a variable or function name. Unlike find_name_end() this
2511 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002512 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002513 * Return a pointer to just after the name. Equal to "arg" if there is no
2514 * valid name.
2515 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002516 static char_u *
2517to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002518{
2519 char_u *p;
2520
2521 // Quick check for valid starting character.
2522 if (!eval_isnamec1(*arg))
2523 return arg;
2524
2525 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2526 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2527 // and can be used in slice "[n:]".
2528 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002529 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002530 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2531 break;
2532 return p;
2533}
2534
2535/*
2536 * Like to_name_end() but also skip over a list or dict constant.
2537 */
2538 char_u *
2539to_name_const_end(char_u *arg)
2540{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002541 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002542 typval_T rettv;
2543
2544 if (p == arg && *arg == '[')
2545 {
2546
2547 // Can be "[1, 2, 3]->Func()".
2548 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2549 p = arg;
2550 }
2551 else if (p == arg && *arg == '#' && arg[1] == '{')
2552 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002553 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002554 ++p;
2555 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2556 p = arg;
2557 }
2558 else if (p == arg && *arg == '{')
2559 {
2560 int ret = get_lambda_tv(&p, &rettv, FALSE);
2561
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002562 // Can be "{x -> ret}()".
2563 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002564 if (ret == NOTDONE)
2565 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2566 if (ret != OK)
2567 p = arg;
2568 }
2569
2570 return p;
2571}
2572
2573 static void
2574type_mismatch(type_T *expected, type_T *actual)
2575{
2576 char *tofree1, *tofree2;
2577
2578 semsg(_("E1013: type mismatch, expected %s but got %s"),
2579 type_name(expected, &tofree1), type_name(actual, &tofree2));
2580 vim_free(tofree1);
2581 vim_free(tofree2);
2582}
2583
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002584 static void
2585arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2586{
2587 char *tofree1, *tofree2;
2588
2589 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2590 argidx,
2591 type_name(expected, &tofree1), type_name(actual, &tofree2));
2592 vim_free(tofree1);
2593 vim_free(tofree2);
2594}
2595
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002596/*
2597 * Check if the expected and actual types match.
Bram Moolenaar939b5db2020-04-28 22:49:08 +02002598 * Does not allow for assigning "any" to a specific type.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002599 */
2600 static int
2601check_type(type_T *expected, type_T *actual, int give_msg)
2602{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002603 int ret = OK;
2604
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002605 // When expected is "unknown" we accept any actual type.
2606 // When expected is "any" we accept any actual type except "void".
2607 if (expected->tt_type != VAR_UNKNOWN
Bram Moolenaar939b5db2020-04-28 22:49:08 +02002608 && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID))
2609
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002610 {
2611 if (expected->tt_type != actual->tt_type)
2612 {
2613 if (give_msg)
2614 type_mismatch(expected, actual);
2615 return FAIL;
2616 }
2617 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2618 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002619 // "unknown" is used for an empty list or dict
2620 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002621 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002622 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002623 else if (expected->tt_type == VAR_FUNC)
2624 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002625 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002626 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2627 if (ret == OK && expected->tt_argcount != -1
2628 && (actual->tt_argcount < expected->tt_min_argcount
2629 || actual->tt_argcount > expected->tt_argcount))
2630 ret = FAIL;
2631 }
2632 if (ret == FAIL && give_msg)
2633 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002634 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002635 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002636}
2637
2638/*
2639 * Check that
2640 * - "actual" is "expected" type or
2641 * - "actual" is a type that can be "expected" type: add a runtime check; or
2642 * - return FAIL.
2643 */
2644 static int
2645need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2646{
Bram Moolenaar89228602020-04-05 22:14:54 +02002647 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002648 return OK;
Bram Moolenaar939b5db2020-04-28 22:49:08 +02002649 if (actual->tt_type != VAR_ANY
2650 && actual->tt_type != VAR_UNKNOWN
2651 && !(actual->tt_type == VAR_FUNC
2652 && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002653 {
2654 type_mismatch(expected, actual);
2655 return FAIL;
2656 }
2657 generate_TYPECHECK(cctx, expected, offset);
2658 return OK;
2659}
2660
2661/*
2662 * parse a list: [expr, expr]
2663 * "*arg" points to the '['.
2664 */
2665 static int
2666compile_list(char_u **arg, cctx_T *cctx)
2667{
2668 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002669 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002670 int count = 0;
2671
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002672 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002673 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002674 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002675 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002676 p = next_line_from_context(cctx);
2677 if (p == NULL)
2678 {
2679 semsg(_(e_list_end), *arg);
2680 return FAIL;
2681 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002682 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002683 p = skipwhite(p);
2684 }
2685 if (*p == ']')
2686 {
2687 ++p;
2688 // Allow for following comment, after at least one space.
2689 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2690 p += STRLEN(p);
2691 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002692 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002693 if (compile_expr1(&p, cctx) == FAIL)
2694 break;
2695 ++count;
2696 if (*p == ',')
2697 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002698 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002699 p = skipwhite(p);
2700 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002701 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002702
2703 generate_NEWLIST(cctx, count);
2704 return OK;
2705}
2706
2707/*
2708 * parse a lambda: {arg, arg -> expr}
2709 * "*arg" points to the '{'.
2710 */
2711 static int
2712compile_lambda(char_u **arg, cctx_T *cctx)
2713{
2714 garray_T *instr = &cctx->ctx_instr;
2715 typval_T rettv;
2716 ufunc_T *ufunc;
2717
2718 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002719 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002720 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002721
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002722 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002723 ++ufunc->uf_refcount;
2724 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002725 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002726
2727 // The function will have one line: "return {expr}".
2728 // Compile it into instructions.
2729 compile_def_function(ufunc, TRUE);
2730
2731 if (ufunc->uf_dfunc_idx >= 0)
2732 {
2733 if (ga_grow(instr, 1) == FAIL)
2734 return FAIL;
2735 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2736 return OK;
2737 }
2738 return FAIL;
2739}
2740
2741/*
2742 * Compile a lamda call: expr->{lambda}(args)
2743 * "arg" points to the "{".
2744 */
2745 static int
2746compile_lambda_call(char_u **arg, cctx_T *cctx)
2747{
2748 ufunc_T *ufunc;
2749 typval_T rettv;
2750 int argcount = 1;
2751 int ret = FAIL;
2752
2753 // Get the funcref in "rettv".
2754 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2755 return FAIL;
2756
2757 if (**arg != '(')
2758 {
2759 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002760 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002761 else
2762 semsg(_(e_missing_paren), "lambda");
2763 clear_tv(&rettv);
2764 return FAIL;
2765 }
2766
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002767 ufunc = rettv.vval.v_partial->pt_func;
2768 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002769 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002770 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002771
2772 // The function will have one line: "return {expr}".
2773 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002774 compile_def_function(ufunc, TRUE);
2775
2776 // compile the arguments
2777 *arg = skipwhite(*arg + 1);
2778 if (compile_arguments(arg, cctx, &argcount) == OK)
2779 // call the compiled function
2780 ret = generate_CALL(cctx, ufunc, argcount);
2781
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002782 return ret;
2783}
2784
2785/*
2786 * parse a dict: {'key': val} or #{key: val}
2787 * "*arg" points to the '{'.
2788 */
2789 static int
2790compile_dict(char_u **arg, cctx_T *cctx, int literal)
2791{
2792 garray_T *instr = &cctx->ctx_instr;
2793 int count = 0;
2794 dict_T *d = dict_alloc();
2795 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002796 char_u *whitep = *arg;
2797 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002798
2799 if (d == NULL)
2800 return FAIL;
2801 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002802 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002803 {
2804 char_u *key = NULL;
2805
Bram Moolenaar2c330432020-04-13 14:41:35 +02002806 while (**arg == NUL || (literal && **arg == '"')
2807 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002808 {
2809 *arg = next_line_from_context(cctx);
2810 if (*arg == NULL)
2811 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002812 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002813 *arg = skipwhite(*arg);
2814 }
2815
2816 if (**arg == '}')
2817 break;
2818
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002819 if (literal)
2820 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002821 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002822
Bram Moolenaar2c330432020-04-13 14:41:35 +02002823 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002824 {
2825 semsg(_("E1014: Invalid key: %s"), *arg);
2826 return FAIL;
2827 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002828 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002829 if (generate_PUSHS(cctx, key) == FAIL)
2830 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002831 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002832 }
2833 else
2834 {
2835 isn_T *isn;
2836
2837 if (compile_expr1(arg, cctx) == FAIL)
2838 return FAIL;
2839 // TODO: check type is string
2840 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2841 if (isn->isn_type == ISN_PUSHS)
2842 key = isn->isn_arg.string;
2843 }
2844
2845 // Check for duplicate keys, if using string keys.
2846 if (key != NULL)
2847 {
2848 item = dict_find(d, key, -1);
2849 if (item != NULL)
2850 {
2851 semsg(_(e_duplicate_key), key);
2852 goto failret;
2853 }
2854 item = dictitem_alloc(key);
2855 if (item != NULL)
2856 {
2857 item->di_tv.v_type = VAR_UNKNOWN;
2858 item->di_tv.v_lock = 0;
2859 if (dict_add(d, item) == FAIL)
2860 dictitem_free(item);
2861 }
2862 }
2863
2864 *arg = skipwhite(*arg);
2865 if (**arg != ':')
2866 {
2867 semsg(_(e_missing_dict_colon), *arg);
2868 return FAIL;
2869 }
2870
Bram Moolenaar2c330432020-04-13 14:41:35 +02002871 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002872 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002873 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002874 {
2875 *arg = next_line_from_context(cctx);
2876 if (*arg == NULL)
2877 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002878 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002879 *arg = skipwhite(*arg);
2880 }
2881
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002882 if (compile_expr1(arg, cctx) == FAIL)
2883 return FAIL;
2884 ++count;
2885
Bram Moolenaar2c330432020-04-13 14:41:35 +02002886 whitep = *arg;
2887 p = skipwhite(*arg);
2888 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002889 {
2890 *arg = next_line_from_context(cctx);
2891 if (*arg == NULL)
2892 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002893 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002894 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002895 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002896 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002897 if (**arg == '}')
2898 break;
2899 if (**arg != ',')
2900 {
2901 semsg(_(e_missing_dict_comma), *arg);
2902 goto failret;
2903 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002904 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002905 *arg = skipwhite(*arg + 1);
2906 }
2907
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002908 *arg = *arg + 1;
2909
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002910 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002911 p = skipwhite(*arg);
2912 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002913 *arg += STRLEN(*arg);
2914
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002915 dict_unref(d);
2916 return generate_NEWDICT(cctx, count);
2917
2918failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002919 if (*arg == NULL)
2920 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002921 dict_unref(d);
2922 return FAIL;
2923}
2924
2925/*
2926 * Compile "&option".
2927 */
2928 static int
2929compile_get_option(char_u **arg, cctx_T *cctx)
2930{
2931 typval_T rettv;
2932 char_u *start = *arg;
2933 int ret;
2934
2935 // parse the option and get the current value to get the type.
2936 rettv.v_type = VAR_UNKNOWN;
2937 ret = get_option_tv(arg, &rettv, TRUE);
2938 if (ret == OK)
2939 {
2940 // include the '&' in the name, get_option_tv() expects it.
2941 char_u *name = vim_strnsave(start, *arg - start);
2942 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2943
2944 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2945 vim_free(name);
2946 }
2947 clear_tv(&rettv);
2948
2949 return ret;
2950}
2951
2952/*
2953 * Compile "$VAR".
2954 */
2955 static int
2956compile_get_env(char_u **arg, cctx_T *cctx)
2957{
2958 char_u *start = *arg;
2959 int len;
2960 int ret;
2961 char_u *name;
2962
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002963 ++*arg;
2964 len = get_env_len(arg);
2965 if (len == 0)
2966 {
2967 semsg(_(e_syntax_at), start - 1);
2968 return FAIL;
2969 }
2970
2971 // include the '$' in the name, get_env_tv() expects it.
2972 name = vim_strnsave(start, len + 1);
2973 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2974 vim_free(name);
2975 return ret;
2976}
2977
2978/*
2979 * Compile "@r".
2980 */
2981 static int
2982compile_get_register(char_u **arg, cctx_T *cctx)
2983{
2984 int ret;
2985
2986 ++*arg;
2987 if (**arg == NUL)
2988 {
2989 semsg(_(e_syntax_at), *arg - 1);
2990 return FAIL;
2991 }
2992 if (!valid_yank_reg(**arg, TRUE))
2993 {
2994 emsg_invreg(**arg);
2995 return FAIL;
2996 }
2997 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2998 ++*arg;
2999 return ret;
3000}
3001
3002/*
3003 * Apply leading '!', '-' and '+' to constant "rettv".
3004 */
3005 static int
3006apply_leader(typval_T *rettv, char_u *start, char_u *end)
3007{
3008 char_u *p = end;
3009
3010 // this works from end to start
3011 while (p > start)
3012 {
3013 --p;
3014 if (*p == '-' || *p == '+')
3015 {
3016 // only '-' has an effect, for '+' we only check the type
3017#ifdef FEAT_FLOAT
3018 if (rettv->v_type == VAR_FLOAT)
3019 {
3020 if (*p == '-')
3021 rettv->vval.v_float = -rettv->vval.v_float;
3022 }
3023 else
3024#endif
3025 {
3026 varnumber_T val;
3027 int error = FALSE;
3028
3029 // tv_get_number_chk() accepts a string, but we don't want that
3030 // here
3031 if (check_not_string(rettv) == FAIL)
3032 return FAIL;
3033 val = tv_get_number_chk(rettv, &error);
3034 clear_tv(rettv);
3035 if (error)
3036 return FAIL;
3037 if (*p == '-')
3038 val = -val;
3039 rettv->v_type = VAR_NUMBER;
3040 rettv->vval.v_number = val;
3041 }
3042 }
3043 else
3044 {
3045 int v = tv2bool(rettv);
3046
3047 // '!' is permissive in the type.
3048 clear_tv(rettv);
3049 rettv->v_type = VAR_BOOL;
3050 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3051 }
3052 }
3053 return OK;
3054}
3055
3056/*
3057 * Recognize v: variables that are constants and set "rettv".
3058 */
3059 static void
3060get_vim_constant(char_u **arg, typval_T *rettv)
3061{
3062 if (STRNCMP(*arg, "v:true", 6) == 0)
3063 {
3064 rettv->v_type = VAR_BOOL;
3065 rettv->vval.v_number = VVAL_TRUE;
3066 *arg += 6;
3067 }
3068 else if (STRNCMP(*arg, "v:false", 7) == 0)
3069 {
3070 rettv->v_type = VAR_BOOL;
3071 rettv->vval.v_number = VVAL_FALSE;
3072 *arg += 7;
3073 }
3074 else if (STRNCMP(*arg, "v:null", 6) == 0)
3075 {
3076 rettv->v_type = VAR_SPECIAL;
3077 rettv->vval.v_number = VVAL_NULL;
3078 *arg += 6;
3079 }
3080 else if (STRNCMP(*arg, "v:none", 6) == 0)
3081 {
3082 rettv->v_type = VAR_SPECIAL;
3083 rettv->vval.v_number = VVAL_NONE;
3084 *arg += 6;
3085 }
3086}
3087
3088/*
3089 * Compile code to apply '-', '+' and '!'.
3090 */
3091 static int
3092compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3093{
3094 char_u *p = end;
3095
3096 // this works from end to start
3097 while (p > start)
3098 {
3099 --p;
3100 if (*p == '-' || *p == '+')
3101 {
3102 int negate = *p == '-';
3103 isn_T *isn;
3104
3105 // TODO: check type
3106 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3107 {
3108 --p;
3109 if (*p == '-')
3110 negate = !negate;
3111 }
3112 // only '-' has an effect, for '+' we only check the type
3113 if (negate)
3114 isn = generate_instr(cctx, ISN_NEGATENR);
3115 else
3116 isn = generate_instr(cctx, ISN_CHECKNR);
3117 if (isn == NULL)
3118 return FAIL;
3119 }
3120 else
3121 {
3122 int invert = TRUE;
3123
3124 while (p > start && p[-1] == '!')
3125 {
3126 --p;
3127 invert = !invert;
3128 }
3129 if (generate_2BOOL(cctx, invert) == FAIL)
3130 return FAIL;
3131 }
3132 }
3133 return OK;
3134}
3135
3136/*
3137 * Compile whatever comes after "name" or "name()".
3138 */
3139 static int
3140compile_subscript(
3141 char_u **arg,
3142 cctx_T *cctx,
3143 char_u **start_leader,
3144 char_u *end_leader)
3145{
3146 for (;;)
3147 {
3148 if (**arg == '(')
3149 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003150 garray_T *stack = &cctx->ctx_type_stack;
3151 type_T *type;
3152 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003153
3154 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003155 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3156
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003157 *arg = skipwhite(*arg + 1);
3158 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3159 return FAIL;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003160 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003161 return FAIL;
3162 }
3163 else if (**arg == '-' && (*arg)[1] == '>')
3164 {
3165 char_u *p;
3166
3167 // something->method()
3168 // Apply the '!', '-' and '+' first:
3169 // -1.0->func() works like (-1.0)->func()
3170 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3171 return FAIL;
3172 *start_leader = end_leader; // don't apply again later
3173
3174 *arg = skipwhite(*arg + 2);
3175 if (**arg == '{')
3176 {
3177 // lambda call: list->{lambda}
3178 if (compile_lambda_call(arg, cctx) == FAIL)
3179 return FAIL;
3180 }
3181 else
3182 {
3183 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003184 p = *arg;
3185 if (ASCII_ISALPHA(*p) && p[1] == ':')
3186 p += 2;
3187 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003188 ;
3189 if (*p != '(')
3190 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003191 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003192 return FAIL;
3193 }
3194 // TODO: base value may not be the first argument
3195 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3196 return FAIL;
3197 }
3198 }
3199 else if (**arg == '[')
3200 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003201 garray_T *stack;
3202 type_T **typep;
3203
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003204 // list index: list[123]
3205 // TODO: more arguments
3206 // TODO: dict member dict['name']
3207 *arg = skipwhite(*arg + 1);
3208 if (compile_expr1(arg, cctx) == FAIL)
3209 return FAIL;
3210
3211 if (**arg != ']')
3212 {
3213 emsg(_(e_missbrac));
3214 return FAIL;
3215 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003216 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003217
3218 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3219 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003220 stack = &cctx->ctx_type_stack;
3221 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3222 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3223 {
3224 emsg(_(e_listreq));
3225 return FAIL;
3226 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003227 if ((*typep)->tt_type == VAR_LIST)
3228 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003229 }
3230 else if (**arg == '.' && (*arg)[1] != '.')
3231 {
3232 char_u *p;
3233
3234 ++*arg;
3235 p = *arg;
3236 // dictionary member: dict.name
3237 if (eval_isnamec1(*p))
3238 while (eval_isnamec(*p))
3239 MB_PTR_ADV(p);
3240 if (p == *arg)
3241 {
3242 semsg(_(e_syntax_at), *arg);
3243 return FAIL;
3244 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003245 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3246 return FAIL;
3247 *arg = p;
3248 }
3249 else
3250 break;
3251 }
3252
3253 // TODO - see handle_subscript():
3254 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3255 // Don't do this when "Func" is already a partial that was bound
3256 // explicitly (pt_auto is FALSE).
3257
3258 return OK;
3259}
3260
3261/*
3262 * Compile an expression at "*p" and add instructions to "instr".
3263 * "p" is advanced until after the expression, skipping white space.
3264 *
3265 * This is the equivalent of eval1(), eval2(), etc.
3266 */
3267
3268/*
3269 * number number constant
3270 * 0zFFFFFFFF Blob constant
3271 * "string" string constant
3272 * 'string' literal string constant
3273 * &option-name option value
3274 * @r register contents
3275 * identifier variable value
3276 * function() function call
3277 * $VAR environment variable
3278 * (expression) nested expression
3279 * [expr, expr] List
3280 * {key: val, key: val} Dictionary
3281 * #{key: val, key: val} Dictionary with literal keys
3282 *
3283 * Also handle:
3284 * ! in front logical NOT
3285 * - in front unary minus
3286 * + in front unary plus (ignored)
3287 * trailing (arg) funcref/partial call
3288 * trailing [] subscript in String or List
3289 * trailing .name entry in Dictionary
3290 * trailing ->name() method call
3291 */
3292 static int
3293compile_expr7(char_u **arg, cctx_T *cctx)
3294{
3295 typval_T rettv;
3296 char_u *start_leader, *end_leader;
3297 int ret = OK;
3298
3299 /*
3300 * Skip '!', '-' and '+' characters. They are handled later.
3301 */
3302 start_leader = *arg;
3303 while (**arg == '!' || **arg == '-' || **arg == '+')
3304 *arg = skipwhite(*arg + 1);
3305 end_leader = *arg;
3306
3307 rettv.v_type = VAR_UNKNOWN;
3308 switch (**arg)
3309 {
3310 /*
3311 * Number constant.
3312 */
3313 case '0': // also for blob starting with 0z
3314 case '1':
3315 case '2':
3316 case '3':
3317 case '4':
3318 case '5':
3319 case '6':
3320 case '7':
3321 case '8':
3322 case '9':
3323 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3324 return FAIL;
3325 break;
3326
3327 /*
3328 * String constant: "string".
3329 */
3330 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3331 return FAIL;
3332 break;
3333
3334 /*
3335 * Literal string constant: 'str''ing'.
3336 */
3337 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3338 return FAIL;
3339 break;
3340
3341 /*
3342 * Constant Vim variable.
3343 */
3344 case 'v': get_vim_constant(arg, &rettv);
3345 ret = NOTDONE;
3346 break;
3347
3348 /*
3349 * List: [expr, expr]
3350 */
3351 case '[': ret = compile_list(arg, cctx);
3352 break;
3353
3354 /*
3355 * Dictionary: #{key: val, key: val}
3356 */
3357 case '#': if ((*arg)[1] == '{')
3358 {
3359 ++*arg;
3360 ret = compile_dict(arg, cctx, TRUE);
3361 }
3362 else
3363 ret = NOTDONE;
3364 break;
3365
3366 /*
3367 * Lambda: {arg, arg -> expr}
3368 * Dictionary: {'key': val, 'key': val}
3369 */
3370 case '{': {
3371 char_u *start = skipwhite(*arg + 1);
3372
3373 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003374 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003375 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003376 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003377 if (ret != FAIL && *start == '>')
3378 ret = compile_lambda(arg, cctx);
3379 else
3380 ret = compile_dict(arg, cctx, FALSE);
3381 }
3382 break;
3383
3384 /*
3385 * Option value: &name
3386 */
3387 case '&': ret = compile_get_option(arg, cctx);
3388 break;
3389
3390 /*
3391 * Environment variable: $VAR.
3392 */
3393 case '$': ret = compile_get_env(arg, cctx);
3394 break;
3395
3396 /*
3397 * Register contents: @r.
3398 */
3399 case '@': ret = compile_get_register(arg, cctx);
3400 break;
3401 /*
3402 * nested expression: (expression).
3403 */
3404 case '(': *arg = skipwhite(*arg + 1);
3405 ret = compile_expr1(arg, cctx); // recursive!
3406 *arg = skipwhite(*arg);
3407 if (**arg == ')')
3408 ++*arg;
3409 else if (ret == OK)
3410 {
3411 emsg(_(e_missing_close));
3412 ret = FAIL;
3413 }
3414 break;
3415
3416 default: ret = NOTDONE;
3417 break;
3418 }
3419 if (ret == FAIL)
3420 return FAIL;
3421
3422 if (rettv.v_type != VAR_UNKNOWN)
3423 {
3424 // apply the '!', '-' and '+' before the constant
3425 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3426 {
3427 clear_tv(&rettv);
3428 return FAIL;
3429 }
3430 start_leader = end_leader; // don't apply again below
3431
3432 // push constant
3433 switch (rettv.v_type)
3434 {
3435 case VAR_BOOL:
3436 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3437 break;
3438 case VAR_SPECIAL:
3439 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3440 break;
3441 case VAR_NUMBER:
3442 generate_PUSHNR(cctx, rettv.vval.v_number);
3443 break;
3444#ifdef FEAT_FLOAT
3445 case VAR_FLOAT:
3446 generate_PUSHF(cctx, rettv.vval.v_float);
3447 break;
3448#endif
3449 case VAR_BLOB:
3450 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3451 rettv.vval.v_blob = NULL;
3452 break;
3453 case VAR_STRING:
3454 generate_PUSHS(cctx, rettv.vval.v_string);
3455 rettv.vval.v_string = NULL;
3456 break;
3457 default:
3458 iemsg("constant type missing");
3459 return FAIL;
3460 }
3461 }
3462 else if (ret == NOTDONE)
3463 {
3464 char_u *p;
3465 int r;
3466
3467 if (!eval_isnamec1(**arg))
3468 {
3469 semsg(_("E1015: Name expected: %s"), *arg);
3470 return FAIL;
3471 }
3472
3473 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003474 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003475 if (*p == '(')
3476 r = compile_call(arg, p - *arg, cctx, 0);
3477 else
3478 r = compile_load(arg, p, cctx, TRUE);
3479 if (r == FAIL)
3480 return FAIL;
3481 }
3482
3483 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3484 return FAIL;
3485
3486 // Now deal with prefixed '-', '+' and '!', if not done already.
3487 return compile_leader(cctx, start_leader, end_leader);
3488}
3489
3490/*
3491 * * number multiplication
3492 * / number division
3493 * % number modulo
3494 */
3495 static int
3496compile_expr6(char_u **arg, cctx_T *cctx)
3497{
3498 char_u *op;
3499
3500 // get the first variable
3501 if (compile_expr7(arg, cctx) == FAIL)
3502 return FAIL;
3503
3504 /*
3505 * Repeat computing, until no "*", "/" or "%" is following.
3506 */
3507 for (;;)
3508 {
3509 op = skipwhite(*arg);
3510 if (*op != '*' && *op != '/' && *op != '%')
3511 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003512 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003513 {
3514 char_u buf[3];
3515
3516 vim_strncpy(buf, op, 1);
3517 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003518 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003519 }
3520 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003521 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003522 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003523
3524 // get the second variable
3525 if (compile_expr7(arg, cctx) == FAIL)
3526 return FAIL;
3527
3528 generate_two_op(cctx, op);
3529 }
3530
3531 return OK;
3532}
3533
3534/*
3535 * + number addition
3536 * - number subtraction
3537 * .. string concatenation
3538 */
3539 static int
3540compile_expr5(char_u **arg, cctx_T *cctx)
3541{
3542 char_u *op;
3543 int oplen;
3544
3545 // get the first variable
3546 if (compile_expr6(arg, cctx) == FAIL)
3547 return FAIL;
3548
3549 /*
3550 * Repeat computing, until no "+", "-" or ".." is following.
3551 */
3552 for (;;)
3553 {
3554 op = skipwhite(*arg);
3555 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3556 break;
3557 oplen = (*op == '.' ? 2 : 1);
3558
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003559 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003560 {
3561 char_u buf[3];
3562
3563 vim_strncpy(buf, op, oplen);
3564 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003565 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003566 }
3567
3568 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003569 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003570 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003571
3572 // get the second variable
3573 if (compile_expr6(arg, cctx) == FAIL)
3574 return FAIL;
3575
3576 if (*op == '.')
3577 {
3578 if (may_generate_2STRING(-2, cctx) == FAIL
3579 || may_generate_2STRING(-1, cctx) == FAIL)
3580 return FAIL;
3581 generate_instr_drop(cctx, ISN_CONCAT, 1);
3582 }
3583 else
3584 generate_two_op(cctx, op);
3585 }
3586
3587 return OK;
3588}
3589
Bram Moolenaar080457c2020-03-03 21:53:32 +01003590 static exptype_T
3591get_compare_type(char_u *p, int *len, int *type_is)
3592{
3593 exptype_T type = EXPR_UNKNOWN;
3594 int i;
3595
3596 switch (p[0])
3597 {
3598 case '=': if (p[1] == '=')
3599 type = EXPR_EQUAL;
3600 else if (p[1] == '~')
3601 type = EXPR_MATCH;
3602 break;
3603 case '!': if (p[1] == '=')
3604 type = EXPR_NEQUAL;
3605 else if (p[1] == '~')
3606 type = EXPR_NOMATCH;
3607 break;
3608 case '>': if (p[1] != '=')
3609 {
3610 type = EXPR_GREATER;
3611 *len = 1;
3612 }
3613 else
3614 type = EXPR_GEQUAL;
3615 break;
3616 case '<': if (p[1] != '=')
3617 {
3618 type = EXPR_SMALLER;
3619 *len = 1;
3620 }
3621 else
3622 type = EXPR_SEQUAL;
3623 break;
3624 case 'i': if (p[1] == 's')
3625 {
3626 // "is" and "isnot"; but not a prefix of a name
3627 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3628 *len = 5;
3629 i = p[*len];
3630 if (!isalnum(i) && i != '_')
3631 {
3632 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3633 *type_is = TRUE;
3634 }
3635 }
3636 break;
3637 }
3638 return type;
3639}
3640
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003641/*
3642 * expr5a == expr5b
3643 * expr5a =~ expr5b
3644 * expr5a != expr5b
3645 * expr5a !~ expr5b
3646 * expr5a > expr5b
3647 * expr5a >= expr5b
3648 * expr5a < expr5b
3649 * expr5a <= expr5b
3650 * expr5a is expr5b
3651 * expr5a isnot expr5b
3652 *
3653 * Produces instructions:
3654 * EVAL expr5a Push result of "expr5a"
3655 * EVAL expr5b Push result of "expr5b"
3656 * COMPARE one of the compare instructions
3657 */
3658 static int
3659compile_expr4(char_u **arg, cctx_T *cctx)
3660{
3661 exptype_T type = EXPR_UNKNOWN;
3662 char_u *p;
3663 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003664 int type_is = FALSE;
3665
3666 // get the first variable
3667 if (compile_expr5(arg, cctx) == FAIL)
3668 return FAIL;
3669
3670 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003671 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003672
3673 /*
3674 * If there is a comparative operator, use it.
3675 */
3676 if (type != EXPR_UNKNOWN)
3677 {
3678 int ic = FALSE; // Default: do not ignore case
3679
3680 if (type_is && (p[len] == '?' || p[len] == '#'))
3681 {
3682 semsg(_(e_invexpr2), *arg);
3683 return FAIL;
3684 }
3685 // extra question mark appended: ignore case
3686 if (p[len] == '?')
3687 {
3688 ic = TRUE;
3689 ++len;
3690 }
3691 // extra '#' appended: match case (ignored)
3692 else if (p[len] == '#')
3693 ++len;
3694 // nothing appended: match case
3695
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003696 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003697 {
3698 char_u buf[7];
3699
3700 vim_strncpy(buf, p, len);
3701 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003702 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003703 }
3704
3705 // get the second variable
3706 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003707 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003708 return FAIL;
3709
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003710 if (compile_expr5(arg, cctx) == FAIL)
3711 return FAIL;
3712
3713 generate_COMPARE(cctx, type, ic);
3714 }
3715
3716 return OK;
3717}
3718
3719/*
3720 * Compile || or &&.
3721 */
3722 static int
3723compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3724{
3725 char_u *p = skipwhite(*arg);
3726 int opchar = *op;
3727
3728 if (p[0] == opchar && p[1] == opchar)
3729 {
3730 garray_T *instr = &cctx->ctx_instr;
3731 garray_T end_ga;
3732
3733 /*
3734 * Repeat until there is no following "||" or "&&"
3735 */
3736 ga_init2(&end_ga, sizeof(int), 10);
3737 while (p[0] == opchar && p[1] == opchar)
3738 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003739 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3740 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003741 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003742 return FAIL;
3743 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003744
3745 if (ga_grow(&end_ga, 1) == FAIL)
3746 {
3747 ga_clear(&end_ga);
3748 return FAIL;
3749 }
3750 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3751 ++end_ga.ga_len;
3752 generate_JUMP(cctx, opchar == '|'
3753 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3754
3755 // eval the next expression
3756 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003757 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003758 return FAIL;
3759
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003760 if ((opchar == '|' ? compile_expr3(arg, cctx)
3761 : compile_expr4(arg, cctx)) == FAIL)
3762 {
3763 ga_clear(&end_ga);
3764 return FAIL;
3765 }
3766 p = skipwhite(*arg);
3767 }
3768
3769 // Fill in the end label in all jumps.
3770 while (end_ga.ga_len > 0)
3771 {
3772 isn_T *isn;
3773
3774 --end_ga.ga_len;
3775 isn = ((isn_T *)instr->ga_data)
3776 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3777 isn->isn_arg.jump.jump_where = instr->ga_len;
3778 }
3779 ga_clear(&end_ga);
3780 }
3781
3782 return OK;
3783}
3784
3785/*
3786 * expr4a && expr4a && expr4a logical AND
3787 *
3788 * Produces instructions:
3789 * EVAL expr4a Push result of "expr4a"
3790 * JUMP_AND_KEEP_IF_FALSE end
3791 * EVAL expr4b Push result of "expr4b"
3792 * JUMP_AND_KEEP_IF_FALSE end
3793 * EVAL expr4c Push result of "expr4c"
3794 * end:
3795 */
3796 static int
3797compile_expr3(char_u **arg, cctx_T *cctx)
3798{
3799 // get the first variable
3800 if (compile_expr4(arg, cctx) == FAIL)
3801 return FAIL;
3802
3803 // || and && work almost the same
3804 return compile_and_or(arg, cctx, "&&");
3805}
3806
3807/*
3808 * expr3a || expr3b || expr3c logical OR
3809 *
3810 * Produces instructions:
3811 * EVAL expr3a Push result of "expr3a"
3812 * JUMP_AND_KEEP_IF_TRUE end
3813 * EVAL expr3b Push result of "expr3b"
3814 * JUMP_AND_KEEP_IF_TRUE end
3815 * EVAL expr3c Push result of "expr3c"
3816 * end:
3817 */
3818 static int
3819compile_expr2(char_u **arg, cctx_T *cctx)
3820{
3821 // eval the first expression
3822 if (compile_expr3(arg, cctx) == FAIL)
3823 return FAIL;
3824
3825 // || and && work almost the same
3826 return compile_and_or(arg, cctx, "||");
3827}
3828
3829/*
3830 * Toplevel expression: expr2 ? expr1a : expr1b
3831 *
3832 * Produces instructions:
3833 * EVAL expr2 Push result of "expr"
3834 * JUMP_IF_FALSE alt jump if false
3835 * EVAL expr1a
3836 * JUMP_ALWAYS end
3837 * alt: EVAL expr1b
3838 * end:
3839 */
3840 static int
3841compile_expr1(char_u **arg, cctx_T *cctx)
3842{
3843 char_u *p;
3844
3845 // evaluate the first expression
3846 if (compile_expr2(arg, cctx) == FAIL)
3847 return FAIL;
3848
3849 p = skipwhite(*arg);
3850 if (*p == '?')
3851 {
3852 garray_T *instr = &cctx->ctx_instr;
3853 garray_T *stack = &cctx->ctx_type_stack;
3854 int alt_idx = instr->ga_len;
3855 int end_idx;
3856 isn_T *isn;
3857 type_T *type1;
3858 type_T *type2;
3859
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003860 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3861 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003862 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003863 return FAIL;
3864 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003865
3866 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3867
3868 // evaluate the second expression; any type is accepted
3869 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003870 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003871 return FAIL;
3872
Bram Moolenaara6d53682020-01-28 23:04:06 +01003873 if (compile_expr1(arg, cctx) == FAIL)
3874 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003875
3876 // remember the type and drop it
3877 --stack->ga_len;
3878 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3879
3880 end_idx = instr->ga_len;
3881 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3882
3883 // jump here from JUMP_IF_FALSE
3884 isn = ((isn_T *)instr->ga_data) + alt_idx;
3885 isn->isn_arg.jump.jump_where = instr->ga_len;
3886
3887 // Check for the ":".
3888 p = skipwhite(*arg);
3889 if (*p != ':')
3890 {
3891 emsg(_(e_missing_colon));
3892 return FAIL;
3893 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003894 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3895 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003896 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003897 return FAIL;
3898 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003899
3900 // evaluate the third expression
3901 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003902 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003903 return FAIL;
3904
Bram Moolenaara6d53682020-01-28 23:04:06 +01003905 if (compile_expr1(arg, cctx) == FAIL)
3906 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003907
3908 // If the types differ, the result has a more generic type.
3909 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003910 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003911
3912 // jump here from JUMP_ALWAYS
3913 isn = ((isn_T *)instr->ga_data) + end_idx;
3914 isn->isn_arg.jump.jump_where = instr->ga_len;
3915 }
3916 return OK;
3917}
3918
3919/*
3920 * compile "return [expr]"
3921 */
3922 static char_u *
3923compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3924{
3925 char_u *p = arg;
3926 garray_T *stack = &cctx->ctx_type_stack;
3927 type_T *stack_type;
3928
3929 if (*p != NUL && *p != '|' && *p != '\n')
3930 {
3931 // compile return argument into instructions
3932 if (compile_expr1(&p, cctx) == FAIL)
3933 return NULL;
3934
3935 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3936 if (set_return_type)
3937 cctx->ctx_ufunc->uf_ret_type = stack_type;
3938 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3939 == FAIL)
3940 return NULL;
3941 }
3942 else
3943 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003944 // "set_return_type" cannot be TRUE, only used for a lambda which
3945 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003946 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3947 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003948 {
3949 emsg(_("E1003: Missing return value"));
3950 return NULL;
3951 }
3952
3953 // No argument, return zero.
3954 generate_PUSHNR(cctx, 0);
3955 }
3956
3957 if (generate_instr(cctx, ISN_RETURN) == NULL)
3958 return NULL;
3959
3960 // "return val | endif" is possible
3961 return skipwhite(p);
3962}
3963
3964/*
3965 * Return the length of an assignment operator, or zero if there isn't one.
3966 */
3967 int
3968assignment_len(char_u *p, int *heredoc)
3969{
3970 if (*p == '=')
3971 {
3972 if (p[1] == '<' && p[2] == '<')
3973 {
3974 *heredoc = TRUE;
3975 return 3;
3976 }
3977 return 1;
3978 }
3979 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3980 return 2;
3981 if (STRNCMP(p, "..=", 3) == 0)
3982 return 3;
3983 return 0;
3984}
3985
3986// words that cannot be used as a variable
3987static char *reserved[] = {
3988 "true",
3989 "false",
3990 NULL
3991};
3992
3993/*
3994 * Get a line for "=<<".
3995 * Return a pointer to the line in allocated memory.
3996 * Return NULL for end-of-file or some error.
3997 */
3998 static char_u *
3999heredoc_getline(
4000 int c UNUSED,
4001 void *cookie,
4002 int indent UNUSED,
4003 int do_concat UNUSED)
4004{
4005 cctx_T *cctx = (cctx_T *)cookie;
4006
4007 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004008 {
4009 iemsg("Heredoc got to end");
4010 return NULL;
4011 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004012 ++cctx->ctx_lnum;
4013 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4014 [cctx->ctx_lnum]);
4015}
4016
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004017typedef enum {
4018 dest_local,
4019 dest_option,
4020 dest_env,
4021 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004022 dest_buffer,
4023 dest_window,
4024 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004025 dest_vimvar,
4026 dest_script,
4027 dest_reg,
4028} assign_dest_T;
4029
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004030/*
4031 * compile "let var [= expr]", "const var = expr" and "var = expr"
4032 * "arg" points to "var".
4033 */
4034 static char_u *
4035compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4036{
4037 char_u *p;
4038 char_u *ret = NULL;
4039 int var_count = 0;
4040 int semicolon = 0;
4041 size_t varlen;
4042 garray_T *instr = &cctx->ctx_instr;
4043 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004044 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004045 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004046 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004047 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004048 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004049 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004050 int oplen = 0;
4051 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004052 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004053 lvar_T *lvar;
4054 char_u *name;
4055 char_u *sp;
4056 int has_type = FALSE;
4057 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4058 int instr_count = -1;
4059
4060 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4061 if (p == NULL)
4062 return NULL;
4063 if (var_count > 0)
4064 {
4065 // TODO: let [var, var] = list
4066 emsg("Cannot handle a list yet");
4067 return NULL;
4068 }
4069
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004070 // "a: type" is declaring variable "a" with a type, not "a:".
4071 if (is_decl && p == arg + 2 && p[-1] == ':')
4072 --p;
4073
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004074 varlen = p - arg;
4075 name = vim_strnsave(arg, (int)varlen);
4076 if (name == NULL)
4077 return NULL;
4078
Bram Moolenaar080457c2020-03-03 21:53:32 +01004079 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004080 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004081 if (*arg == '&')
4082 {
4083 int cc;
4084 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004085
Bram Moolenaar080457c2020-03-03 21:53:32 +01004086 dest = dest_option;
4087 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004088 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004089 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004090 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004091 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004092 if (is_decl)
4093 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004094 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004095 goto theend;
4096 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004097 p = arg;
4098 p = find_option_end(&p, &opt_flags);
4099 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004100 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004101 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004102 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004103 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004104 }
4105 cc = *p;
4106 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004107 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004108 *p = cc;
4109 if (opt_type == -3)
4110 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004111 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004112 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004113 }
4114 if (opt_type == -2 || opt_type == 0)
4115 type = &t_string;
4116 else
4117 type = &t_number; // both number and boolean option
4118 }
4119 else if (*arg == '$')
4120 {
4121 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004122 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004123 if (is_decl)
4124 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004125 semsg(_("E1065: Cannot declare an environment variable: %s"),
4126 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004127 goto theend;
4128 }
4129 }
4130 else if (*arg == '@')
4131 {
4132 if (!valid_yank_reg(arg[1], TRUE))
4133 {
4134 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004135 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004136 }
4137 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004138 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004139 if (is_decl)
4140 {
4141 semsg(_("E1066: Cannot declare a register: %s"), name);
4142 goto theend;
4143 }
4144 }
4145 else if (STRNCMP(arg, "g:", 2) == 0)
4146 {
4147 dest = dest_global;
4148 if (is_decl)
4149 {
4150 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4151 goto theend;
4152 }
4153 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004154 else if (STRNCMP(arg, "b:", 2) == 0)
4155 {
4156 dest = dest_buffer;
4157 if (is_decl)
4158 {
4159 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4160 goto theend;
4161 }
4162 }
4163 else if (STRNCMP(arg, "w:", 2) == 0)
4164 {
4165 dest = dest_window;
4166 if (is_decl)
4167 {
4168 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4169 goto theend;
4170 }
4171 }
4172 else if (STRNCMP(arg, "t:", 2) == 0)
4173 {
4174 dest = dest_tab;
4175 if (is_decl)
4176 {
4177 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4178 goto theend;
4179 }
4180 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004181 else if (STRNCMP(arg, "v:", 2) == 0)
4182 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004183 typval_T *vtv;
4184 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004185
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004186 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004187 if (vimvaridx < 0)
4188 {
4189 semsg(_(e_var_notfound), arg);
4190 goto theend;
4191 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004192 // We use the current value of "sandbox" here, is that OK?
4193 if (var_check_ro(di_flags, name, FALSE))
4194 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004195 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004196 vtv = get_vim_var_tv(vimvaridx);
4197 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004198 if (is_decl)
4199 {
4200 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4201 goto theend;
4202 }
4203 }
4204 else
4205 {
4206 for (idx = 0; reserved[idx] != NULL; ++idx)
4207 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004208 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004209 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004210 goto theend;
4211 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004212
4213 idx = lookup_local(arg, varlen, cctx);
4214 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004215 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004216 if (is_decl)
4217 {
4218 semsg(_("E1017: Variable already declared: %s"), name);
4219 goto theend;
4220 }
4221 else
4222 {
4223 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4224 if (lvar->lv_const)
4225 {
4226 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4227 goto theend;
4228 }
4229 }
4230 }
4231 else if (STRNCMP(arg, "s:", 2) == 0
4232 || lookup_script(arg, varlen) == OK
4233 || find_imported(arg, varlen, cctx) != NULL)
4234 {
4235 dest = dest_script;
4236 if (is_decl)
4237 {
4238 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004239 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004240 goto theend;
4241 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004242 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004243 else if (name[1] == ':' && name[2] != NUL)
4244 {
4245 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4246 goto theend;
4247 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004248 }
4249 }
4250
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004251 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004252 {
4253 if (is_decl && *p == ':')
4254 {
4255 // parse optional type: "let var: type = expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004256 if (!VIM_ISWHITE(p[1]))
4257 {
4258 semsg(_(e_white_after), ":");
4259 goto theend;
4260 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004261 p = skipwhite(p + 1);
4262 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004263 has_type = TRUE;
4264 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004265 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004266 {
4267 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4268 type = lvar->lv_type;
4269 }
4270 }
4271
4272 sp = p;
4273 p = skipwhite(p);
4274 op = p;
4275 oplen = assignment_len(p, &heredoc);
4276 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4277 {
4278 char_u buf[4];
4279
4280 vim_strncpy(buf, op, oplen);
4281 semsg(_(e_white_both), buf);
4282 }
4283
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004284 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004285 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004286 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004287 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004288 goto theend;
4289 }
4290
Bram Moolenaar080457c2020-03-03 21:53:32 +01004291 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004292 {
4293 if (oplen > 1 && !heredoc)
4294 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004295 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004296 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4297 name);
4298 goto theend;
4299 }
4300
4301 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004302 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004303 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004304 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4305 if (idx < 0)
4306 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004307 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004308 }
4309
4310 if (heredoc)
4311 {
4312 list_T *l;
4313 listitem_T *li;
4314
4315 // [let] varname =<< [trim] {end}
4316 eap->getline = heredoc_getline;
4317 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004318 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004319
4320 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004321 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004322 {
4323 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4324 li->li_tv.vval.v_string = NULL;
4325 }
4326 generate_NEWLIST(cctx, l->lv_len);
4327 type = &t_list_string;
4328 list_free(l);
4329 p += STRLEN(p);
4330 }
4331 else if (oplen > 0)
4332 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004333 int r;
4334 type_T *stacktype;
4335 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004336
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004337 // for "+=", "*=", "..=" etc. first load the current value
4338 if (*op != '=')
4339 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004340 switch (dest)
4341 {
4342 case dest_option:
4343 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004344 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004345 break;
4346 case dest_global:
4347 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4348 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004349 case dest_buffer:
4350 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4351 break;
4352 case dest_window:
4353 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4354 break;
4355 case dest_tab:
4356 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4357 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004358 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004359 compile_load_scriptvar(cctx,
4360 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004361 break;
4362 case dest_env:
4363 // Include $ in the name here
4364 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4365 break;
4366 case dest_reg:
4367 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4368 break;
4369 case dest_vimvar:
4370 generate_LOADV(cctx, name + 2, TRUE);
4371 break;
4372 case dest_local:
4373 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4374 break;
4375 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004376 }
4377
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004378 // Compile the expression. Temporarily hide the new local variable
4379 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004380 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004381 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004382 instr_count = instr->ga_len;
4383 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004384 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004385 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004386 ++cctx->ctx_locals.ga_len;
4387 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004388 goto theend;
4389
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004390 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004391 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004392 stack = &cctx->ctx_type_stack;
4393 stacktype = stack->ga_len == 0 ? &t_void
4394 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4395 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004396 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004397 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4398 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004399 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004400 if (stacktype->tt_type == VAR_VOID)
4401 {
4402 emsg(_("E1031: Cannot use void value"));
4403 goto theend;
4404 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004405 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004406 {
4407 // An empty list or dict has a &t_void member, for a
4408 // variable that implies &t_any.
4409 if (stacktype == &t_list_empty)
4410 lvar->lv_type = &t_list_any;
4411 else if (stacktype == &t_dict_empty)
4412 lvar->lv_type = &t_dict_any;
4413 else
4414 lvar->lv_type = stacktype;
4415 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004416 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004417 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4418 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004419 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004420 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004421 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004422 }
4423 }
4424 else if (cmdidx == CMD_const)
4425 {
4426 emsg(_("E1021: const requires a value"));
4427 goto theend;
4428 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004429 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004430 {
4431 emsg(_("E1022: type or initialization required"));
4432 goto theend;
4433 }
4434 else
4435 {
4436 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004437 if (ga_grow(instr, 1) == FAIL)
4438 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004439 switch (type->tt_type)
4440 {
4441 case VAR_BOOL:
4442 generate_PUSHBOOL(cctx, VVAL_FALSE);
4443 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004444 case VAR_FLOAT:
4445#ifdef FEAT_FLOAT
4446 generate_PUSHF(cctx, 0.0);
4447#endif
4448 break;
4449 case VAR_STRING:
4450 generate_PUSHS(cctx, NULL);
4451 break;
4452 case VAR_BLOB:
4453 generate_PUSHBLOB(cctx, NULL);
4454 break;
4455 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004456 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004457 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004458 case VAR_LIST:
4459 generate_NEWLIST(cctx, 0);
4460 break;
4461 case VAR_DICT:
4462 generate_NEWDICT(cctx, 0);
4463 break;
4464 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004465 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004466 break;
4467 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004468 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004469 break;
4470 case VAR_NUMBER:
4471 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004472 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004473 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004474 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004475 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004476 generate_PUSHNR(cctx, 0);
4477 break;
4478 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004479 }
4480
4481 if (oplen > 0 && *op != '=')
4482 {
4483 type_T *expected = &t_number;
4484 garray_T *stack = &cctx->ctx_type_stack;
4485 type_T *stacktype;
4486
4487 // TODO: if type is known use float or any operation
4488
4489 if (*op == '.')
4490 expected = &t_string;
4491 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4492 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4493 goto theend;
4494
4495 if (*op == '.')
4496 generate_instr_drop(cctx, ISN_CONCAT, 1);
4497 else
4498 {
4499 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4500
4501 if (isn == NULL)
4502 goto theend;
4503 switch (*op)
4504 {
4505 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4506 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4507 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4508 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4509 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4510 }
4511 }
4512 }
4513
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004514 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004515 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004516 case dest_option:
4517 generate_STOREOPT(cctx, name + 1, opt_flags);
4518 break;
4519 case dest_global:
4520 // include g: with the name, easier to execute that way
4521 generate_STORE(cctx, ISN_STOREG, 0, name);
4522 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004523 case dest_buffer:
4524 // include b: with the name, easier to execute that way
4525 generate_STORE(cctx, ISN_STOREB, 0, name);
4526 break;
4527 case dest_window:
4528 // include w: with the name, easier to execute that way
4529 generate_STORE(cctx, ISN_STOREW, 0, name);
4530 break;
4531 case dest_tab:
4532 // include t: with the name, easier to execute that way
4533 generate_STORE(cctx, ISN_STORET, 0, name);
4534 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004535 case dest_env:
4536 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4537 break;
4538 case dest_reg:
4539 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4540 break;
4541 case dest_vimvar:
4542 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4543 break;
4544 case dest_script:
4545 {
4546 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4547 imported_T *import = NULL;
4548 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004549
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004550 if (name[1] != ':')
4551 {
4552 import = find_imported(name, 0, cctx);
4553 if (import != NULL)
4554 sid = import->imp_sid;
4555 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004556
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004557 idx = get_script_item_idx(sid, rawname, TRUE);
4558 // TODO: specific type
4559 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004560 {
4561 char_u *name_s = name;
4562
4563 // Include s: in the name for store_var()
4564 if (name[1] != ':')
4565 {
4566 int len = (int)STRLEN(name) + 3;
4567
4568 name_s = alloc(len);
4569 if (name_s == NULL)
4570 name_s = name;
4571 else
4572 vim_snprintf((char *)name_s, len, "s:%s", name);
4573 }
4574 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4575 if (name_s != name)
4576 vim_free(name_s);
4577 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004578 else
4579 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4580 sid, idx, &t_any);
4581 }
4582 break;
4583 case dest_local:
4584 {
4585 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004586
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004587 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4588 // into ISN_STORENR
4589 if (instr->ga_len == instr_count + 1
4590 && isn->isn_type == ISN_PUSHNR)
4591 {
4592 varnumber_T val = isn->isn_arg.number;
4593 garray_T *stack = &cctx->ctx_type_stack;
4594
4595 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004596 isn->isn_arg.storenr.stnr_idx = idx;
4597 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004598 if (stack->ga_len > 0)
4599 --stack->ga_len;
4600 }
4601 else
4602 generate_STORE(cctx, ISN_STORE, idx, NULL);
4603 }
4604 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004605 }
4606 ret = p;
4607
4608theend:
4609 vim_free(name);
4610 return ret;
4611}
4612
4613/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004614 * Check if "name" can be "unlet".
4615 */
4616 int
4617check_vim9_unlet(char_u *name)
4618{
4619 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
4620 {
4621 semsg(_("E1081: Cannot unlet %s"), name);
4622 return FAIL;
4623 }
4624 return OK;
4625}
4626
4627/*
4628 * Callback passed to ex_unletlock().
4629 */
4630 static int
4631compile_unlet(
4632 lval_T *lvp,
4633 char_u *name_end,
4634 exarg_T *eap,
4635 int deep UNUSED,
4636 void *coookie)
4637{
4638 cctx_T *cctx = coookie;
4639
4640 if (lvp->ll_tv == NULL)
4641 {
4642 char_u *p = lvp->ll_name;
4643 int cc = *name_end;
4644 int ret = OK;
4645
4646 // Normal name. Only supports g:, w:, t: and b: namespaces.
4647 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004648 if (*p == '$')
4649 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
4650 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004651 ret = FAIL;
4652 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004653 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004654
4655 *name_end = cc;
4656 return ret;
4657 }
4658
4659 // TODO: unlet {list}[idx]
4660 // TODO: unlet {dict}[key]
4661 emsg("Sorry, :unlet not fully implemented yet");
4662 return FAIL;
4663}
4664
4665/*
4666 * compile "unlet var", "lock var" and "unlock var"
4667 * "arg" points to "var".
4668 */
4669 static char_u *
4670compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
4671{
4672 char_u *p = arg;
4673
4674 if (eap->cmdidx != CMD_unlet)
4675 {
4676 emsg("Sorry, :lock and unlock not implemented yet");
4677 return NULL;
4678 }
4679
4680 if (*p == '!')
4681 {
4682 p = skipwhite(p + 1);
4683 eap->forceit = TRUE;
4684 }
4685
4686 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
4687 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
4688}
4689
4690/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004691 * Compile an :import command.
4692 */
4693 static char_u *
4694compile_import(char_u *arg, cctx_T *cctx)
4695{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004696 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004697}
4698
4699/*
4700 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4701 */
4702 static int
4703compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4704{
4705 garray_T *instr = &cctx->ctx_instr;
4706 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4707
4708 if (endlabel == NULL)
4709 return FAIL;
4710 endlabel->el_next = *el;
4711 *el = endlabel;
4712 endlabel->el_end_label = instr->ga_len;
4713
4714 generate_JUMP(cctx, when, 0);
4715 return OK;
4716}
4717
4718 static void
4719compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4720{
4721 garray_T *instr = &cctx->ctx_instr;
4722
4723 while (*el != NULL)
4724 {
4725 endlabel_T *cur = (*el);
4726 isn_T *isn;
4727
4728 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4729 isn->isn_arg.jump.jump_where = instr->ga_len;
4730 *el = cur->el_next;
4731 vim_free(cur);
4732 }
4733}
4734
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004735 static void
4736compile_free_jump_to_end(endlabel_T **el)
4737{
4738 while (*el != NULL)
4739 {
4740 endlabel_T *cur = (*el);
4741
4742 *el = cur->el_next;
4743 vim_free(cur);
4744 }
4745}
4746
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004747/*
4748 * Create a new scope and set up the generic items.
4749 */
4750 static scope_T *
4751new_scope(cctx_T *cctx, scopetype_T type)
4752{
4753 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4754
4755 if (scope == NULL)
4756 return NULL;
4757 scope->se_outer = cctx->ctx_scope;
4758 cctx->ctx_scope = scope;
4759 scope->se_type = type;
4760 scope->se_local_count = cctx->ctx_locals.ga_len;
4761 return scope;
4762}
4763
4764/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004765 * Free the current scope and go back to the outer scope.
4766 */
4767 static void
4768drop_scope(cctx_T *cctx)
4769{
4770 scope_T *scope = cctx->ctx_scope;
4771
4772 if (scope == NULL)
4773 {
4774 iemsg("calling drop_scope() without a scope");
4775 return;
4776 }
4777 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004778 switch (scope->se_type)
4779 {
4780 case IF_SCOPE:
4781 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4782 case FOR_SCOPE:
4783 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4784 case WHILE_SCOPE:
4785 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4786 case TRY_SCOPE:
4787 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4788 case NO_SCOPE:
4789 case BLOCK_SCOPE:
4790 break;
4791 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004792 vim_free(scope);
4793}
4794
4795/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004796 * Evaluate an expression that is a constant:
4797 * has(arg)
4798 *
4799 * Also handle:
4800 * ! in front logical NOT
4801 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004802 * Return FAIL if the expression is not a constant.
4803 */
4804 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004805evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004806{
4807 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004808 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004809 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004810
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004811 /*
4812 * Skip '!' characters. They are handled later.
4813 */
4814 start_leader = *arg;
4815 while (**arg == '!')
4816 *arg = skipwhite(*arg + 1);
4817 end_leader = *arg;
4818
4819 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004820 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004821 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004822 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4823 {
4824 tv->v_type = VAR_SPECIAL;
4825 tv->vval.v_number = VVAL_TRUE;
4826 *arg += 4;
4827 return OK;
4828 }
4829 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4830 {
4831 tv->v_type = VAR_SPECIAL;
4832 tv->vval.v_number = VVAL_FALSE;
4833 *arg += 5;
4834 return OK;
4835 }
4836
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004837 if (STRNCMP("has(", *arg, 4) == 0)
4838 {
4839 has_call = TRUE;
4840 *arg = skipwhite(*arg + 4);
4841 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004842
4843 if (**arg == '"')
4844 {
4845 if (get_string_tv(arg, tv, TRUE) == FAIL)
4846 return FAIL;
4847 }
4848 else if (**arg == '\'')
4849 {
4850 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4851 return FAIL;
4852 }
4853 else
4854 return FAIL;
4855
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004856 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004857 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004858 *arg = skipwhite(*arg);
4859 if (**arg != ')')
4860 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004861 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004862
4863 argvars[0] = *tv;
4864 argvars[1].v_type = VAR_UNKNOWN;
4865 tv->v_type = VAR_NUMBER;
4866 tv->vval.v_number = 0;
4867 f_has(argvars, tv);
4868 clear_tv(&argvars[0]);
4869
4870 while (start_leader < end_leader)
4871 {
4872 if (*start_leader == '!')
4873 tv->vval.v_number = !tv->vval.v_number;
4874 ++start_leader;
4875 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004876 }
4877
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004878 return OK;
4879}
4880
Bram Moolenaar080457c2020-03-03 21:53:32 +01004881 static int
4882evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4883{
4884 exptype_T type = EXPR_UNKNOWN;
4885 char_u *p;
4886 int len = 2;
4887 int type_is = FALSE;
4888
4889 // get the first variable
4890 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4891 return FAIL;
4892
4893 p = skipwhite(*arg);
4894 type = get_compare_type(p, &len, &type_is);
4895
4896 /*
4897 * If there is a comparative operator, use it.
4898 */
4899 if (type != EXPR_UNKNOWN)
4900 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004901 typval_T tv2;
4902 char_u *s1, *s2;
4903 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4904 int n;
4905
4906 // TODO: Only string == string is supported now
4907 if (tv->v_type != VAR_STRING)
4908 return FAIL;
4909 if (type != EXPR_EQUAL)
4910 return FAIL;
4911
4912 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004913 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004914 *arg = skipwhite(p + len);
4915 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4916 || tv2.v_type != VAR_STRING)
4917 {
4918 clear_tv(&tv2);
4919 return FAIL;
4920 }
4921 s1 = tv_get_string_buf(tv, buf1);
4922 s2 = tv_get_string_buf(&tv2, buf2);
4923 n = STRCMP(s1, s2);
4924 clear_tv(tv);
4925 clear_tv(&tv2);
4926 tv->v_type = VAR_BOOL;
4927 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004928 }
4929
4930 return OK;
4931}
4932
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004933static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4934
4935/*
4936 * Compile constant || or &&.
4937 */
4938 static int
4939evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4940{
4941 char_u *p = skipwhite(*arg);
4942 int opchar = *op;
4943
4944 if (p[0] == opchar && p[1] == opchar)
4945 {
4946 int val = tv2bool(tv);
4947
4948 /*
4949 * Repeat until there is no following "||" or "&&"
4950 */
4951 while (p[0] == opchar && p[1] == opchar)
4952 {
4953 typval_T tv2;
4954
4955 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4956 return FAIL;
4957
4958 // eval the next expression
4959 *arg = skipwhite(p + 2);
4960 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004961 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004962 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004963 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004964 {
4965 clear_tv(&tv2);
4966 return FAIL;
4967 }
4968 if ((opchar == '&') == val)
4969 {
4970 // false || tv2 or true && tv2: use tv2
4971 clear_tv(tv);
4972 *tv = tv2;
4973 val = tv2bool(tv);
4974 }
4975 else
4976 clear_tv(&tv2);
4977 p = skipwhite(*arg);
4978 }
4979 }
4980
4981 return OK;
4982}
4983
4984/*
4985 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4986 * Return FAIL if the expression is not a constant.
4987 */
4988 static int
4989evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4990{
4991 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004992 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004993 return FAIL;
4994
4995 // || and && work almost the same
4996 return evaluate_const_and_or(arg, cctx, "&&", tv);
4997}
4998
4999/*
5000 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
5001 * Return FAIL if the expression is not a constant.
5002 */
5003 static int
5004evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
5005{
5006 // evaluate the first expression
5007 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
5008 return FAIL;
5009
5010 // || and && work almost the same
5011 return evaluate_const_and_or(arg, cctx, "||", tv);
5012}
5013
5014/*
5015 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
5016 * E.g. for "has('feature')".
5017 * This does not produce error messages. "tv" should be cleared afterwards.
5018 * Return FAIL if the expression is not a constant.
5019 */
5020 static int
5021evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
5022{
5023 char_u *p;
5024
5025 // evaluate the first expression
5026 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
5027 return FAIL;
5028
5029 p = skipwhite(*arg);
5030 if (*p == '?')
5031 {
5032 int val = tv2bool(tv);
5033 typval_T tv2;
5034
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005035 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005036 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5037 return FAIL;
5038
5039 // evaluate the second expression; any type is accepted
5040 clear_tv(tv);
5041 *arg = skipwhite(p + 1);
5042 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
5043 return FAIL;
5044
5045 // Check for the ":".
5046 p = skipwhite(*arg);
5047 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5048 return FAIL;
5049
5050 // evaluate the third expression
5051 *arg = skipwhite(p + 1);
5052 tv2.v_type = VAR_UNKNOWN;
5053 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
5054 {
5055 clear_tv(&tv2);
5056 return FAIL;
5057 }
5058 if (val)
5059 {
5060 // use the expr after "?"
5061 clear_tv(&tv2);
5062 }
5063 else
5064 {
5065 // use the expr after ":"
5066 clear_tv(tv);
5067 *tv = tv2;
5068 }
5069 }
5070 return OK;
5071}
5072
5073/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005074 * compile "if expr"
5075 *
5076 * "if expr" Produces instructions:
5077 * EVAL expr Push result of "expr"
5078 * JUMP_IF_FALSE end
5079 * ... body ...
5080 * end:
5081 *
5082 * "if expr | else" Produces instructions:
5083 * EVAL expr Push result of "expr"
5084 * JUMP_IF_FALSE else
5085 * ... body ...
5086 * JUMP_ALWAYS end
5087 * else:
5088 * ... body ...
5089 * end:
5090 *
5091 * "if expr1 | elseif expr2 | else" Produces instructions:
5092 * EVAL expr Push result of "expr"
5093 * JUMP_IF_FALSE elseif
5094 * ... body ...
5095 * JUMP_ALWAYS end
5096 * elseif:
5097 * EVAL expr Push result of "expr"
5098 * JUMP_IF_FALSE else
5099 * ... body ...
5100 * JUMP_ALWAYS end
5101 * else:
5102 * ... body ...
5103 * end:
5104 */
5105 static char_u *
5106compile_if(char_u *arg, cctx_T *cctx)
5107{
5108 char_u *p = arg;
5109 garray_T *instr = &cctx->ctx_instr;
5110 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005111 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005112
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005113 // compile "expr"; if we know it evaluates to FALSE skip the block
5114 tv.v_type = VAR_UNKNOWN;
5115 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5116 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5117 else
5118 cctx->ctx_skip = MAYBE;
5119 clear_tv(&tv);
5120 if (cctx->ctx_skip == MAYBE)
5121 {
5122 p = arg;
5123 if (compile_expr1(&p, cctx) == FAIL)
5124 return NULL;
5125 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005126
5127 scope = new_scope(cctx, IF_SCOPE);
5128 if (scope == NULL)
5129 return NULL;
5130
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005131 if (cctx->ctx_skip == MAYBE)
5132 {
5133 // "where" is set when ":elseif", "else" or ":endif" is found
5134 scope->se_u.se_if.is_if_label = instr->ga_len;
5135 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5136 }
5137 else
5138 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005139
5140 return p;
5141}
5142
5143 static char_u *
5144compile_elseif(char_u *arg, cctx_T *cctx)
5145{
5146 char_u *p = arg;
5147 garray_T *instr = &cctx->ctx_instr;
5148 isn_T *isn;
5149 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005150 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005151
5152 if (scope == NULL || scope->se_type != IF_SCOPE)
5153 {
5154 emsg(_(e_elseif_without_if));
5155 return NULL;
5156 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005157 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005158
Bram Moolenaar158906c2020-02-06 20:39:45 +01005159 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005160 {
5161 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005162 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005163 return NULL;
5164 // previous "if" or "elseif" jumps here
5165 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5166 isn->isn_arg.jump.jump_where = instr->ga_len;
5167 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005168
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005169 // compile "expr"; if we know it evaluates to FALSE skip the block
5170 tv.v_type = VAR_UNKNOWN;
5171 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5172 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5173 else
5174 cctx->ctx_skip = MAYBE;
5175 clear_tv(&tv);
5176 if (cctx->ctx_skip == MAYBE)
5177 {
5178 p = arg;
5179 if (compile_expr1(&p, cctx) == FAIL)
5180 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005181
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005182 // "where" is set when ":elseif", "else" or ":endif" is found
5183 scope->se_u.se_if.is_if_label = instr->ga_len;
5184 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5185 }
5186 else
5187 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005188
5189 return p;
5190}
5191
5192 static char_u *
5193compile_else(char_u *arg, cctx_T *cctx)
5194{
5195 char_u *p = arg;
5196 garray_T *instr = &cctx->ctx_instr;
5197 isn_T *isn;
5198 scope_T *scope = cctx->ctx_scope;
5199
5200 if (scope == NULL || scope->se_type != IF_SCOPE)
5201 {
5202 emsg(_(e_else_without_if));
5203 return NULL;
5204 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005205 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005206
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005207 // jump from previous block to the end, unless the else block is empty
5208 if (cctx->ctx_skip == MAYBE)
5209 {
5210 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005211 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005212 return NULL;
5213 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005214
Bram Moolenaar158906c2020-02-06 20:39:45 +01005215 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005216 {
5217 if (scope->se_u.se_if.is_if_label >= 0)
5218 {
5219 // previous "if" or "elseif" jumps here
5220 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5221 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005222 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005223 }
5224 }
5225
5226 if (cctx->ctx_skip != MAYBE)
5227 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005228
5229 return p;
5230}
5231
5232 static char_u *
5233compile_endif(char_u *arg, cctx_T *cctx)
5234{
5235 scope_T *scope = cctx->ctx_scope;
5236 ifscope_T *ifscope;
5237 garray_T *instr = &cctx->ctx_instr;
5238 isn_T *isn;
5239
5240 if (scope == NULL || scope->se_type != IF_SCOPE)
5241 {
5242 emsg(_(e_endif_without_if));
5243 return NULL;
5244 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005245 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005246 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005247
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005248 if (scope->se_u.se_if.is_if_label >= 0)
5249 {
5250 // previous "if" or "elseif" jumps here
5251 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5252 isn->isn_arg.jump.jump_where = instr->ga_len;
5253 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005254 // Fill in the "end" label in jumps at the end of the blocks.
5255 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005256 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005257
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005258 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005259 return arg;
5260}
5261
5262/*
5263 * compile "for var in expr"
5264 *
5265 * Produces instructions:
5266 * PUSHNR -1
5267 * STORE loop-idx Set index to -1
5268 * EVAL expr Push result of "expr"
5269 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5270 * - if beyond end, jump to "end"
5271 * - otherwise get item from list and push it
5272 * STORE var Store item in "var"
5273 * ... body ...
5274 * JUMP top Jump back to repeat
5275 * end: DROP Drop the result of "expr"
5276 *
5277 */
5278 static char_u *
5279compile_for(char_u *arg, cctx_T *cctx)
5280{
5281 char_u *p;
5282 size_t varlen;
5283 garray_T *instr = &cctx->ctx_instr;
5284 garray_T *stack = &cctx->ctx_type_stack;
5285 scope_T *scope;
5286 int loop_idx; // index of loop iteration variable
5287 int var_idx; // index of "var"
5288 type_T *vartype;
5289
5290 // TODO: list of variables: "for [key, value] in dict"
5291 // parse "var"
5292 for (p = arg; eval_isnamec1(*p); ++p)
5293 ;
5294 varlen = p - arg;
5295 var_idx = lookup_local(arg, varlen, cctx);
5296 if (var_idx >= 0)
5297 {
5298 semsg(_("E1023: variable already defined: %s"), arg);
5299 return NULL;
5300 }
5301
5302 // consume "in"
5303 p = skipwhite(p);
5304 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5305 {
5306 emsg(_(e_missing_in));
5307 return NULL;
5308 }
5309 p = skipwhite(p + 2);
5310
5311
5312 scope = new_scope(cctx, FOR_SCOPE);
5313 if (scope == NULL)
5314 return NULL;
5315
5316 // Reserve a variable to store the loop iteration counter.
5317 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5318 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005319 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005320 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005321 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005322 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005323 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005324
5325 // Reserve a variable to store "var"
5326 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5327 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005328 {
5329 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005330 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005331 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005332
5333 generate_STORENR(cctx, loop_idx, -1);
5334
5335 // compile "expr", it remains on the stack until "endfor"
5336 arg = p;
5337 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005338 {
5339 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005340 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005341 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005342
5343 // now we know the type of "var"
5344 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5345 if (vartype->tt_type != VAR_LIST)
5346 {
5347 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005348 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005349 return NULL;
5350 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005351 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005352 {
5353 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
5354
5355 lvar->lv_type = vartype->tt_member;
5356 }
5357
5358 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005359 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005360
5361 generate_FOR(cctx, loop_idx);
5362 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
5363
5364 return arg;
5365}
5366
5367/*
5368 * compile "endfor"
5369 */
5370 static char_u *
5371compile_endfor(char_u *arg, cctx_T *cctx)
5372{
5373 garray_T *instr = &cctx->ctx_instr;
5374 scope_T *scope = cctx->ctx_scope;
5375 forscope_T *forscope;
5376 isn_T *isn;
5377
5378 if (scope == NULL || scope->se_type != FOR_SCOPE)
5379 {
5380 emsg(_(e_for));
5381 return NULL;
5382 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005383 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005384 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005385 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005386
5387 // At end of ":for" scope jump back to the FOR instruction.
5388 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5389
5390 // Fill in the "end" label in the FOR statement so it can jump here
5391 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5392 isn->isn_arg.forloop.for_end = instr->ga_len;
5393
5394 // Fill in the "end" label any BREAK statements
5395 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5396
5397 // Below the ":for" scope drop the "expr" list from the stack.
5398 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5399 return NULL;
5400
5401 vim_free(scope);
5402
5403 return arg;
5404}
5405
5406/*
5407 * compile "while expr"
5408 *
5409 * Produces instructions:
5410 * top: EVAL expr Push result of "expr"
5411 * JUMP_IF_FALSE end jump if false
5412 * ... body ...
5413 * JUMP top Jump back to repeat
5414 * end:
5415 *
5416 */
5417 static char_u *
5418compile_while(char_u *arg, cctx_T *cctx)
5419{
5420 char_u *p = arg;
5421 garray_T *instr = &cctx->ctx_instr;
5422 scope_T *scope;
5423
5424 scope = new_scope(cctx, WHILE_SCOPE);
5425 if (scope == NULL)
5426 return NULL;
5427
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005428 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005429
5430 // compile "expr"
5431 if (compile_expr1(&p, cctx) == FAIL)
5432 return NULL;
5433
5434 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005435 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005436 JUMP_IF_FALSE, cctx) == FAIL)
5437 return FAIL;
5438
5439 return p;
5440}
5441
5442/*
5443 * compile "endwhile"
5444 */
5445 static char_u *
5446compile_endwhile(char_u *arg, cctx_T *cctx)
5447{
5448 scope_T *scope = cctx->ctx_scope;
5449
5450 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5451 {
5452 emsg(_(e_while));
5453 return NULL;
5454 }
5455 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005456 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005457
5458 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005459 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005460
5461 // Fill in the "end" label in the WHILE statement so it can jump here.
5462 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005463 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005464
5465 vim_free(scope);
5466
5467 return arg;
5468}
5469
5470/*
5471 * compile "continue"
5472 */
5473 static char_u *
5474compile_continue(char_u *arg, cctx_T *cctx)
5475{
5476 scope_T *scope = cctx->ctx_scope;
5477
5478 for (;;)
5479 {
5480 if (scope == NULL)
5481 {
5482 emsg(_(e_continue));
5483 return NULL;
5484 }
5485 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5486 break;
5487 scope = scope->se_outer;
5488 }
5489
5490 // Jump back to the FOR or WHILE instruction.
5491 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005492 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5493 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005494 return arg;
5495}
5496
5497/*
5498 * compile "break"
5499 */
5500 static char_u *
5501compile_break(char_u *arg, cctx_T *cctx)
5502{
5503 scope_T *scope = cctx->ctx_scope;
5504 endlabel_T **el;
5505
5506 for (;;)
5507 {
5508 if (scope == NULL)
5509 {
5510 emsg(_(e_break));
5511 return NULL;
5512 }
5513 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5514 break;
5515 scope = scope->se_outer;
5516 }
5517
5518 // Jump to the end of the FOR or WHILE loop.
5519 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005520 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005521 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005522 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005523 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5524 return FAIL;
5525
5526 return arg;
5527}
5528
5529/*
5530 * compile "{" start of block
5531 */
5532 static char_u *
5533compile_block(char_u *arg, cctx_T *cctx)
5534{
5535 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5536 return NULL;
5537 return skipwhite(arg + 1);
5538}
5539
5540/*
5541 * compile end of block: drop one scope
5542 */
5543 static void
5544compile_endblock(cctx_T *cctx)
5545{
5546 scope_T *scope = cctx->ctx_scope;
5547
5548 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005549 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005550 vim_free(scope);
5551}
5552
5553/*
5554 * compile "try"
5555 * Creates a new scope for the try-endtry, pointing to the first catch and
5556 * finally.
5557 * Creates another scope for the "try" block itself.
5558 * TRY instruction sets up exception handling at runtime.
5559 *
5560 * "try"
5561 * TRY -> catch1, -> finally push trystack entry
5562 * ... try block
5563 * "throw {exception}"
5564 * EVAL {exception}
5565 * THROW create exception
5566 * ... try block
5567 * " catch {expr}"
5568 * JUMP -> finally
5569 * catch1: PUSH exeception
5570 * EVAL {expr}
5571 * MATCH
5572 * JUMP nomatch -> catch2
5573 * CATCH remove exception
5574 * ... catch block
5575 * " catch"
5576 * JUMP -> finally
5577 * catch2: CATCH remove exception
5578 * ... catch block
5579 * " finally"
5580 * finally:
5581 * ... finally block
5582 * " endtry"
5583 * ENDTRY pop trystack entry, may rethrow
5584 */
5585 static char_u *
5586compile_try(char_u *arg, cctx_T *cctx)
5587{
5588 garray_T *instr = &cctx->ctx_instr;
5589 scope_T *try_scope;
5590 scope_T *scope;
5591
5592 // scope that holds the jumps that go to catch/finally/endtry
5593 try_scope = new_scope(cctx, TRY_SCOPE);
5594 if (try_scope == NULL)
5595 return NULL;
5596
5597 // "catch" is set when the first ":catch" is found.
5598 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005599 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005600 if (generate_instr(cctx, ISN_TRY) == NULL)
5601 return NULL;
5602
5603 // scope for the try block itself
5604 scope = new_scope(cctx, BLOCK_SCOPE);
5605 if (scope == NULL)
5606 return NULL;
5607
5608 return arg;
5609}
5610
5611/*
5612 * compile "catch {expr}"
5613 */
5614 static char_u *
5615compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5616{
5617 scope_T *scope = cctx->ctx_scope;
5618 garray_T *instr = &cctx->ctx_instr;
5619 char_u *p;
5620 isn_T *isn;
5621
5622 // end block scope from :try or :catch
5623 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5624 compile_endblock(cctx);
5625 scope = cctx->ctx_scope;
5626
5627 // Error if not in a :try scope
5628 if (scope == NULL || scope->se_type != TRY_SCOPE)
5629 {
5630 emsg(_(e_catch));
5631 return NULL;
5632 }
5633
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005634 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005635 {
5636 emsg(_("E1033: catch unreachable after catch-all"));
5637 return NULL;
5638 }
5639
5640 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005641 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005642 JUMP_ALWAYS, cctx) == FAIL)
5643 return NULL;
5644
5645 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005646 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005647 if (isn->isn_arg.try.try_catch == 0)
5648 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005649 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005650 {
5651 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005652 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005653 isn->isn_arg.jump.jump_where = instr->ga_len;
5654 }
5655
5656 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005657 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005658 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005659 scope->se_u.se_try.ts_caught_all = TRUE;
5660 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005661 }
5662 else
5663 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005664 char_u *end;
5665 char_u *pat;
5666 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005667 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005668 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005669
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005670 // Push v:exception, push {expr} and MATCH
5671 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5672
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005673 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005674 if (*end != *p)
5675 {
5676 semsg(_("E1067: Separator mismatch: %s"), p);
5677 vim_free(tofree);
5678 return FAIL;
5679 }
5680 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005681 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005682 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005683 len = (int)(end - tofree);
5684 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005685 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005686 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005687 if (pat == NULL)
5688 return FAIL;
5689 if (generate_PUSHS(cctx, pat) == FAIL)
5690 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005691
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005692 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5693 return NULL;
5694
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005695 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005696 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5697 return NULL;
5698 }
5699
5700 if (generate_instr(cctx, ISN_CATCH) == NULL)
5701 return NULL;
5702
5703 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5704 return NULL;
5705 return p;
5706}
5707
5708 static char_u *
5709compile_finally(char_u *arg, cctx_T *cctx)
5710{
5711 scope_T *scope = cctx->ctx_scope;
5712 garray_T *instr = &cctx->ctx_instr;
5713 isn_T *isn;
5714
5715 // end block scope from :try or :catch
5716 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5717 compile_endblock(cctx);
5718 scope = cctx->ctx_scope;
5719
5720 // Error if not in a :try scope
5721 if (scope == NULL || scope->se_type != TRY_SCOPE)
5722 {
5723 emsg(_(e_finally));
5724 return NULL;
5725 }
5726
5727 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005728 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005729 if (isn->isn_arg.try.try_finally != 0)
5730 {
5731 emsg(_(e_finally_dup));
5732 return NULL;
5733 }
5734
5735 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005736 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005737
Bram Moolenaar585fea72020-04-02 22:33:21 +02005738 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005739 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005740 {
5741 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005742 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005743 isn->isn_arg.jump.jump_where = instr->ga_len;
5744 }
5745
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005746 // TODO: set index in ts_finally_label jumps
5747
5748 return arg;
5749}
5750
5751 static char_u *
5752compile_endtry(char_u *arg, cctx_T *cctx)
5753{
5754 scope_T *scope = cctx->ctx_scope;
5755 garray_T *instr = &cctx->ctx_instr;
5756 isn_T *isn;
5757
5758 // end block scope from :catch or :finally
5759 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5760 compile_endblock(cctx);
5761 scope = cctx->ctx_scope;
5762
5763 // Error if not in a :try scope
5764 if (scope == NULL || scope->se_type != TRY_SCOPE)
5765 {
5766 if (scope == NULL)
5767 emsg(_(e_no_endtry));
5768 else if (scope->se_type == WHILE_SCOPE)
5769 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005770 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005771 emsg(_(e_endfor));
5772 else
5773 emsg(_(e_endif));
5774 return NULL;
5775 }
5776
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005777 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005778 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5779 {
5780 emsg(_("E1032: missing :catch or :finally"));
5781 return NULL;
5782 }
5783
5784 // Fill in the "end" label in jumps at the end of the blocks, if not done
5785 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005786 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005787
5788 // End :catch or :finally scope: set value in ISN_TRY instruction
5789 if (isn->isn_arg.try.try_finally == 0)
5790 isn->isn_arg.try.try_finally = instr->ga_len;
5791 compile_endblock(cctx);
5792
5793 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5794 return NULL;
5795 return arg;
5796}
5797
5798/*
5799 * compile "throw {expr}"
5800 */
5801 static char_u *
5802compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5803{
5804 char_u *p = skipwhite(arg);
5805
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005806 if (compile_expr1(&p, cctx) == FAIL)
5807 return NULL;
5808 if (may_generate_2STRING(-1, cctx) == FAIL)
5809 return NULL;
5810 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5811 return NULL;
5812
5813 return p;
5814}
5815
5816/*
5817 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005818 * compile "echomsg expr"
5819 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01005820 * compile "execute expr"
5821 */
5822 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005823compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01005824{
5825 char_u *p = arg;
5826 int count = 0;
5827
5828 for (;;)
5829 {
5830 if (compile_expr1(&p, cctx) == FAIL)
5831 return NULL;
5832 ++count;
5833 p = skipwhite(p);
5834 if (ends_excmd(*p))
5835 break;
5836 }
5837
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005838 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
5839 generate_ECHO(cctx, cmdidx == CMD_echo, count);
5840 else if (cmdidx == CMD_execute)
5841 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
5842 else if (cmdidx == CMD_echomsg)
5843 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
5844 else
5845 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005846 return p;
5847}
5848
5849/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005850 * A command that is not compiled, execute with legacy code.
5851 */
5852 static char_u *
5853compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
5854{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005855 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005856 int has_expr = FALSE;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005857
5858 if (cctx->ctx_skip == TRUE)
5859 goto theend;
5860
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005861 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
5862 has_expr = (excmd_get_argt(eap->cmdidx) & (EX_XFILE | EX_EXPAND));
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005863 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
5864 {
5865 // expand filename in "syntax include [@group] filename"
5866 has_expr = TRUE;
5867 eap->arg = skipwhite(eap->arg + 7);
5868 if (*eap->arg == '@')
5869 eap->arg = skiptowhite(eap->arg);
5870 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005871
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005872 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005873 {
5874 int count = 0;
5875 char_u *start = skipwhite(line);
5876
5877 // :cmd xxx`=expr1`yyy`=expr2`zzz
5878 // PUSHS ":cmd xxx"
5879 // eval expr1
5880 // PUSHS "yyy"
5881 // eval expr2
5882 // PUSHS "zzz"
5883 // EXECCONCAT 5
5884 for (;;)
5885 {
5886 if (p > start)
5887 {
5888 generate_PUSHS(cctx, vim_strnsave(start, (int)(p - start)));
5889 ++count;
5890 }
5891 p += 2;
5892 if (compile_expr1(&p, cctx) == FAIL)
5893 return NULL;
5894 may_generate_2STRING(-1, cctx);
5895 ++count;
5896 p = skipwhite(p);
5897 if (*p != '`')
5898 {
5899 emsg(_("E1083: missing backtick"));
5900 return NULL;
5901 }
5902 start = p + 1;
5903
5904 p = (char_u *)strstr((char *)start, "`=");
5905 if (p == NULL)
5906 {
5907 if (*skipwhite(start) != NUL)
5908 {
5909 generate_PUSHS(cctx, vim_strsave(start));
5910 ++count;
5911 }
5912 break;
5913 }
5914 }
5915 generate_EXECCONCAT(cctx, count);
5916 }
5917 else
5918 generate_EXEC(cctx, line);
5919
5920theend:
5921 return (char_u *)"";
5922}
5923
5924/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005925 * After ex_function() has collected all the function lines: parse and compile
5926 * the lines into instructions.
5927 * Adds the function to "def_functions".
5928 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5929 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005930 * This can be used recursively through compile_lambda(), which may reallocate
5931 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005932 */
5933 void
5934compile_def_function(ufunc_T *ufunc, int set_return_type)
5935{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005936 char_u *line = NULL;
5937 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005938 char *errormsg = NULL; // error message
5939 int had_return = FALSE;
5940 cctx_T cctx;
5941 garray_T *instr;
5942 int called_emsg_before = called_emsg;
5943 int ret = FAIL;
5944 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005945 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005946
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005947 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005948 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005949
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005950 if (ufunc->uf_dfunc_idx >= 0)
5951 {
5952 // Redefining a function that was compiled before.
5953 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5954
5955 // Free old instructions.
5956 delete_def_function_contents(dfunc);
5957 }
5958 else
5959 {
5960 // Add the function to "def_functions".
5961 if (ga_grow(&def_functions, 1) == FAIL)
5962 return;
5963 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005964 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005965 dfunc->df_idx = def_functions.ga_len;
5966 ufunc->uf_dfunc_idx = dfunc->df_idx;
5967 dfunc->df_ufunc = ufunc;
5968 ++def_functions.ga_len;
5969 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005970 }
5971
Bram Moolenaara80faa82020-04-12 19:37:17 +02005972 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005973 cctx.ctx_ufunc = ufunc;
5974 cctx.ctx_lnum = -1;
5975 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5976 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5977 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5978 cctx.ctx_type_list = &ufunc->uf_type_list;
5979 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5980 instr = &cctx.ctx_instr;
5981
5982 // Most modern script version.
5983 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5984
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005985 if (ufunc->uf_def_args.ga_len > 0)
5986 {
5987 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005988 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005989 int i;
5990 char_u *arg;
5991 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5992
5993 // Produce instructions for the default values of optional arguments.
5994 // Store the instruction index in uf_def_arg_idx[] so that we know
5995 // where to start when the function is called, depending on the number
5996 // of arguments.
5997 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5998 if (ufunc->uf_def_arg_idx == NULL)
5999 goto erret;
6000 for (i = 0; i < count; ++i)
6001 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006002 garray_T *stack = &cctx.ctx_type_stack;
6003 type_T *val_type;
6004 int arg_idx = first_def_arg + i;
6005
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006006 ufunc->uf_def_arg_idx[i] = instr->ga_len;
6007 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006008 if (compile_expr1(&arg, &cctx) == FAIL)
6009 goto erret;
6010
6011 // If no type specified use the type of the default value.
6012 // Otherwise check that the default value type matches the
6013 // specified type.
6014 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6015 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
6016 ufunc->uf_arg_types[arg_idx] = val_type;
6017 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
6018 == FAIL)
6019 {
6020 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
6021 arg_idx + 1);
6022 goto erret;
6023 }
6024
6025 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006026 goto erret;
6027 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006028 ufunc->uf_def_arg_idx[count] = instr->ga_len;
6029 }
6030
6031 /*
6032 * Loop over all the lines of the function and generate instructions.
6033 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006034 for (;;)
6035 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006036 exarg_T ea;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006037 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006038
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006039 // Bail out on the first error to avoid a flood of errors and report
6040 // the right line number when inside try/catch.
6041 if (emsg_before != called_emsg)
6042 goto erret;
6043
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006044 if (line != NULL && *line == '|')
6045 // the line continues after a '|'
6046 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02006047 else if (line != NULL && *line != NUL
6048 && !(*line == '#' && (line == cctx.ctx_line_start
6049 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006050 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006051 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006052 goto erret;
6053 }
6054 else
6055 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006056 line = next_line_from_context(&cctx);
6057 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006058 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006059 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006060 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006061 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006062
6063 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006064 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006065 ea.cmdlinep = &line;
6066 ea.cmd = skipwhite(line);
6067
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006068 // Some things can be recognized by the first character.
6069 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006070 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006071 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006072 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006073 if (ea.cmd[1] != '{')
6074 {
6075 line = (char_u *)"";
6076 continue;
6077 }
6078 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006079
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006080 case '}':
6081 {
6082 // "}" ends a block scope
6083 scopetype_T stype = cctx.ctx_scope == NULL
6084 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006085
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006086 if (stype == BLOCK_SCOPE)
6087 {
6088 compile_endblock(&cctx);
6089 line = ea.cmd;
6090 }
6091 else
6092 {
6093 emsg(_("E1025: using } outside of a block scope"));
6094 goto erret;
6095 }
6096 if (line != NULL)
6097 line = skipwhite(ea.cmd + 1);
6098 continue;
6099 }
6100
6101 case '{':
6102 // "{" starts a block scope
6103 // "{'a': 1}->func() is something else
6104 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6105 {
6106 line = compile_block(ea.cmd, &cctx);
6107 continue;
6108 }
6109 break;
6110
6111 case ':':
6112 is_ex_command = TRUE;
6113 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006114 }
6115
6116 /*
6117 * COMMAND MODIFIERS
6118 */
6119 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6120 {
6121 if (errormsg != NULL)
6122 goto erret;
6123 // empty line or comment
6124 line = (char_u *)"";
6125 continue;
6126 }
6127
6128 // Skip ":call" to get to the function name.
6129 if (checkforcmd(&ea.cmd, "call", 3))
6130 ea.cmd = skipwhite(ea.cmd);
6131
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006132 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006133 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006134 // Assuming the command starts with a variable or function name,
6135 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6136 // val".
6137 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6138 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006139 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006140 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006141 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006142 int oplen;
6143 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006144
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006145 oplen = assignment_len(skipwhite(p), &heredoc);
6146 if (oplen > 0)
6147 {
6148 // Recognize an assignment if we recognize the variable
6149 // name:
6150 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006151 // "local = expr" where "local" is a local var.
6152 // "script = expr" where "script" is a script-local var.
6153 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006154 // "&opt = expr"
6155 // "$ENV = expr"
6156 // "@r = expr"
6157 if (*ea.cmd == '&'
6158 || *ea.cmd == '$'
6159 || *ea.cmd == '@'
6160 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
6161 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
6162 || lookup_script(ea.cmd, p - ea.cmd) == OK
6163 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6164 {
6165 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6166 if (line == NULL)
6167 goto erret;
6168 continue;
6169 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006170 }
6171 }
6172 }
6173
6174 /*
6175 * COMMAND after range
6176 */
6177 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006178 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
6179 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006180
6181 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6182 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006183 if (cctx.ctx_skip == TRUE)
6184 {
6185 line += STRLEN(line);
6186 continue;
6187 }
6188
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006189 // Expression or function call.
6190 if (ea.cmdidx == CMD_eval)
6191 {
6192 p = ea.cmd;
6193 if (compile_expr1(&p, &cctx) == FAIL)
6194 goto erret;
6195
6196 // drop the return value
6197 generate_instr_drop(&cctx, ISN_DROP, 1);
6198 line = p;
6199 continue;
6200 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006201 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006202 iemsg("Command from find_ex_command() not handled");
6203 goto erret;
6204 }
6205
6206 p = skipwhite(p);
6207
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006208 if (cctx.ctx_skip == TRUE
6209 && ea.cmdidx != CMD_elseif
6210 && ea.cmdidx != CMD_else
6211 && ea.cmdidx != CMD_endif)
6212 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006213 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006214 continue;
6215 }
6216
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006217 switch (ea.cmdidx)
6218 {
6219 case CMD_def:
6220 case CMD_function:
6221 // TODO: Nested function
6222 emsg("Nested function not implemented yet");
6223 goto erret;
6224
6225 case CMD_return:
6226 line = compile_return(p, set_return_type, &cctx);
6227 had_return = TRUE;
6228 break;
6229
6230 case CMD_let:
6231 case CMD_const:
6232 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6233 break;
6234
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006235 case CMD_unlet:
6236 case CMD_unlockvar:
6237 case CMD_lockvar:
6238 line = compile_unletlock(p, &ea, &cctx);
6239 break;
6240
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006241 case CMD_import:
6242 line = compile_import(p, &cctx);
6243 break;
6244
6245 case CMD_if:
6246 line = compile_if(p, &cctx);
6247 break;
6248 case CMD_elseif:
6249 line = compile_elseif(p, &cctx);
6250 break;
6251 case CMD_else:
6252 line = compile_else(p, &cctx);
6253 break;
6254 case CMD_endif:
6255 line = compile_endif(p, &cctx);
6256 break;
6257
6258 case CMD_while:
6259 line = compile_while(p, &cctx);
6260 break;
6261 case CMD_endwhile:
6262 line = compile_endwhile(p, &cctx);
6263 break;
6264
6265 case CMD_for:
6266 line = compile_for(p, &cctx);
6267 break;
6268 case CMD_endfor:
6269 line = compile_endfor(p, &cctx);
6270 break;
6271 case CMD_continue:
6272 line = compile_continue(p, &cctx);
6273 break;
6274 case CMD_break:
6275 line = compile_break(p, &cctx);
6276 break;
6277
6278 case CMD_try:
6279 line = compile_try(p, &cctx);
6280 break;
6281 case CMD_catch:
6282 line = compile_catch(p, &cctx);
6283 break;
6284 case CMD_finally:
6285 line = compile_finally(p, &cctx);
6286 break;
6287 case CMD_endtry:
6288 line = compile_endtry(p, &cctx);
6289 break;
6290 case CMD_throw:
6291 line = compile_throw(p, &cctx);
6292 break;
6293
6294 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006295 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006296 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006297 case CMD_echomsg:
6298 case CMD_echoerr:
6299 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006300 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006301
6302 default:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006303 // TODO: other commands with an expression argument
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006304 // Not recognized, execute with do_cmdline_cmd().
6305 ea.arg = p;
6306 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006307 break;
6308 }
6309 if (line == NULL)
6310 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006311 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006312
6313 if (cctx.ctx_type_stack.ga_len < 0)
6314 {
6315 iemsg("Type stack underflow");
6316 goto erret;
6317 }
6318 }
6319
6320 if (cctx.ctx_scope != NULL)
6321 {
6322 if (cctx.ctx_scope->se_type == IF_SCOPE)
6323 emsg(_(e_endif));
6324 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6325 emsg(_(e_endwhile));
6326 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6327 emsg(_(e_endfor));
6328 else
6329 emsg(_("E1026: Missing }"));
6330 goto erret;
6331 }
6332
6333 if (!had_return)
6334 {
6335 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6336 {
6337 emsg(_("E1027: Missing return statement"));
6338 goto erret;
6339 }
6340
6341 // Return zero if there is no return at the end.
6342 generate_PUSHNR(&cctx, 0);
6343 generate_instr(&cctx, ISN_RETURN);
6344 }
6345
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006346 {
6347 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6348 + ufunc->uf_dfunc_idx;
6349 dfunc->df_deleted = FALSE;
6350 dfunc->df_instr = instr->ga_data;
6351 dfunc->df_instr_count = instr->ga_len;
6352 dfunc->df_varcount = cctx.ctx_max_local;
6353 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006354
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006355 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006356 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006357 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006358
6359 // Create a type for the function, with the return type and any
6360 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006361 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6362 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006363 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006364 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006365 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6366 argcount, &ufunc->uf_type_list);
6367 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006368 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006369 argcount + varargs,
6370 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006371 {
6372 ret = FAIL;
6373 goto erret;
6374 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006375 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6376 ufunc->uf_func_type->tt_min_argcount =
6377 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006378 if (ufunc->uf_arg_types == NULL)
6379 {
6380 int i;
6381
6382 // lambda does not have argument types.
6383 for (i = 0; i < argcount; ++i)
6384 ufunc->uf_func_type->tt_args[i] = &t_any;
6385 }
6386 else
6387 mch_memmove(ufunc->uf_func_type->tt_args,
6388 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006389 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006390 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006391 ufunc->uf_func_type->tt_args[argcount] =
6392 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006393 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6394 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006395 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006396 else
6397 // No arguments, can use a predefined type.
6398 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6399 argcount, &ufunc->uf_type_list);
6400
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006401 }
6402
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006403 ret = OK;
6404
6405erret:
6406 if (ret == FAIL)
6407 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006408 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006409 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6410 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006411
6412 for (idx = 0; idx < instr->ga_len; ++idx)
6413 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006414 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006415
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006416 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006417 if (!dfunc->df_deleted)
6418 --def_functions.ga_len;
6419
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006420 while (cctx.ctx_scope != NULL)
6421 drop_scope(&cctx);
6422
Bram Moolenaar20431c92020-03-20 18:39:46 +01006423 // Don't execute this function body.
6424 ga_clear_strings(&ufunc->uf_lines);
6425
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006426 if (errormsg != NULL)
6427 emsg(errormsg);
6428 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006429 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006430 }
6431
6432 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006433 free_imported(&cctx);
6434 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006435 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006436}
6437
6438/*
6439 * Delete an instruction, free what it contains.
6440 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006441 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006442delete_instr(isn_T *isn)
6443{
6444 switch (isn->isn_type)
6445 {
6446 case ISN_EXEC:
6447 case ISN_LOADENV:
6448 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006449 case ISN_LOADB:
6450 case ISN_LOADW:
6451 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006452 case ISN_LOADOPT:
6453 case ISN_MEMBER:
6454 case ISN_PUSHEXC:
6455 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006456 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006457 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006458 case ISN_STOREB:
6459 case ISN_STOREW:
6460 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006461 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006462 vim_free(isn->isn_arg.string);
6463 break;
6464
6465 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006466 case ISN_STORES:
6467 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006468 break;
6469
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006470 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006471 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006472 vim_free(isn->isn_arg.unlet.ul_name);
6473 break;
6474
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006475 case ISN_STOREOPT:
6476 vim_free(isn->isn_arg.storeopt.so_name);
6477 break;
6478
6479 case ISN_PUSHBLOB: // push blob isn_arg.blob
6480 blob_unref(isn->isn_arg.blob);
6481 break;
6482
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006483 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006484#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006485 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006486#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006487 break;
6488
6489 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006490#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006491 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006492#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006493 break;
6494
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006495 case ISN_UCALL:
6496 vim_free(isn->isn_arg.ufunc.cuf_name);
6497 break;
6498
6499 case ISN_2BOOL:
6500 case ISN_2STRING:
6501 case ISN_ADDBLOB:
6502 case ISN_ADDLIST:
6503 case ISN_BCALL:
6504 case ISN_CATCH:
6505 case ISN_CHECKNR:
6506 case ISN_CHECKTYPE:
6507 case ISN_COMPAREANY:
6508 case ISN_COMPAREBLOB:
6509 case ISN_COMPAREBOOL:
6510 case ISN_COMPAREDICT:
6511 case ISN_COMPAREFLOAT:
6512 case ISN_COMPAREFUNC:
6513 case ISN_COMPARELIST:
6514 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006515 case ISN_COMPARESPECIAL:
6516 case ISN_COMPARESTRING:
6517 case ISN_CONCAT:
6518 case ISN_DCALL:
6519 case ISN_DROP:
6520 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006521 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006522 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006523 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006524 case ISN_EXECCONCAT:
6525 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006526 case ISN_FOR:
6527 case ISN_FUNCREF:
6528 case ISN_INDEX:
6529 case ISN_JUMP:
6530 case ISN_LOAD:
6531 case ISN_LOADSCRIPT:
6532 case ISN_LOADREG:
6533 case ISN_LOADV:
6534 case ISN_NEGATENR:
6535 case ISN_NEWDICT:
6536 case ISN_NEWLIST:
6537 case ISN_OPNR:
6538 case ISN_OPFLOAT:
6539 case ISN_OPANY:
6540 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006541 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006542 case ISN_PUSHF:
6543 case ISN_PUSHNR:
6544 case ISN_PUSHBOOL:
6545 case ISN_PUSHSPEC:
6546 case ISN_RETURN:
6547 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006548 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006549 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006550 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006551 case ISN_STORESCRIPT:
6552 case ISN_THROW:
6553 case ISN_TRY:
6554 // nothing allocated
6555 break;
6556 }
6557}
6558
6559/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006560 * Free all instructions for "dfunc".
6561 */
6562 static void
6563delete_def_function_contents(dfunc_T *dfunc)
6564{
6565 int idx;
6566
6567 ga_clear(&dfunc->df_def_args_isn);
6568
6569 if (dfunc->df_instr != NULL)
6570 {
6571 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6572 delete_instr(dfunc->df_instr + idx);
6573 VIM_CLEAR(dfunc->df_instr);
6574 }
6575
6576 dfunc->df_deleted = TRUE;
6577}
6578
6579/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006580 * When a user function is deleted, delete any associated def function.
6581 */
6582 void
6583delete_def_function(ufunc_T *ufunc)
6584{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006585 if (ufunc->uf_dfunc_idx >= 0)
6586 {
6587 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6588 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006589
Bram Moolenaar20431c92020-03-20 18:39:46 +01006590 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006591 }
6592}
6593
6594#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006595/*
6596 * Free all functions defined with ":def".
6597 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006598 void
6599free_def_functions(void)
6600{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006601 int idx;
6602
6603 for (idx = 0; idx < def_functions.ga_len; ++idx)
6604 {
6605 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6606
6607 delete_def_function_contents(dfunc);
6608 }
6609
6610 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006611}
6612#endif
6613
6614
6615#endif // FEAT_EVAL