blob: 64f7dd59b1ddc0eb7d18bf05977b390ae5960169 [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9compile.c: :def and dealing with instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#define DEFINE_VIM9_GLOBALS
24#include "vim9.h"
25
26/*
27 * Chain of jump instructions where the end label needs to be set.
28 */
29typedef struct endlabel_S endlabel_T;
30struct endlabel_S {
31 endlabel_T *el_next; // chain end_label locations
32 int el_end_label; // instruction idx where to set end
33};
34
35/*
36 * info specific for the scope of :if / elseif / else
37 */
38typedef struct {
39 int is_if_label; // instruction idx at IF or ELSEIF
40 endlabel_T *is_end_label; // instructions to set end label
41} ifscope_T;
42
43/*
44 * info specific for the scope of :while
45 */
46typedef struct {
47 int ws_top_label; // instruction idx at WHILE
48 endlabel_T *ws_end_label; // instructions to set end
49} whilescope_T;
50
51/*
52 * info specific for the scope of :for
53 */
54typedef struct {
55 int fs_top_label; // instruction idx at FOR
56 endlabel_T *fs_end_label; // break instructions
57} forscope_T;
58
59/*
60 * info specific for the scope of :try
61 */
62typedef struct {
63 int ts_try_label; // instruction idx at TRY
64 endlabel_T *ts_end_label; // jump to :finally or :endtry
65 int ts_catch_label; // instruction idx of last CATCH
66 int ts_caught_all; // "catch" without argument encountered
67} tryscope_T;
68
69typedef enum {
70 NO_SCOPE,
71 IF_SCOPE,
72 WHILE_SCOPE,
73 FOR_SCOPE,
74 TRY_SCOPE,
75 BLOCK_SCOPE
76} scopetype_T;
77
78/*
79 * Info for one scope, pointed to by "ctx_scope".
80 */
81typedef struct scope_S scope_T;
82struct scope_S {
83 scope_T *se_outer; // scope containing this one
84 scopetype_T se_type;
85 int se_local_count; // ctx_locals.ga_len before scope
86 union {
87 ifscope_T se_if;
88 whilescope_T se_while;
89 forscope_T se_for;
90 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +010091 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010092};
93
94/*
95 * Entry for "ctx_locals". Used for arguments and local variables.
96 */
97typedef struct {
98 char_u *lv_name;
99 type_T *lv_type;
100 int lv_const; // when TRUE cannot be assigned to
101 int lv_arg; // when TRUE this is an argument
102} lvar_T;
103
104/*
105 * Context for compiling lines of Vim script.
106 * Stores info about the local variables and condition stack.
107 */
108struct cctx_S {
109 ufunc_T *ctx_ufunc; // current function
110 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200111 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100112 garray_T ctx_instr; // generated instructions
113
114 garray_T ctx_locals; // currently visible local variables
115 int ctx_max_local; // maximum number of locals at one time
116
117 garray_T ctx_imports; // imported items
118
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100119 int ctx_skip; // when TRUE skip commands, when FALSE skip
120 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100121 scope_T *ctx_scope; // current scope, NULL at toplevel
122
123 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200124 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100125};
126
127static char e_var_notfound[] = N_("E1001: variable not found: %s");
128static char e_syntax_at[] = N_("E1002: Syntax error at %s");
129
130static int compile_expr1(char_u **arg, cctx_T *cctx);
131static int compile_expr2(char_u **arg, cctx_T *cctx);
132static int compile_expr3(char_u **arg, cctx_T *cctx);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100133static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200134static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
135static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100136
137/*
138 * Lookup variable "name" in the local scope and return the index.
139 */
140 static int
141lookup_local(char_u *name, size_t len, cctx_T *cctx)
142{
143 int idx;
144
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100145 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146 return -1;
147 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
148 {
149 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
150
151 if (STRNCMP(name, lvar->lv_name, len) == 0
152 && STRLEN(lvar->lv_name) == len)
153 return idx;
154 }
155 return -1;
156}
157
158/*
159 * Lookup an argument in the current function.
160 * Returns the argument index or -1 if not found.
161 */
162 static int
163lookup_arg(char_u *name, size_t len, cctx_T *cctx)
164{
165 int idx;
166
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100167 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100168 return -1;
169 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
170 {
171 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
172
173 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
174 return idx;
175 }
176 return -1;
177}
178
179/*
180 * Lookup a vararg argument in the current function.
181 * Returns TRUE if there is a match.
182 */
183 static int
184lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
185{
186 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
187
188 return len > 0 && va_name != NULL
189 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
190}
191
192/*
193 * Lookup a variable in the current script.
194 * Returns OK or FAIL.
195 */
196 static int
197lookup_script(char_u *name, size_t len)
198{
199 int cc;
200 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
201 dictitem_T *di;
202
203 cc = name[len];
204 name[len] = NUL;
205 di = find_var_in_ht(ht, 0, name, TRUE);
206 name[len] = cc;
207 return di == NULL ? FAIL: OK;
208}
209
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100210/*
211 * Check if "p[len]" is already defined, either in script "import_sid" or in
212 * compilation context "cctx".
213 * Return FAIL and give an error if it defined.
214 */
215 int
216check_defined(char_u *p, int len, cctx_T *cctx)
217{
218 if (lookup_script(p, len) == OK
219 || (cctx != NULL
220 && (lookup_local(p, len, cctx) >= 0
221 || find_imported(p, len, cctx) != NULL)))
222 {
223 semsg("E1073: imported name already defined: %s", p);
224 return FAIL;
225 }
226 return OK;
227}
228
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200229/*
230 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
231 * be freed later.
232 */
233 static type_T *
234alloc_type(garray_T *type_gap)
235{
236 type_T *type;
237
238 if (ga_grow(type_gap, 1) == FAIL)
239 return NULL;
240 type = ALLOC_CLEAR_ONE(type_T);
241 if (type != NULL)
242 {
243 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
244 ++type_gap->ga_len;
245 }
246 return type;
247}
248
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100249 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200250get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100251{
252 type_T *type;
253
254 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200255 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100256 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200257 if (member_type->tt_type == VAR_VOID
258 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100259 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100260 if (member_type->tt_type == VAR_BOOL)
261 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100262 if (member_type->tt_type == VAR_NUMBER)
263 return &t_list_number;
264 if (member_type->tt_type == VAR_STRING)
265 return &t_list_string;
266
267 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200268 type = alloc_type(type_gap);
269 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100270 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 type->tt_type = VAR_LIST;
272 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200273 type->tt_argcount = 0;
274 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100275 return type;
276}
277
278 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200279get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100280{
281 type_T *type;
282
283 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200284 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100285 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200286 if (member_type->tt_type == VAR_VOID
287 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100288 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100289 if (member_type->tt_type == VAR_BOOL)
290 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100291 if (member_type->tt_type == VAR_NUMBER)
292 return &t_dict_number;
293 if (member_type->tt_type == VAR_STRING)
294 return &t_dict_string;
295
296 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200297 type = alloc_type(type_gap);
298 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100299 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100300 type->tt_type = VAR_DICT;
301 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200302 type->tt_argcount = 0;
303 type->tt_args = NULL;
304 return type;
305}
306
307/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200308 * Allocate a new type for a function.
309 */
310 static type_T *
311alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
312{
313 type_T *type = alloc_type(type_gap);
314
315 if (type == NULL)
316 return &t_any;
317 type->tt_type = VAR_FUNC;
318 type->tt_member = ret_type;
319 type->tt_argcount = argcount;
320 type->tt_args = NULL;
321 return type;
322}
323
324/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200325 * Get a function type, based on the return type "ret_type".
326 * If "argcount" is -1 or 0 a predefined type can be used.
327 * If "argcount" > 0 always create a new type, so that arguments can be added.
328 */
329 static type_T *
330get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
331{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200332 // recognize commonly used types
333 if (argcount <= 0)
334 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200335 if (ret_type == &t_unknown)
336 {
337 // (argcount == 0) is not possible
338 return &t_func_unknown;
339 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200340 if (ret_type == &t_void)
341 {
342 if (argcount == 0)
343 return &t_func_0_void;
344 else
345 return &t_func_void;
346 }
347 if (ret_type == &t_any)
348 {
349 if (argcount == 0)
350 return &t_func_0_any;
351 else
352 return &t_func_any;
353 }
354 if (ret_type == &t_number)
355 {
356 if (argcount == 0)
357 return &t_func_0_number;
358 else
359 return &t_func_number;
360 }
361 if (ret_type == &t_string)
362 {
363 if (argcount == 0)
364 return &t_func_0_string;
365 else
366 return &t_func_string;
367 }
368 }
369
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200370 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100371}
372
Bram Moolenaara8c17702020-04-01 21:17:24 +0200373/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200374 * For a function type, reserve space for "argcount" argument types (including
375 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200376 */
377 static int
378func_type_add_arg_types(
379 type_T *functype,
380 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200381 garray_T *type_gap)
382{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200383 // To make it easy to free the space needed for the argument types, add the
384 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200385 if (ga_grow(type_gap, 1) == FAIL)
386 return FAIL;
387 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
388 if (functype->tt_args == NULL)
389 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200390 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
391 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200392 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200393 return OK;
394}
395
396/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200397 * Return the type_T for a typval. Only for primitive types.
398 */
399 static type_T *
400typval2type(typval_T *tv)
401{
402 if (tv->v_type == VAR_NUMBER)
403 return &t_number;
404 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200405 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200406 if (tv->v_type == VAR_STRING)
407 return &t_string;
408 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
409 return &t_list_string;
410 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
411 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200412 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200413}
414
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100415/////////////////////////////////////////////////////////////////////
416// Following generate_ functions expect the caller to call ga_grow().
417
Bram Moolenaar080457c2020-03-03 21:53:32 +0100418#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
419#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
420
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100421/*
422 * Generate an instruction without arguments.
423 * Returns a pointer to the new instruction, NULL if failed.
424 */
425 static isn_T *
426generate_instr(cctx_T *cctx, isntype_T isn_type)
427{
428 garray_T *instr = &cctx->ctx_instr;
429 isn_T *isn;
430
Bram Moolenaar080457c2020-03-03 21:53:32 +0100431 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100432 if (ga_grow(instr, 1) == FAIL)
433 return NULL;
434 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
435 isn->isn_type = isn_type;
436 isn->isn_lnum = cctx->ctx_lnum + 1;
437 ++instr->ga_len;
438
439 return isn;
440}
441
442/*
443 * Generate an instruction without arguments.
444 * "drop" will be removed from the stack.
445 * Returns a pointer to the new instruction, NULL if failed.
446 */
447 static isn_T *
448generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
449{
450 garray_T *stack = &cctx->ctx_type_stack;
451
Bram Moolenaar080457c2020-03-03 21:53:32 +0100452 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100453 stack->ga_len -= drop;
454 return generate_instr(cctx, isn_type);
455}
456
457/*
458 * Generate instruction "isn_type" and put "type" on the type stack.
459 */
460 static isn_T *
461generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
462{
463 isn_T *isn;
464 garray_T *stack = &cctx->ctx_type_stack;
465
466 if ((isn = generate_instr(cctx, isn_type)) == NULL)
467 return NULL;
468
469 if (ga_grow(stack, 1) == FAIL)
470 return NULL;
471 ((type_T **)stack->ga_data)[stack->ga_len] = type;
472 ++stack->ga_len;
473
474 return isn;
475}
476
477/*
478 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
479 */
480 static int
481may_generate_2STRING(int offset, cctx_T *cctx)
482{
483 isn_T *isn;
484 garray_T *stack = &cctx->ctx_type_stack;
485 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
486
487 if ((*type)->tt_type == VAR_STRING)
488 return OK;
489 *type = &t_string;
490
491 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
492 return FAIL;
493 isn->isn_arg.number = offset;
494
495 return OK;
496}
497
498 static int
499check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
500{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200501 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100502 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200503 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100504 {
505 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100506 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100507 else
508 semsg(_("E1036: %c requires number or float arguments"), *op);
509 return FAIL;
510 }
511 return OK;
512}
513
514/*
515 * Generate an instruction with two arguments. The instruction depends on the
516 * type of the arguments.
517 */
518 static int
519generate_two_op(cctx_T *cctx, char_u *op)
520{
521 garray_T *stack = &cctx->ctx_type_stack;
522 type_T *type1;
523 type_T *type2;
524 vartype_T vartype;
525 isn_T *isn;
526
Bram Moolenaar080457c2020-03-03 21:53:32 +0100527 RETURN_OK_IF_SKIP(cctx);
528
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100529 // Get the known type of the two items on the stack. If they are matching
530 // use a type-specific instruction. Otherwise fall back to runtime type
531 // checking.
532 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
533 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200534 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100535 if (type1->tt_type == type2->tt_type
536 && (type1->tt_type == VAR_NUMBER
537 || type1->tt_type == VAR_LIST
538#ifdef FEAT_FLOAT
539 || type1->tt_type == VAR_FLOAT
540#endif
541 || type1->tt_type == VAR_BLOB))
542 vartype = type1->tt_type;
543
544 switch (*op)
545 {
546 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200547 && type1->tt_type != VAR_ANY
548 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100549 && check_number_or_float(
550 type1->tt_type, type2->tt_type, op) == FAIL)
551 return FAIL;
552 isn = generate_instr_drop(cctx,
553 vartype == VAR_NUMBER ? ISN_OPNR
554 : vartype == VAR_LIST ? ISN_ADDLIST
555 : vartype == VAR_BLOB ? ISN_ADDBLOB
556#ifdef FEAT_FLOAT
557 : vartype == VAR_FLOAT ? ISN_OPFLOAT
558#endif
559 : ISN_OPANY, 1);
560 if (isn != NULL)
561 isn->isn_arg.op.op_type = EXPR_ADD;
562 break;
563
564 case '-':
565 case '*':
566 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
567 op) == FAIL)
568 return FAIL;
569 if (vartype == VAR_NUMBER)
570 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
571#ifdef FEAT_FLOAT
572 else if (vartype == VAR_FLOAT)
573 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
574#endif
575 else
576 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
577 if (isn != NULL)
578 isn->isn_arg.op.op_type = *op == '*'
579 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
580 break;
581
Bram Moolenaar4c683752020-04-05 21:38:23 +0200582 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100583 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200584 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100585 && type2->tt_type != VAR_NUMBER))
586 {
587 emsg(_("E1035: % requires number arguments"));
588 return FAIL;
589 }
590 isn = generate_instr_drop(cctx,
591 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
592 if (isn != NULL)
593 isn->isn_arg.op.op_type = EXPR_REM;
594 break;
595 }
596
597 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200598 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100599 {
600 type_T *type = &t_any;
601
602#ifdef FEAT_FLOAT
603 // float+number and number+float results in float
604 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
605 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
606 type = &t_float;
607#endif
608 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
609 }
610
611 return OK;
612}
613
614/*
615 * Generate an ISN_COMPARE* instruction with a boolean result.
616 */
617 static int
618generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
619{
620 isntype_T isntype = ISN_DROP;
621 isn_T *isn;
622 garray_T *stack = &cctx->ctx_type_stack;
623 vartype_T type1;
624 vartype_T type2;
625
Bram Moolenaar080457c2020-03-03 21:53:32 +0100626 RETURN_OK_IF_SKIP(cctx);
627
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100628 // Get the known type of the two items on the stack. If they are matching
629 // use a type-specific instruction. Otherwise fall back to runtime type
630 // checking.
631 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
632 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200633 if (type1 == VAR_UNKNOWN)
634 type1 = VAR_ANY;
635 if (type2 == VAR_UNKNOWN)
636 type2 = VAR_ANY;
637
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100638 if (type1 == type2)
639 {
640 switch (type1)
641 {
642 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
643 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
644 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
645 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
646 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
647 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
648 case VAR_LIST: isntype = ISN_COMPARELIST; break;
649 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
650 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100651 default: isntype = ISN_COMPAREANY; break;
652 }
653 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200654 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100655 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
656 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
657 isntype = ISN_COMPAREANY;
658
659 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
660 && (isntype == ISN_COMPAREBOOL
661 || isntype == ISN_COMPARESPECIAL
662 || isntype == ISN_COMPARENR
663 || isntype == ISN_COMPAREFLOAT))
664 {
665 semsg(_("E1037: Cannot use \"%s\" with %s"),
666 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
667 return FAIL;
668 }
669 if (isntype == ISN_DROP
670 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
671 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
672 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
673 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
674 && exptype != EXPR_IS && exptype != EXPR_ISNOT
675 && (type1 == VAR_BLOB || type2 == VAR_BLOB
676 || type1 == VAR_LIST || type2 == VAR_LIST))))
677 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100678 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100679 vartype_name(type1), vartype_name(type2));
680 return FAIL;
681 }
682
683 if ((isn = generate_instr(cctx, isntype)) == NULL)
684 return FAIL;
685 isn->isn_arg.op.op_type = exptype;
686 isn->isn_arg.op.op_ic = ic;
687
688 // takes two arguments, puts one bool back
689 if (stack->ga_len >= 2)
690 {
691 --stack->ga_len;
692 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
693 }
694
695 return OK;
696}
697
698/*
699 * Generate an ISN_2BOOL instruction.
700 */
701 static int
702generate_2BOOL(cctx_T *cctx, int invert)
703{
704 isn_T *isn;
705 garray_T *stack = &cctx->ctx_type_stack;
706
Bram Moolenaar080457c2020-03-03 21:53:32 +0100707 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100708 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
709 return FAIL;
710 isn->isn_arg.number = invert;
711
712 // type becomes bool
713 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
714
715 return OK;
716}
717
718 static int
719generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
720{
721 isn_T *isn;
722 garray_T *stack = &cctx->ctx_type_stack;
723
Bram Moolenaar080457c2020-03-03 21:53:32 +0100724 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100725 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
726 return FAIL;
727 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
728 isn->isn_arg.type.ct_off = offset;
729
730 // type becomes vartype
731 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
732
733 return OK;
734}
735
736/*
737 * Generate an ISN_PUSHNR instruction.
738 */
739 static int
740generate_PUSHNR(cctx_T *cctx, varnumber_T number)
741{
742 isn_T *isn;
743
Bram Moolenaar080457c2020-03-03 21:53:32 +0100744 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100745 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
746 return FAIL;
747 isn->isn_arg.number = number;
748
749 return OK;
750}
751
752/*
753 * Generate an ISN_PUSHBOOL instruction.
754 */
755 static int
756generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
757{
758 isn_T *isn;
759
Bram Moolenaar080457c2020-03-03 21:53:32 +0100760 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100761 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
762 return FAIL;
763 isn->isn_arg.number = number;
764
765 return OK;
766}
767
768/*
769 * Generate an ISN_PUSHSPEC instruction.
770 */
771 static int
772generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
773{
774 isn_T *isn;
775
Bram Moolenaar080457c2020-03-03 21:53:32 +0100776 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100777 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
778 return FAIL;
779 isn->isn_arg.number = number;
780
781 return OK;
782}
783
784#ifdef FEAT_FLOAT
785/*
786 * Generate an ISN_PUSHF instruction.
787 */
788 static int
789generate_PUSHF(cctx_T *cctx, float_T fnumber)
790{
791 isn_T *isn;
792
Bram Moolenaar080457c2020-03-03 21:53:32 +0100793 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100794 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
795 return FAIL;
796 isn->isn_arg.fnumber = fnumber;
797
798 return OK;
799}
800#endif
801
802/*
803 * Generate an ISN_PUSHS instruction.
804 * Consumes "str".
805 */
806 static int
807generate_PUSHS(cctx_T *cctx, char_u *str)
808{
809 isn_T *isn;
810
Bram Moolenaar080457c2020-03-03 21:53:32 +0100811 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100812 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
813 return FAIL;
814 isn->isn_arg.string = str;
815
816 return OK;
817}
818
819/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100820 * Generate an ISN_PUSHCHANNEL instruction.
821 * Consumes "channel".
822 */
823 static int
824generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
825{
826 isn_T *isn;
827
Bram Moolenaar080457c2020-03-03 21:53:32 +0100828 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100829 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
830 return FAIL;
831 isn->isn_arg.channel = channel;
832
833 return OK;
834}
835
836/*
837 * Generate an ISN_PUSHJOB instruction.
838 * Consumes "job".
839 */
840 static int
841generate_PUSHJOB(cctx_T *cctx, job_T *job)
842{
843 isn_T *isn;
844
Bram Moolenaar080457c2020-03-03 21:53:32 +0100845 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100846 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100847 return FAIL;
848 isn->isn_arg.job = job;
849
850 return OK;
851}
852
853/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100854 * Generate an ISN_PUSHBLOB instruction.
855 * Consumes "blob".
856 */
857 static int
858generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
859{
860 isn_T *isn;
861
Bram Moolenaar080457c2020-03-03 21:53:32 +0100862 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100863 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
864 return FAIL;
865 isn->isn_arg.blob = blob;
866
867 return OK;
868}
869
870/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100871 * Generate an ISN_PUSHFUNC instruction with name "name".
872 * Consumes "name".
873 */
874 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200875generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100876{
877 isn_T *isn;
878
Bram Moolenaar080457c2020-03-03 21:53:32 +0100879 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200880 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100881 return FAIL;
882 isn->isn_arg.string = name;
883
884 return OK;
885}
886
887/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100888 * Generate an ISN_STORE instruction.
889 */
890 static int
891generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
892{
893 isn_T *isn;
894
Bram Moolenaar080457c2020-03-03 21:53:32 +0100895 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100896 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
897 return FAIL;
898 if (name != NULL)
899 isn->isn_arg.string = vim_strsave(name);
900 else
901 isn->isn_arg.number = idx;
902
903 return OK;
904}
905
906/*
907 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
908 */
909 static int
910generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
911{
912 isn_T *isn;
913
Bram Moolenaar080457c2020-03-03 21:53:32 +0100914 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100915 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
916 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100917 isn->isn_arg.storenr.stnr_idx = idx;
918 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100919
920 return OK;
921}
922
923/*
924 * Generate an ISN_STOREOPT instruction
925 */
926 static int
927generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
928{
929 isn_T *isn;
930
Bram Moolenaar080457c2020-03-03 21:53:32 +0100931 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100932 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
933 return FAIL;
934 isn->isn_arg.storeopt.so_name = vim_strsave(name);
935 isn->isn_arg.storeopt.so_flags = opt_flags;
936
937 return OK;
938}
939
940/*
941 * Generate an ISN_LOAD or similar instruction.
942 */
943 static int
944generate_LOAD(
945 cctx_T *cctx,
946 isntype_T isn_type,
947 int idx,
948 char_u *name,
949 type_T *type)
950{
951 isn_T *isn;
952
Bram Moolenaar080457c2020-03-03 21:53:32 +0100953 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100954 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
955 return FAIL;
956 if (name != NULL)
957 isn->isn_arg.string = vim_strsave(name);
958 else
959 isn->isn_arg.number = idx;
960
961 return OK;
962}
963
964/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200965 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100966 */
967 static int
968generate_LOADV(
969 cctx_T *cctx,
970 char_u *name,
971 int error)
972{
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200973 int di_flags;
974 int vidx = find_vim_var(name, &di_flags);
975 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100976
Bram Moolenaar080457c2020-03-03 21:53:32 +0100977 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100978 if (vidx < 0)
979 {
980 if (error)
981 semsg(_(e_var_notfound), name);
982 return FAIL;
983 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200984 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100985
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200986 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100987}
988
989/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100990 * Generate an ISN_LOADS instruction.
991 */
992 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100993generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100994 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100995 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100996 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100997 int sid,
998 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100999{
1000 isn_T *isn;
1001
Bram Moolenaar080457c2020-03-03 21:53:32 +01001002 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001003 if (isn_type == ISN_LOADS)
1004 isn = generate_instr_type(cctx, isn_type, type);
1005 else
1006 isn = generate_instr_drop(cctx, isn_type, 1);
1007 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001008 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001009 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1010 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011
1012 return OK;
1013}
1014
1015/*
1016 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1017 */
1018 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001019generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001020 cctx_T *cctx,
1021 isntype_T isn_type,
1022 int sid,
1023 int idx,
1024 type_T *type)
1025{
1026 isn_T *isn;
1027
Bram Moolenaar080457c2020-03-03 21:53:32 +01001028 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001029 if (isn_type == ISN_LOADSCRIPT)
1030 isn = generate_instr_type(cctx, isn_type, type);
1031 else
1032 isn = generate_instr_drop(cctx, isn_type, 1);
1033 if (isn == NULL)
1034 return FAIL;
1035 isn->isn_arg.script.script_sid = sid;
1036 isn->isn_arg.script.script_idx = idx;
1037 return OK;
1038}
1039
1040/*
1041 * Generate an ISN_NEWLIST instruction.
1042 */
1043 static int
1044generate_NEWLIST(cctx_T *cctx, int count)
1045{
1046 isn_T *isn;
1047 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001048 type_T *type;
1049 type_T *member;
1050
Bram Moolenaar080457c2020-03-03 21:53:32 +01001051 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001052 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1053 return FAIL;
1054 isn->isn_arg.number = count;
1055
1056 // drop the value types
1057 stack->ga_len -= count;
1058
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001059 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001060 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001061 if (count > 0)
1062 member = ((type_T **)stack->ga_data)[stack->ga_len];
1063 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001064 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001065 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001066
1067 // add the list type to the type stack
1068 if (ga_grow(stack, 1) == FAIL)
1069 return FAIL;
1070 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1071 ++stack->ga_len;
1072
1073 return OK;
1074}
1075
1076/*
1077 * Generate an ISN_NEWDICT instruction.
1078 */
1079 static int
1080generate_NEWDICT(cctx_T *cctx, int count)
1081{
1082 isn_T *isn;
1083 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001084 type_T *type;
1085 type_T *member;
1086
Bram Moolenaar080457c2020-03-03 21:53:32 +01001087 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001088 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1089 return FAIL;
1090 isn->isn_arg.number = count;
1091
1092 // drop the key and value types
1093 stack->ga_len -= 2 * count;
1094
Bram Moolenaar436472f2020-02-20 22:54:43 +01001095 // Use the first value type for the list member type. Use "void" for an
1096 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001097 if (count > 0)
1098 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1099 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001100 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001101 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001102
1103 // add the dict type to the type stack
1104 if (ga_grow(stack, 1) == FAIL)
1105 return FAIL;
1106 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1107 ++stack->ga_len;
1108
1109 return OK;
1110}
1111
1112/*
1113 * Generate an ISN_FUNCREF instruction.
1114 */
1115 static int
1116generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1117{
1118 isn_T *isn;
1119 garray_T *stack = &cctx->ctx_type_stack;
1120
Bram Moolenaar080457c2020-03-03 21:53:32 +01001121 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001122 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1123 return FAIL;
1124 isn->isn_arg.number = dfunc_idx;
1125
1126 if (ga_grow(stack, 1) == FAIL)
1127 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001128 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001129 // TODO: argument and return types
1130 ++stack->ga_len;
1131
1132 return OK;
1133}
1134
1135/*
1136 * Generate an ISN_JUMP instruction.
1137 */
1138 static int
1139generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1140{
1141 isn_T *isn;
1142 garray_T *stack = &cctx->ctx_type_stack;
1143
Bram Moolenaar080457c2020-03-03 21:53:32 +01001144 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001145 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1146 return FAIL;
1147 isn->isn_arg.jump.jump_when = when;
1148 isn->isn_arg.jump.jump_where = where;
1149
1150 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1151 --stack->ga_len;
1152
1153 return OK;
1154}
1155
1156 static int
1157generate_FOR(cctx_T *cctx, int loop_idx)
1158{
1159 isn_T *isn;
1160 garray_T *stack = &cctx->ctx_type_stack;
1161
Bram Moolenaar080457c2020-03-03 21:53:32 +01001162 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001163 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1164 return FAIL;
1165 isn->isn_arg.forloop.for_idx = loop_idx;
1166
1167 if (ga_grow(stack, 1) == FAIL)
1168 return FAIL;
1169 // type doesn't matter, will be stored next
1170 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1171 ++stack->ga_len;
1172
1173 return OK;
1174}
1175
1176/*
1177 * Generate an ISN_BCALL instruction.
1178 * Return FAIL if the number of arguments is wrong.
1179 */
1180 static int
1181generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1182{
1183 isn_T *isn;
1184 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001185 type_T *argtypes[MAX_FUNC_ARGS];
1186 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001187
Bram Moolenaar080457c2020-03-03 21:53:32 +01001188 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001189 if (check_internal_func(func_idx, argcount) == FAIL)
1190 return FAIL;
1191
1192 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1193 return FAIL;
1194 isn->isn_arg.bfunc.cbf_idx = func_idx;
1195 isn->isn_arg.bfunc.cbf_argcount = argcount;
1196
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001197 for (i = 0; i < argcount; ++i)
1198 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1199
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001200 stack->ga_len -= argcount; // drop the arguments
1201 if (ga_grow(stack, 1) == FAIL)
1202 return FAIL;
1203 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001204 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001205 ++stack->ga_len; // add return value
1206
1207 return OK;
1208}
1209
1210/*
1211 * Generate an ISN_DCALL or ISN_UCALL instruction.
1212 * Return FAIL if the number of arguments is wrong.
1213 */
1214 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001215generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001216{
1217 isn_T *isn;
1218 garray_T *stack = &cctx->ctx_type_stack;
1219 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001220 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001221
Bram Moolenaar080457c2020-03-03 21:53:32 +01001222 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001223 if (argcount > regular_args && !has_varargs(ufunc))
1224 {
1225 semsg(_(e_toomanyarg), ufunc->uf_name);
1226 return FAIL;
1227 }
1228 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1229 {
1230 semsg(_(e_toofewarg), ufunc->uf_name);
1231 return FAIL;
1232 }
1233
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001234 if (ufunc->uf_dfunc_idx >= 0)
1235 {
1236 int i;
1237
1238 for (i = 0; i < argcount; ++i)
1239 {
1240 type_T *expected;
1241 type_T *actual;
1242
1243 if (i < regular_args)
1244 {
1245 if (ufunc->uf_arg_types == NULL)
1246 continue;
1247 expected = ufunc->uf_arg_types[i];
1248 }
1249 else
1250 expected = ufunc->uf_va_type->tt_member;
1251 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1252 if (check_type(expected, actual, FALSE) == FAIL)
1253 {
1254 arg_type_mismatch(expected, actual, i + 1);
1255 return FAIL;
1256 }
1257 }
1258 }
1259
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001260 if ((isn = generate_instr(cctx,
1261 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1262 return FAIL;
1263 if (ufunc->uf_dfunc_idx >= 0)
1264 {
1265 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1266 isn->isn_arg.dfunc.cdf_argcount = argcount;
1267 }
1268 else
1269 {
1270 // A user function may be deleted and redefined later, can't use the
1271 // ufunc pointer, need to look it up again at runtime.
1272 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1273 isn->isn_arg.ufunc.cuf_argcount = argcount;
1274 }
1275
1276 stack->ga_len -= argcount; // drop the arguments
1277 if (ga_grow(stack, 1) == FAIL)
1278 return FAIL;
1279 // add return value
1280 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1281 ++stack->ga_len;
1282
1283 return OK;
1284}
1285
1286/*
1287 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1288 */
1289 static int
1290generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1291{
1292 isn_T *isn;
1293 garray_T *stack = &cctx->ctx_type_stack;
1294
Bram Moolenaar080457c2020-03-03 21:53:32 +01001295 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001296 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1297 return FAIL;
1298 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1299 isn->isn_arg.ufunc.cuf_argcount = argcount;
1300
1301 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001302 if (ga_grow(stack, 1) == FAIL)
1303 return FAIL;
1304 // add return value
1305 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1306 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001307
1308 return OK;
1309}
1310
1311/*
1312 * Generate an ISN_PCALL instruction.
1313 */
1314 static int
1315generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1316{
1317 isn_T *isn;
1318 garray_T *stack = &cctx->ctx_type_stack;
1319
Bram Moolenaar080457c2020-03-03 21:53:32 +01001320 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001321
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001322 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1323 return FAIL;
1324 isn->isn_arg.pfunc.cpf_top = at_top;
1325 isn->isn_arg.pfunc.cpf_argcount = argcount;
1326
1327 stack->ga_len -= argcount; // drop the arguments
1328
1329 // drop the funcref/partial, get back the return value
1330 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1331
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001332 // If partial is above the arguments it must be cleared and replaced with
1333 // the return value.
1334 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1335 return FAIL;
1336
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001337 return OK;
1338}
1339
1340/*
1341 * Generate an ISN_MEMBER instruction.
1342 */
1343 static int
1344generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1345{
1346 isn_T *isn;
1347 garray_T *stack = &cctx->ctx_type_stack;
1348 type_T *type;
1349
Bram Moolenaar080457c2020-03-03 21:53:32 +01001350 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001351 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1352 return FAIL;
1353 isn->isn_arg.string = vim_strnsave(name, (int)len);
1354
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001355 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001356 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001357 if (type->tt_type != VAR_DICT && type != &t_any)
1358 {
1359 emsg(_(e_dictreq));
1360 return FAIL;
1361 }
1362 // change dict type to dict member type
1363 if (type->tt_type == VAR_DICT)
1364 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001365
1366 return OK;
1367}
1368
1369/*
1370 * Generate an ISN_ECHO instruction.
1371 */
1372 static int
1373generate_ECHO(cctx_T *cctx, int with_white, int count)
1374{
1375 isn_T *isn;
1376
Bram Moolenaar080457c2020-03-03 21:53:32 +01001377 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001378 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1379 return FAIL;
1380 isn->isn_arg.echo.echo_with_white = with_white;
1381 isn->isn_arg.echo.echo_count = count;
1382
1383 return OK;
1384}
1385
Bram Moolenaarad39c092020-02-26 18:23:43 +01001386/*
1387 * Generate an ISN_EXECUTE instruction.
1388 */
1389 static int
1390generate_EXECUTE(cctx_T *cctx, int count)
1391{
1392 isn_T *isn;
1393
1394 if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL)
1395 return FAIL;
1396 isn->isn_arg.number = count;
1397
1398 return OK;
1399}
1400
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001401 static int
1402generate_EXEC(cctx_T *cctx, char_u *line)
1403{
1404 isn_T *isn;
1405
Bram Moolenaar080457c2020-03-03 21:53:32 +01001406 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001407 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1408 return FAIL;
1409 isn->isn_arg.string = vim_strsave(line);
1410 return OK;
1411}
1412
1413static char e_white_both[] =
1414 N_("E1004: white space required before and after '%s'");
Bram Moolenaard77a8522020-04-03 21:59:57 +02001415static char e_white_after[] = N_("E1069: white space required after '%s'");
1416static char e_no_white_before[] = N_("E1068: No white space allowed before '%s'");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001417
1418/*
1419 * Reserve space for a local variable.
1420 * Return the index or -1 if it failed.
1421 */
1422 static int
1423reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1424{
1425 int idx;
1426 lvar_T *lvar;
1427
1428 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1429 {
1430 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1431 return -1;
1432 }
1433
1434 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1435 return -1;
1436 idx = cctx->ctx_locals.ga_len;
1437 if (cctx->ctx_max_local < idx + 1)
1438 cctx->ctx_max_local = idx + 1;
1439 ++cctx->ctx_locals.ga_len;
1440
1441 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1442 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1443 lvar->lv_const = isConst;
1444 lvar->lv_type = type;
1445
1446 return idx;
1447}
1448
1449/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001450 * Remove local variables above "new_top".
1451 */
1452 static void
1453unwind_locals(cctx_T *cctx, int new_top)
1454{
1455 if (cctx->ctx_locals.ga_len > new_top)
1456 {
1457 int idx;
1458 lvar_T *lvar;
1459
1460 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1461 {
1462 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1463 vim_free(lvar->lv_name);
1464 }
1465 }
1466 cctx->ctx_locals.ga_len = new_top;
1467}
1468
1469/*
1470 * Free all local variables.
1471 */
1472 static void
1473free_local(cctx_T *cctx)
1474{
1475 unwind_locals(cctx, 0);
1476 ga_clear(&cctx->ctx_locals);
1477}
1478
1479/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001480 * Skip over a type definition and return a pointer to just after it.
1481 */
1482 char_u *
1483skip_type(char_u *start)
1484{
1485 char_u *p = start;
1486
1487 while (ASCII_ISALNUM(*p) || *p == '_')
1488 ++p;
1489
1490 // Skip over "<type>"; this is permissive about white space.
1491 if (*skipwhite(p) == '<')
1492 {
1493 p = skipwhite(p);
1494 p = skip_type(skipwhite(p + 1));
1495 p = skipwhite(p);
1496 if (*p == '>')
1497 ++p;
1498 }
1499 return p;
1500}
1501
1502/*
1503 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001504 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001505 * Returns NULL in case of failure.
1506 */
1507 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001508parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001509{
1510 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001511 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001512
1513 if (**arg != '<')
1514 {
1515 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001516 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001517 else
1518 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001519 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001520 }
1521 *arg = skipwhite(*arg + 1);
1522
Bram Moolenaard77a8522020-04-03 21:59:57 +02001523 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001524
1525 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001526 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001527 {
1528 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001529 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001530 }
1531 ++*arg;
1532
1533 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001534 return get_list_type(member_type, type_gap);
1535 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001536}
1537
1538/*
1539 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001540 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001541 */
1542 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001543parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001544{
1545 char_u *p = *arg;
1546 size_t len;
1547
1548 // skip over the first word
1549 while (ASCII_ISALNUM(*p) || *p == '_')
1550 ++p;
1551 len = p - *arg;
1552
1553 switch (**arg)
1554 {
1555 case 'a':
1556 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1557 {
1558 *arg += len;
1559 return &t_any;
1560 }
1561 break;
1562 case 'b':
1563 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1564 {
1565 *arg += len;
1566 return &t_bool;
1567 }
1568 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1569 {
1570 *arg += len;
1571 return &t_blob;
1572 }
1573 break;
1574 case 'c':
1575 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1576 {
1577 *arg += len;
1578 return &t_channel;
1579 }
1580 break;
1581 case 'd':
1582 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1583 {
1584 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001585 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001586 }
1587 break;
1588 case 'f':
1589 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1590 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001591#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001592 *arg += len;
1593 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001594#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001595 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001596 return &t_any;
1597#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001598 }
1599 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1600 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001601 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001602 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001603 int argcount = -1;
1604 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001605 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001606 type_T *arg_type[MAX_FUNC_ARGS + 1];
1607
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001608 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001609 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001610 if (**arg == '(')
1611 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001612 // "func" may or may not return a value, "func()" does
1613 // not return a value.
1614 ret_type = &t_void;
1615
Bram Moolenaard77a8522020-04-03 21:59:57 +02001616 p = ++*arg;
1617 argcount = 0;
1618 while (*p != NUL && *p != ')')
1619 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001620 if (*p == '?')
1621 {
1622 if (first_optional == -1)
1623 first_optional = argcount;
1624 ++p;
1625 }
1626 else if (first_optional != -1)
1627 {
1628 emsg(_("E1007: mandatory argument after optional argument"));
1629 return &t_any;
1630 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001631 else if (STRNCMP(p, "...", 3) == 0)
1632 {
1633 flags |= TTFLAG_VARARGS;
1634 p += 3;
1635 }
1636
1637 arg_type[argcount++] = parse_type(&p, type_gap);
1638
1639 // Nothing comes after "...{type}".
1640 if (flags & TTFLAG_VARARGS)
1641 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001642
Bram Moolenaard77a8522020-04-03 21:59:57 +02001643 if (*p != ',' && *skipwhite(p) == ',')
1644 {
1645 semsg(_(e_no_white_before), ",");
1646 return &t_any;
1647 }
1648 if (*p == ',')
1649 {
1650 ++p;
1651 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001652 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001653 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001654 return &t_any;
1655 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001656 }
1657 p = skipwhite(p);
1658 if (argcount == MAX_FUNC_ARGS)
1659 {
1660 emsg(_("E740: Too many argument types"));
1661 return &t_any;
1662 }
1663 }
1664
1665 p = skipwhite(p);
1666 if (*p != ')')
1667 {
1668 emsg(_(e_missing_close));
1669 return &t_any;
1670 }
1671 *arg = p + 1;
1672 }
1673 if (**arg == ':')
1674 {
1675 // parse return type
1676 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001677 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001678 semsg(_(e_white_after), ":");
1679 *arg = skipwhite(*arg);
1680 ret_type = parse_type(arg, type_gap);
1681 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001682 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001683 type = get_func_type(ret_type, argcount, type_gap);
1684 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001685 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001686 type = alloc_func_type(ret_type, argcount, type_gap);
1687 type->tt_flags = flags;
1688 if (argcount > 0)
1689 {
1690 type->tt_argcount = argcount;
1691 type->tt_min_argcount = first_optional == -1
1692 ? argcount : first_optional;
1693 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001694 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001695 return &t_any;
1696 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001697 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001698 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001699 }
1700 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001701 }
1702 break;
1703 case 'j':
1704 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1705 {
1706 *arg += len;
1707 return &t_job;
1708 }
1709 break;
1710 case 'l':
1711 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1712 {
1713 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001714 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001715 }
1716 break;
1717 case 'n':
1718 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1719 {
1720 *arg += len;
1721 return &t_number;
1722 }
1723 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001724 case 's':
1725 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1726 {
1727 *arg += len;
1728 return &t_string;
1729 }
1730 break;
1731 case 'v':
1732 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1733 {
1734 *arg += len;
1735 return &t_void;
1736 }
1737 break;
1738 }
1739
1740 semsg(_("E1010: Type not recognized: %s"), *arg);
1741 return &t_any;
1742}
1743
1744/*
1745 * Check if "type1" and "type2" are exactly the same.
1746 */
1747 static int
1748equal_type(type_T *type1, type_T *type2)
1749{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001750 int i;
1751
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001752 if (type1->tt_type != type2->tt_type)
1753 return FALSE;
1754 switch (type1->tt_type)
1755 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001756 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001757 case VAR_ANY:
1758 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001759 case VAR_SPECIAL:
1760 case VAR_BOOL:
1761 case VAR_NUMBER:
1762 case VAR_FLOAT:
1763 case VAR_STRING:
1764 case VAR_BLOB:
1765 case VAR_JOB:
1766 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001767 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001768 case VAR_LIST:
1769 case VAR_DICT:
1770 return equal_type(type1->tt_member, type2->tt_member);
1771 case VAR_FUNC:
1772 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001773 if (!equal_type(type1->tt_member, type2->tt_member)
1774 || type1->tt_argcount != type2->tt_argcount)
1775 return FALSE;
1776 if (type1->tt_argcount < 0
1777 || type1->tt_args == NULL || type2->tt_args == NULL)
1778 return TRUE;
1779 for (i = 0; i < type1->tt_argcount; ++i)
1780 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1781 return FALSE;
1782 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001783 }
1784 return TRUE;
1785}
1786
1787/*
1788 * Find the common type of "type1" and "type2" and put it in "dest".
1789 * "type2" and "dest" may be the same.
1790 */
1791 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001792common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001793{
1794 if (equal_type(type1, type2))
1795 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001796 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001797 return;
1798 }
1799
1800 if (type1->tt_type == type2->tt_type)
1801 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001802 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1803 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001804 type_T *common;
1805
Bram Moolenaard77a8522020-04-03 21:59:57 +02001806 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001807 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001808 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001809 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001810 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001811 return;
1812 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001813 if (type1->tt_type == VAR_FUNC)
1814 {
1815 type_T *common;
1816
1817 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1818 if (type1->tt_argcount == type2->tt_argcount
1819 && type1->tt_argcount >= 0)
1820 {
1821 int argcount = type1->tt_argcount;
1822 int i;
1823
1824 *dest = alloc_func_type(common, argcount, type_gap);
1825 if (type1->tt_args != NULL && type2->tt_args != NULL)
1826 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001827 if (func_type_add_arg_types(*dest, argcount,
1828 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001829 for (i = 0; i < argcount; ++i)
1830 common_type(type1->tt_args[i], type2->tt_args[i],
1831 &(*dest)->tt_args[i], type_gap);
1832 }
1833 }
1834 else
1835 *dest = alloc_func_type(common, -1, type_gap);
1836 return;
1837 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001838 }
1839
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001840 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001841}
1842
1843 char *
1844vartype_name(vartype_T type)
1845{
1846 switch (type)
1847 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001848 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001849 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001850 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001851 case VAR_SPECIAL: return "special";
1852 case VAR_BOOL: return "bool";
1853 case VAR_NUMBER: return "number";
1854 case VAR_FLOAT: return "float";
1855 case VAR_STRING: return "string";
1856 case VAR_BLOB: return "blob";
1857 case VAR_JOB: return "job";
1858 case VAR_CHANNEL: return "channel";
1859 case VAR_LIST: return "list";
1860 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001861
1862 case VAR_FUNC:
1863 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001864 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001865 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001866}
1867
1868/*
1869 * Return the name of a type.
1870 * The result may be in allocated memory, in which case "tofree" is set.
1871 */
1872 char *
1873type_name(type_T *type, char **tofree)
1874{
1875 char *name = vartype_name(type->tt_type);
1876
1877 *tofree = NULL;
1878 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1879 {
1880 char *member_free;
1881 char *member_name = type_name(type->tt_member, &member_free);
1882 size_t len;
1883
1884 len = STRLEN(name) + STRLEN(member_name) + 3;
1885 *tofree = alloc(len);
1886 if (*tofree != NULL)
1887 {
1888 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1889 vim_free(member_free);
1890 return *tofree;
1891 }
1892 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001893 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001894 {
1895 garray_T ga;
1896 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001897 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001898
1899 ga_init2(&ga, 1, 100);
1900 if (ga_grow(&ga, 20) == FAIL)
1901 return "[unknown]";
1902 *tofree = ga.ga_data;
1903 STRCPY(ga.ga_data, "func(");
1904 ga.ga_len += 5;
1905
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001906 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001907 {
1908 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001909 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001910 int len;
1911
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001912 if (type->tt_args == NULL)
1913 arg_type = "[unknown]";
1914 else
1915 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001916 if (i > 0)
1917 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001918 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001919 ga.ga_len += 2;
1920 }
1921 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001922 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001923 {
1924 vim_free(arg_free);
1925 return "[unknown]";
1926 }
1927 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001928 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001929 {
1930 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1931 ga.ga_len += 3;
1932 }
1933 else if (i >= type->tt_min_argcount)
1934 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001935 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001936 ga.ga_len += len;
1937 vim_free(arg_free);
1938 }
1939
1940 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001941 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001942 else
1943 {
1944 char *ret_free;
1945 char *ret_name = type_name(type->tt_member, &ret_free);
1946 int len;
1947
1948 len = (int)STRLEN(ret_name) + 4;
1949 if (ga_grow(&ga, len) == FAIL)
1950 {
1951 vim_free(ret_free);
1952 return "[unknown]";
1953 }
1954 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001955 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1956 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001957 vim_free(ret_free);
1958 }
1959 return ga.ga_data;
1960 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001961
1962 return name;
1963}
1964
1965/*
1966 * Find "name" in script-local items of script "sid".
1967 * Returns the index in "sn_var_vals" if found.
1968 * If found but not in "sn_var_vals" returns -1.
1969 * If not found returns -2.
1970 */
1971 int
1972get_script_item_idx(int sid, char_u *name, int check_writable)
1973{
1974 hashtab_T *ht;
1975 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001976 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001977 int idx;
1978
1979 // First look the name up in the hashtable.
1980 if (sid <= 0 || sid > script_items.ga_len)
1981 return -1;
1982 ht = &SCRIPT_VARS(sid);
1983 di = find_var_in_ht(ht, 0, name, TRUE);
1984 if (di == NULL)
1985 return -2;
1986
1987 // Now find the svar_T index in sn_var_vals.
1988 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
1989 {
1990 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
1991
1992 if (sv->sv_tv == &di->di_tv)
1993 {
1994 if (check_writable && sv->sv_const)
1995 semsg(_(e_readonlyvar), name);
1996 return idx;
1997 }
1998 }
1999 return -1;
2000}
2001
2002/*
2003 * Find "name" in imported items of the current script/
2004 */
2005 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002006find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002007{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002008 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002009 int idx;
2010
2011 if (cctx != NULL)
2012 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2013 {
2014 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2015 + idx;
2016
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002017 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2018 : STRLEN(import->imp_name) == len
2019 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002020 return import;
2021 }
2022
2023 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2024 {
2025 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2026
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002027 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2028 : STRLEN(import->imp_name) == len
2029 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002030 return import;
2031 }
2032 return NULL;
2033}
2034
2035/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002036 * Free all imported variables.
2037 */
2038 static void
2039free_imported(cctx_T *cctx)
2040{
2041 int idx;
2042
2043 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2044 {
2045 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2046
2047 vim_free(import->imp_name);
2048 }
2049 ga_clear(&cctx->ctx_imports);
2050}
2051
2052/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002053 * Get the next line of the function from "cctx".
2054 * Returns NULL when at the end.
2055 */
2056 static char_u *
2057next_line_from_context(cctx_T *cctx)
2058{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002059 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002060
2061 do
2062 {
2063 ++cctx->ctx_lnum;
2064 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002065 {
2066 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002067 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002068 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002069 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002070 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002071 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2072 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002073 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002074 return line;
2075}
2076
2077/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002078 * Return TRUE if "p" points at a "#" but not at "#{".
2079 */
2080 static int
2081comment_start(char_u *p)
2082{
2083 return p[0] == '#' && p[1] != '{';
2084}
2085
2086/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002087 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002088 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002089 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2090 */
2091 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002092may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002093{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002094 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002095 {
2096 char_u *next = next_line_from_context(cctx);
2097
2098 if (next == NULL)
2099 return FAIL;
2100 *arg = skipwhite(next);
2101 }
2102 return OK;
2103}
2104
2105/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002106 * Generate an instruction to load script-local variable "name", without the
2107 * leading "s:".
2108 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002109 */
2110 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002111compile_load_scriptvar(
2112 cctx_T *cctx,
2113 char_u *name, // variable NUL terminated
2114 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002115 char_u **end, // end of variable
2116 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002117{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002118 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002119 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2120 imported_T *import;
2121
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002122 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002123 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002124 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002125 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2126 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002127 }
2128 if (idx >= 0)
2129 {
2130 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2131
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002132 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002133 current_sctx.sc_sid, idx, sv->sv_type);
2134 return OK;
2135 }
2136
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002137 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002138 if (import != NULL)
2139 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002140 if (import->imp_all)
2141 {
2142 char_u *p = skipwhite(*end);
2143 int name_len;
2144 ufunc_T *ufunc;
2145 type_T *type;
2146
2147 // Used "import * as Name", need to lookup the member.
2148 if (*p != '.')
2149 {
2150 semsg(_("E1060: expected dot after name: %s"), start);
2151 return FAIL;
2152 }
2153 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002154 if (VIM_ISWHITE(*p))
2155 {
2156 emsg(_("E1074: no white space allowed after dot"));
2157 return FAIL;
2158 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002159
2160 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2161 // TODO: what if it is a function?
2162 if (idx < 0)
2163 return FAIL;
2164 *end = p;
2165
2166 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2167 import->imp_sid,
2168 idx,
2169 type);
2170 }
2171 else
2172 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002173 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002174 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2175 import->imp_sid,
2176 import->imp_var_vals_idx,
2177 import->imp_type);
2178 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002179 return OK;
2180 }
2181
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002182 if (error)
2183 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002184 return FAIL;
2185}
2186
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002187 static int
2188generate_funcref(cctx_T *cctx, char_u *name)
2189{
2190 ufunc_T *ufunc = find_func(name, cctx);
2191
2192 if (ufunc == NULL)
2193 return FAIL;
2194
2195 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2196}
2197
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002198/*
2199 * Compile a variable name into a load instruction.
2200 * "end" points to just after the name.
2201 * When "error" is FALSE do not give an error when not found.
2202 */
2203 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002204compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002205{
2206 type_T *type;
2207 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002208 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002209 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002210 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002211
2212 if (*(*arg + 1) == ':')
2213 {
2214 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002215 if (end <= *arg + 2)
2216 name = vim_strsave((char_u *)"[empty]");
2217 else
2218 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002219 if (name == NULL)
2220 return FAIL;
2221
2222 if (**arg == 'v')
2223 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002224 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002225 }
2226 else if (**arg == 'g')
2227 {
2228 // Global variables can be defined later, thus we don't check if it
2229 // exists, give error at runtime.
2230 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2231 }
2232 else if (**arg == 's')
2233 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002234 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002235 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002236 else if (**arg == 'b')
2237 {
2238 semsg("Namespace b: not supported yet: %s", *arg);
2239 goto theend;
2240 }
2241 else if (**arg == 'w')
2242 {
2243 semsg("Namespace w: not supported yet: %s", *arg);
2244 goto theend;
2245 }
2246 else if (**arg == 't')
2247 {
2248 semsg("Namespace t: not supported yet: %s", *arg);
2249 goto theend;
2250 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002251 else
2252 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002253 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002254 goto theend;
2255 }
2256 }
2257 else
2258 {
2259 size_t len = end - *arg;
2260 int idx;
2261 int gen_load = FALSE;
2262
2263 name = vim_strnsave(*arg, end - *arg);
2264 if (name == NULL)
2265 return FAIL;
2266
2267 idx = lookup_arg(*arg, len, cctx);
2268 if (idx >= 0)
2269 {
2270 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2271 type = cctx->ctx_ufunc->uf_arg_types[idx];
2272 else
2273 type = &t_any;
2274
2275 // Arguments are located above the frame pointer.
2276 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2277 if (cctx->ctx_ufunc->uf_va_name != NULL)
2278 --idx;
2279 gen_load = TRUE;
2280 }
2281 else if (lookup_vararg(*arg, len, cctx))
2282 {
2283 // varargs is always the last argument
2284 idx = -STACK_FRAME_SIZE - 1;
2285 type = cctx->ctx_ufunc->uf_va_type;
2286 gen_load = TRUE;
2287 }
2288 else
2289 {
2290 idx = lookup_local(*arg, len, cctx);
2291 if (idx >= 0)
2292 {
2293 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2294 gen_load = TRUE;
2295 }
2296 else
2297 {
2298 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2299 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2300 res = generate_PUSHBOOL(cctx, **arg == 't'
2301 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002302 else
2303 {
2304 // "var" can be script-local even without using "s:" if it
2305 // already exists.
2306 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2307 == SCRIPT_VERSION_VIM9
2308 || lookup_script(*arg, len) == OK)
2309 res = compile_load_scriptvar(cctx, name, *arg, &end,
2310 FALSE);
2311
2312 // When the name starts with an uppercase letter or "x:" it
2313 // can be a user defined function.
2314 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2315 res = generate_funcref(cctx, name);
2316 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002317 }
2318 }
2319 if (gen_load)
2320 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2321 }
2322
2323 *arg = end;
2324
2325theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002326 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002327 semsg(_(e_var_notfound), name);
2328 vim_free(name);
2329 return res;
2330}
2331
2332/*
2333 * Compile the argument expressions.
2334 * "arg" points to just after the "(" and is advanced to after the ")"
2335 */
2336 static int
2337compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2338{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002339 char_u *p = *arg;
2340 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002341
Bram Moolenaare6085c52020-04-12 20:19:16 +02002342 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002343 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002344 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002345 {
2346 p = next_line_from_context(cctx);
2347 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002348 goto failret;
2349 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002350 p = skipwhite(p);
2351 }
2352 if (*p == ')')
2353 {
2354 *arg = p + 1;
2355 return OK;
2356 }
2357
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002358 if (compile_expr1(&p, cctx) == FAIL)
2359 return FAIL;
2360 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002361
2362 if (*p != ',' && *skipwhite(p) == ',')
2363 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002364 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002365 p = skipwhite(p);
2366 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002367 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002368 {
2369 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002370 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002371 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002372 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002373 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002374 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002375 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002376failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002377 emsg(_(e_missing_close));
2378 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002379}
2380
2381/*
2382 * Compile a function call: name(arg1, arg2)
2383 * "arg" points to "name", "arg + varlen" to the "(".
2384 * "argcount_init" is 1 for "value->method()"
2385 * Instructions:
2386 * EVAL arg1
2387 * EVAL arg2
2388 * BCALL / DCALL / UCALL
2389 */
2390 static int
2391compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2392{
2393 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002394 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395 int argcount = argcount_init;
2396 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002397 char_u fname_buf[FLEN_FIXED + 1];
2398 char_u *tofree = NULL;
2399 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002400 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002401 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002402
2403 if (varlen >= sizeof(namebuf))
2404 {
2405 semsg(_("E1011: name too long: %s"), name);
2406 return FAIL;
2407 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002408 vim_strncpy(namebuf, *arg, varlen);
2409 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002410
2411 *arg = skipwhite(*arg + varlen + 1);
2412 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002413 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002414
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002415 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002416 {
2417 int idx;
2418
2419 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002420 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002421 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002422 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002423 else
2424 semsg(_(e_unknownfunc), namebuf);
2425 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002426 }
2427
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002428 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002429 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002430 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002431 {
2432 res = generate_CALL(cctx, ufunc, argcount);
2433 goto theend;
2434 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002435
2436 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002437 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002438 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002439 if (STRNCMP(namebuf, "g:", 2) != 0
2440 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002441 {
2442 res = generate_PCALL(cctx, argcount, FALSE);
2443 goto theend;
2444 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002445
2446 // The function may be defined only later. Need to figure out at runtime.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002447 res = generate_UCALL(cctx, name, argcount);
2448
2449theend:
2450 vim_free(tofree);
2451 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002452}
2453
2454// like NAMESPACE_CHAR but with 'a' and 'l'.
2455#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2456
2457/*
2458 * Find the end of a variable or function name. Unlike find_name_end() this
2459 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002460 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002461 * Return a pointer to just after the name. Equal to "arg" if there is no
2462 * valid name.
2463 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002464 static char_u *
2465to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002466{
2467 char_u *p;
2468
2469 // Quick check for valid starting character.
2470 if (!eval_isnamec1(*arg))
2471 return arg;
2472
2473 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2474 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2475 // and can be used in slice "[n:]".
2476 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002477 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002478 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2479 break;
2480 return p;
2481}
2482
2483/*
2484 * Like to_name_end() but also skip over a list or dict constant.
2485 */
2486 char_u *
2487to_name_const_end(char_u *arg)
2488{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002489 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002490 typval_T rettv;
2491
2492 if (p == arg && *arg == '[')
2493 {
2494
2495 // Can be "[1, 2, 3]->Func()".
2496 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2497 p = arg;
2498 }
2499 else if (p == arg && *arg == '#' && arg[1] == '{')
2500 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002501 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002502 ++p;
2503 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2504 p = arg;
2505 }
2506 else if (p == arg && *arg == '{')
2507 {
2508 int ret = get_lambda_tv(&p, &rettv, FALSE);
2509
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002510 // Can be "{x -> ret}()".
2511 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002512 if (ret == NOTDONE)
2513 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2514 if (ret != OK)
2515 p = arg;
2516 }
2517
2518 return p;
2519}
2520
2521 static void
2522type_mismatch(type_T *expected, type_T *actual)
2523{
2524 char *tofree1, *tofree2;
2525
2526 semsg(_("E1013: type mismatch, expected %s but got %s"),
2527 type_name(expected, &tofree1), type_name(actual, &tofree2));
2528 vim_free(tofree1);
2529 vim_free(tofree2);
2530}
2531
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002532 static void
2533arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2534{
2535 char *tofree1, *tofree2;
2536
2537 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2538 argidx,
2539 type_name(expected, &tofree1), type_name(actual, &tofree2));
2540 vim_free(tofree1);
2541 vim_free(tofree2);
2542}
2543
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002544/*
2545 * Check if the expected and actual types match.
2546 */
2547 static int
2548check_type(type_T *expected, type_T *actual, int give_msg)
2549{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002550 int ret = OK;
2551
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002552 // When expected is "unknown" we accept any actual type.
2553 // When expected is "any" we accept any actual type except "void".
2554 if (expected->tt_type != VAR_UNKNOWN
2555 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002556 {
2557 if (expected->tt_type != actual->tt_type)
2558 {
2559 if (give_msg)
2560 type_mismatch(expected, actual);
2561 return FAIL;
2562 }
2563 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2564 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002565 // "unknown" is used for an empty list or dict
2566 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002567 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002568 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002569 else if (expected->tt_type == VAR_FUNC)
2570 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002571 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002572 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2573 if (ret == OK && expected->tt_argcount != -1
2574 && (actual->tt_argcount < expected->tt_min_argcount
2575 || actual->tt_argcount > expected->tt_argcount))
2576 ret = FAIL;
2577 }
2578 if (ret == FAIL && give_msg)
2579 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002580 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002581 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002582}
2583
2584/*
2585 * Check that
2586 * - "actual" is "expected" type or
2587 * - "actual" is a type that can be "expected" type: add a runtime check; or
2588 * - return FAIL.
2589 */
2590 static int
2591need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2592{
Bram Moolenaar89228602020-04-05 22:14:54 +02002593 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002594 return OK;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002595 if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002596 {
2597 type_mismatch(expected, actual);
2598 return FAIL;
2599 }
2600 generate_TYPECHECK(cctx, expected, offset);
2601 return OK;
2602}
2603
2604/*
2605 * parse a list: [expr, expr]
2606 * "*arg" points to the '['.
2607 */
2608 static int
2609compile_list(char_u **arg, cctx_T *cctx)
2610{
2611 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002612 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002613 int count = 0;
2614
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002615 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002616 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002617 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002618 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002619 p = next_line_from_context(cctx);
2620 if (p == NULL)
2621 {
2622 semsg(_(e_list_end), *arg);
2623 return FAIL;
2624 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002625 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002626 p = skipwhite(p);
2627 }
2628 if (*p == ']')
2629 {
2630 ++p;
2631 // Allow for following comment, after at least one space.
2632 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2633 p += STRLEN(p);
2634 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002635 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002636 if (compile_expr1(&p, cctx) == FAIL)
2637 break;
2638 ++count;
2639 if (*p == ',')
2640 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002641 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002642 p = skipwhite(p);
2643 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002644 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002645
2646 generate_NEWLIST(cctx, count);
2647 return OK;
2648}
2649
2650/*
2651 * parse a lambda: {arg, arg -> expr}
2652 * "*arg" points to the '{'.
2653 */
2654 static int
2655compile_lambda(char_u **arg, cctx_T *cctx)
2656{
2657 garray_T *instr = &cctx->ctx_instr;
2658 typval_T rettv;
2659 ufunc_T *ufunc;
2660
2661 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002662 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002663 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002664
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002665 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002666 ++ufunc->uf_refcount;
2667 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002668 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002669
2670 // The function will have one line: "return {expr}".
2671 // Compile it into instructions.
2672 compile_def_function(ufunc, TRUE);
2673
2674 if (ufunc->uf_dfunc_idx >= 0)
2675 {
2676 if (ga_grow(instr, 1) == FAIL)
2677 return FAIL;
2678 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2679 return OK;
2680 }
2681 return FAIL;
2682}
2683
2684/*
2685 * Compile a lamda call: expr->{lambda}(args)
2686 * "arg" points to the "{".
2687 */
2688 static int
2689compile_lambda_call(char_u **arg, cctx_T *cctx)
2690{
2691 ufunc_T *ufunc;
2692 typval_T rettv;
2693 int argcount = 1;
2694 int ret = FAIL;
2695
2696 // Get the funcref in "rettv".
2697 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2698 return FAIL;
2699
2700 if (**arg != '(')
2701 {
2702 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002703 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002704 else
2705 semsg(_(e_missing_paren), "lambda");
2706 clear_tv(&rettv);
2707 return FAIL;
2708 }
2709
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002710 ufunc = rettv.vval.v_partial->pt_func;
2711 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002712 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002713 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002714
2715 // The function will have one line: "return {expr}".
2716 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002717 compile_def_function(ufunc, TRUE);
2718
2719 // compile the arguments
2720 *arg = skipwhite(*arg + 1);
2721 if (compile_arguments(arg, cctx, &argcount) == OK)
2722 // call the compiled function
2723 ret = generate_CALL(cctx, ufunc, argcount);
2724
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002725 return ret;
2726}
2727
2728/*
2729 * parse a dict: {'key': val} or #{key: val}
2730 * "*arg" points to the '{'.
2731 */
2732 static int
2733compile_dict(char_u **arg, cctx_T *cctx, int literal)
2734{
2735 garray_T *instr = &cctx->ctx_instr;
2736 int count = 0;
2737 dict_T *d = dict_alloc();
2738 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002739 char_u *whitep = *arg;
2740 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002741
2742 if (d == NULL)
2743 return FAIL;
2744 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002745 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002746 {
2747 char_u *key = NULL;
2748
Bram Moolenaar2c330432020-04-13 14:41:35 +02002749 while (**arg == NUL || (literal && **arg == '"')
2750 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002751 {
2752 *arg = next_line_from_context(cctx);
2753 if (*arg == NULL)
2754 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002755 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002756 *arg = skipwhite(*arg);
2757 }
2758
2759 if (**arg == '}')
2760 break;
2761
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002762 if (literal)
2763 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002764 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002765
Bram Moolenaar2c330432020-04-13 14:41:35 +02002766 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002767 {
2768 semsg(_("E1014: Invalid key: %s"), *arg);
2769 return FAIL;
2770 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002771 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002772 if (generate_PUSHS(cctx, key) == FAIL)
2773 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002774 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002775 }
2776 else
2777 {
2778 isn_T *isn;
2779
2780 if (compile_expr1(arg, cctx) == FAIL)
2781 return FAIL;
2782 // TODO: check type is string
2783 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2784 if (isn->isn_type == ISN_PUSHS)
2785 key = isn->isn_arg.string;
2786 }
2787
2788 // Check for duplicate keys, if using string keys.
2789 if (key != NULL)
2790 {
2791 item = dict_find(d, key, -1);
2792 if (item != NULL)
2793 {
2794 semsg(_(e_duplicate_key), key);
2795 goto failret;
2796 }
2797 item = dictitem_alloc(key);
2798 if (item != NULL)
2799 {
2800 item->di_tv.v_type = VAR_UNKNOWN;
2801 item->di_tv.v_lock = 0;
2802 if (dict_add(d, item) == FAIL)
2803 dictitem_free(item);
2804 }
2805 }
2806
2807 *arg = skipwhite(*arg);
2808 if (**arg != ':')
2809 {
2810 semsg(_(e_missing_dict_colon), *arg);
2811 return FAIL;
2812 }
2813
Bram Moolenaar2c330432020-04-13 14:41:35 +02002814 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002815 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002816 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002817 {
2818 *arg = next_line_from_context(cctx);
2819 if (*arg == NULL)
2820 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002821 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002822 *arg = skipwhite(*arg);
2823 }
2824
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002825 if (compile_expr1(arg, cctx) == FAIL)
2826 return FAIL;
2827 ++count;
2828
Bram Moolenaar2c330432020-04-13 14:41:35 +02002829 whitep = *arg;
2830 p = skipwhite(*arg);
2831 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002832 {
2833 *arg = next_line_from_context(cctx);
2834 if (*arg == NULL)
2835 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002836 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002837 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002838 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002839 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002840 if (**arg == '}')
2841 break;
2842 if (**arg != ',')
2843 {
2844 semsg(_(e_missing_dict_comma), *arg);
2845 goto failret;
2846 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002847 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002848 *arg = skipwhite(*arg + 1);
2849 }
2850
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002851 *arg = *arg + 1;
2852
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002853 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002854 p = skipwhite(*arg);
2855 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002856 *arg += STRLEN(*arg);
2857
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002858 dict_unref(d);
2859 return generate_NEWDICT(cctx, count);
2860
2861failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002862 if (*arg == NULL)
2863 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002864 dict_unref(d);
2865 return FAIL;
2866}
2867
2868/*
2869 * Compile "&option".
2870 */
2871 static int
2872compile_get_option(char_u **arg, cctx_T *cctx)
2873{
2874 typval_T rettv;
2875 char_u *start = *arg;
2876 int ret;
2877
2878 // parse the option and get the current value to get the type.
2879 rettv.v_type = VAR_UNKNOWN;
2880 ret = get_option_tv(arg, &rettv, TRUE);
2881 if (ret == OK)
2882 {
2883 // include the '&' in the name, get_option_tv() expects it.
2884 char_u *name = vim_strnsave(start, *arg - start);
2885 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2886
2887 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2888 vim_free(name);
2889 }
2890 clear_tv(&rettv);
2891
2892 return ret;
2893}
2894
2895/*
2896 * Compile "$VAR".
2897 */
2898 static int
2899compile_get_env(char_u **arg, cctx_T *cctx)
2900{
2901 char_u *start = *arg;
2902 int len;
2903 int ret;
2904 char_u *name;
2905
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002906 ++*arg;
2907 len = get_env_len(arg);
2908 if (len == 0)
2909 {
2910 semsg(_(e_syntax_at), start - 1);
2911 return FAIL;
2912 }
2913
2914 // include the '$' in the name, get_env_tv() expects it.
2915 name = vim_strnsave(start, len + 1);
2916 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2917 vim_free(name);
2918 return ret;
2919}
2920
2921/*
2922 * Compile "@r".
2923 */
2924 static int
2925compile_get_register(char_u **arg, cctx_T *cctx)
2926{
2927 int ret;
2928
2929 ++*arg;
2930 if (**arg == NUL)
2931 {
2932 semsg(_(e_syntax_at), *arg - 1);
2933 return FAIL;
2934 }
2935 if (!valid_yank_reg(**arg, TRUE))
2936 {
2937 emsg_invreg(**arg);
2938 return FAIL;
2939 }
2940 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2941 ++*arg;
2942 return ret;
2943}
2944
2945/*
2946 * Apply leading '!', '-' and '+' to constant "rettv".
2947 */
2948 static int
2949apply_leader(typval_T *rettv, char_u *start, char_u *end)
2950{
2951 char_u *p = end;
2952
2953 // this works from end to start
2954 while (p > start)
2955 {
2956 --p;
2957 if (*p == '-' || *p == '+')
2958 {
2959 // only '-' has an effect, for '+' we only check the type
2960#ifdef FEAT_FLOAT
2961 if (rettv->v_type == VAR_FLOAT)
2962 {
2963 if (*p == '-')
2964 rettv->vval.v_float = -rettv->vval.v_float;
2965 }
2966 else
2967#endif
2968 {
2969 varnumber_T val;
2970 int error = FALSE;
2971
2972 // tv_get_number_chk() accepts a string, but we don't want that
2973 // here
2974 if (check_not_string(rettv) == FAIL)
2975 return FAIL;
2976 val = tv_get_number_chk(rettv, &error);
2977 clear_tv(rettv);
2978 if (error)
2979 return FAIL;
2980 if (*p == '-')
2981 val = -val;
2982 rettv->v_type = VAR_NUMBER;
2983 rettv->vval.v_number = val;
2984 }
2985 }
2986 else
2987 {
2988 int v = tv2bool(rettv);
2989
2990 // '!' is permissive in the type.
2991 clear_tv(rettv);
2992 rettv->v_type = VAR_BOOL;
2993 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
2994 }
2995 }
2996 return OK;
2997}
2998
2999/*
3000 * Recognize v: variables that are constants and set "rettv".
3001 */
3002 static void
3003get_vim_constant(char_u **arg, typval_T *rettv)
3004{
3005 if (STRNCMP(*arg, "v:true", 6) == 0)
3006 {
3007 rettv->v_type = VAR_BOOL;
3008 rettv->vval.v_number = VVAL_TRUE;
3009 *arg += 6;
3010 }
3011 else if (STRNCMP(*arg, "v:false", 7) == 0)
3012 {
3013 rettv->v_type = VAR_BOOL;
3014 rettv->vval.v_number = VVAL_FALSE;
3015 *arg += 7;
3016 }
3017 else if (STRNCMP(*arg, "v:null", 6) == 0)
3018 {
3019 rettv->v_type = VAR_SPECIAL;
3020 rettv->vval.v_number = VVAL_NULL;
3021 *arg += 6;
3022 }
3023 else if (STRNCMP(*arg, "v:none", 6) == 0)
3024 {
3025 rettv->v_type = VAR_SPECIAL;
3026 rettv->vval.v_number = VVAL_NONE;
3027 *arg += 6;
3028 }
3029}
3030
3031/*
3032 * Compile code to apply '-', '+' and '!'.
3033 */
3034 static int
3035compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3036{
3037 char_u *p = end;
3038
3039 // this works from end to start
3040 while (p > start)
3041 {
3042 --p;
3043 if (*p == '-' || *p == '+')
3044 {
3045 int negate = *p == '-';
3046 isn_T *isn;
3047
3048 // TODO: check type
3049 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3050 {
3051 --p;
3052 if (*p == '-')
3053 negate = !negate;
3054 }
3055 // only '-' has an effect, for '+' we only check the type
3056 if (negate)
3057 isn = generate_instr(cctx, ISN_NEGATENR);
3058 else
3059 isn = generate_instr(cctx, ISN_CHECKNR);
3060 if (isn == NULL)
3061 return FAIL;
3062 }
3063 else
3064 {
3065 int invert = TRUE;
3066
3067 while (p > start && p[-1] == '!')
3068 {
3069 --p;
3070 invert = !invert;
3071 }
3072 if (generate_2BOOL(cctx, invert) == FAIL)
3073 return FAIL;
3074 }
3075 }
3076 return OK;
3077}
3078
3079/*
3080 * Compile whatever comes after "name" or "name()".
3081 */
3082 static int
3083compile_subscript(
3084 char_u **arg,
3085 cctx_T *cctx,
3086 char_u **start_leader,
3087 char_u *end_leader)
3088{
3089 for (;;)
3090 {
3091 if (**arg == '(')
3092 {
3093 int argcount = 0;
3094
3095 // funcref(arg)
3096 *arg = skipwhite(*arg + 1);
3097 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3098 return FAIL;
3099 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
3100 return FAIL;
3101 }
3102 else if (**arg == '-' && (*arg)[1] == '>')
3103 {
3104 char_u *p;
3105
3106 // something->method()
3107 // Apply the '!', '-' and '+' first:
3108 // -1.0->func() works like (-1.0)->func()
3109 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3110 return FAIL;
3111 *start_leader = end_leader; // don't apply again later
3112
3113 *arg = skipwhite(*arg + 2);
3114 if (**arg == '{')
3115 {
3116 // lambda call: list->{lambda}
3117 if (compile_lambda_call(arg, cctx) == FAIL)
3118 return FAIL;
3119 }
3120 else
3121 {
3122 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003123 p = *arg;
3124 if (ASCII_ISALPHA(*p) && p[1] == ':')
3125 p += 2;
3126 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003127 ;
3128 if (*p != '(')
3129 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003130 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003131 return FAIL;
3132 }
3133 // TODO: base value may not be the first argument
3134 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3135 return FAIL;
3136 }
3137 }
3138 else if (**arg == '[')
3139 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003140 garray_T *stack;
3141 type_T **typep;
3142
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003143 // list index: list[123]
3144 // TODO: more arguments
3145 // TODO: dict member dict['name']
3146 *arg = skipwhite(*arg + 1);
3147 if (compile_expr1(arg, cctx) == FAIL)
3148 return FAIL;
3149
3150 if (**arg != ']')
3151 {
3152 emsg(_(e_missbrac));
3153 return FAIL;
3154 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003155 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003156
3157 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3158 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003159 stack = &cctx->ctx_type_stack;
3160 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3161 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3162 {
3163 emsg(_(e_listreq));
3164 return FAIL;
3165 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003166 if ((*typep)->tt_type == VAR_LIST)
3167 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003168 }
3169 else if (**arg == '.' && (*arg)[1] != '.')
3170 {
3171 char_u *p;
3172
3173 ++*arg;
3174 p = *arg;
3175 // dictionary member: dict.name
3176 if (eval_isnamec1(*p))
3177 while (eval_isnamec(*p))
3178 MB_PTR_ADV(p);
3179 if (p == *arg)
3180 {
3181 semsg(_(e_syntax_at), *arg);
3182 return FAIL;
3183 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003184 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3185 return FAIL;
3186 *arg = p;
3187 }
3188 else
3189 break;
3190 }
3191
3192 // TODO - see handle_subscript():
3193 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3194 // Don't do this when "Func" is already a partial that was bound
3195 // explicitly (pt_auto is FALSE).
3196
3197 return OK;
3198}
3199
3200/*
3201 * Compile an expression at "*p" and add instructions to "instr".
3202 * "p" is advanced until after the expression, skipping white space.
3203 *
3204 * This is the equivalent of eval1(), eval2(), etc.
3205 */
3206
3207/*
3208 * number number constant
3209 * 0zFFFFFFFF Blob constant
3210 * "string" string constant
3211 * 'string' literal string constant
3212 * &option-name option value
3213 * @r register contents
3214 * identifier variable value
3215 * function() function call
3216 * $VAR environment variable
3217 * (expression) nested expression
3218 * [expr, expr] List
3219 * {key: val, key: val} Dictionary
3220 * #{key: val, key: val} Dictionary with literal keys
3221 *
3222 * Also handle:
3223 * ! in front logical NOT
3224 * - in front unary minus
3225 * + in front unary plus (ignored)
3226 * trailing (arg) funcref/partial call
3227 * trailing [] subscript in String or List
3228 * trailing .name entry in Dictionary
3229 * trailing ->name() method call
3230 */
3231 static int
3232compile_expr7(char_u **arg, cctx_T *cctx)
3233{
3234 typval_T rettv;
3235 char_u *start_leader, *end_leader;
3236 int ret = OK;
3237
3238 /*
3239 * Skip '!', '-' and '+' characters. They are handled later.
3240 */
3241 start_leader = *arg;
3242 while (**arg == '!' || **arg == '-' || **arg == '+')
3243 *arg = skipwhite(*arg + 1);
3244 end_leader = *arg;
3245
3246 rettv.v_type = VAR_UNKNOWN;
3247 switch (**arg)
3248 {
3249 /*
3250 * Number constant.
3251 */
3252 case '0': // also for blob starting with 0z
3253 case '1':
3254 case '2':
3255 case '3':
3256 case '4':
3257 case '5':
3258 case '6':
3259 case '7':
3260 case '8':
3261 case '9':
3262 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3263 return FAIL;
3264 break;
3265
3266 /*
3267 * String constant: "string".
3268 */
3269 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3270 return FAIL;
3271 break;
3272
3273 /*
3274 * Literal string constant: 'str''ing'.
3275 */
3276 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3277 return FAIL;
3278 break;
3279
3280 /*
3281 * Constant Vim variable.
3282 */
3283 case 'v': get_vim_constant(arg, &rettv);
3284 ret = NOTDONE;
3285 break;
3286
3287 /*
3288 * List: [expr, expr]
3289 */
3290 case '[': ret = compile_list(arg, cctx);
3291 break;
3292
3293 /*
3294 * Dictionary: #{key: val, key: val}
3295 */
3296 case '#': if ((*arg)[1] == '{')
3297 {
3298 ++*arg;
3299 ret = compile_dict(arg, cctx, TRUE);
3300 }
3301 else
3302 ret = NOTDONE;
3303 break;
3304
3305 /*
3306 * Lambda: {arg, arg -> expr}
3307 * Dictionary: {'key': val, 'key': val}
3308 */
3309 case '{': {
3310 char_u *start = skipwhite(*arg + 1);
3311
3312 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003313 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003314 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003315 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003316 if (ret != FAIL && *start == '>')
3317 ret = compile_lambda(arg, cctx);
3318 else
3319 ret = compile_dict(arg, cctx, FALSE);
3320 }
3321 break;
3322
3323 /*
3324 * Option value: &name
3325 */
3326 case '&': ret = compile_get_option(arg, cctx);
3327 break;
3328
3329 /*
3330 * Environment variable: $VAR.
3331 */
3332 case '$': ret = compile_get_env(arg, cctx);
3333 break;
3334
3335 /*
3336 * Register contents: @r.
3337 */
3338 case '@': ret = compile_get_register(arg, cctx);
3339 break;
3340 /*
3341 * nested expression: (expression).
3342 */
3343 case '(': *arg = skipwhite(*arg + 1);
3344 ret = compile_expr1(arg, cctx); // recursive!
3345 *arg = skipwhite(*arg);
3346 if (**arg == ')')
3347 ++*arg;
3348 else if (ret == OK)
3349 {
3350 emsg(_(e_missing_close));
3351 ret = FAIL;
3352 }
3353 break;
3354
3355 default: ret = NOTDONE;
3356 break;
3357 }
3358 if (ret == FAIL)
3359 return FAIL;
3360
3361 if (rettv.v_type != VAR_UNKNOWN)
3362 {
3363 // apply the '!', '-' and '+' before the constant
3364 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3365 {
3366 clear_tv(&rettv);
3367 return FAIL;
3368 }
3369 start_leader = end_leader; // don't apply again below
3370
3371 // push constant
3372 switch (rettv.v_type)
3373 {
3374 case VAR_BOOL:
3375 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3376 break;
3377 case VAR_SPECIAL:
3378 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3379 break;
3380 case VAR_NUMBER:
3381 generate_PUSHNR(cctx, rettv.vval.v_number);
3382 break;
3383#ifdef FEAT_FLOAT
3384 case VAR_FLOAT:
3385 generate_PUSHF(cctx, rettv.vval.v_float);
3386 break;
3387#endif
3388 case VAR_BLOB:
3389 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3390 rettv.vval.v_blob = NULL;
3391 break;
3392 case VAR_STRING:
3393 generate_PUSHS(cctx, rettv.vval.v_string);
3394 rettv.vval.v_string = NULL;
3395 break;
3396 default:
3397 iemsg("constant type missing");
3398 return FAIL;
3399 }
3400 }
3401 else if (ret == NOTDONE)
3402 {
3403 char_u *p;
3404 int r;
3405
3406 if (!eval_isnamec1(**arg))
3407 {
3408 semsg(_("E1015: Name expected: %s"), *arg);
3409 return FAIL;
3410 }
3411
3412 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003413 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003414 if (*p == '(')
3415 r = compile_call(arg, p - *arg, cctx, 0);
3416 else
3417 r = compile_load(arg, p, cctx, TRUE);
3418 if (r == FAIL)
3419 return FAIL;
3420 }
3421
3422 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3423 return FAIL;
3424
3425 // Now deal with prefixed '-', '+' and '!', if not done already.
3426 return compile_leader(cctx, start_leader, end_leader);
3427}
3428
3429/*
3430 * * number multiplication
3431 * / number division
3432 * % number modulo
3433 */
3434 static int
3435compile_expr6(char_u **arg, cctx_T *cctx)
3436{
3437 char_u *op;
3438
3439 // get the first variable
3440 if (compile_expr7(arg, cctx) == FAIL)
3441 return FAIL;
3442
3443 /*
3444 * Repeat computing, until no "*", "/" or "%" is following.
3445 */
3446 for (;;)
3447 {
3448 op = skipwhite(*arg);
3449 if (*op != '*' && *op != '/' && *op != '%')
3450 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003451 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003452 {
3453 char_u buf[3];
3454
3455 vim_strncpy(buf, op, 1);
3456 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003457 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003458 }
3459 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003460 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003461 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003462
3463 // get the second variable
3464 if (compile_expr7(arg, cctx) == FAIL)
3465 return FAIL;
3466
3467 generate_two_op(cctx, op);
3468 }
3469
3470 return OK;
3471}
3472
3473/*
3474 * + number addition
3475 * - number subtraction
3476 * .. string concatenation
3477 */
3478 static int
3479compile_expr5(char_u **arg, cctx_T *cctx)
3480{
3481 char_u *op;
3482 int oplen;
3483
3484 // get the first variable
3485 if (compile_expr6(arg, cctx) == FAIL)
3486 return FAIL;
3487
3488 /*
3489 * Repeat computing, until no "+", "-" or ".." is following.
3490 */
3491 for (;;)
3492 {
3493 op = skipwhite(*arg);
3494 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3495 break;
3496 oplen = (*op == '.' ? 2 : 1);
3497
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003498 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003499 {
3500 char_u buf[3];
3501
3502 vim_strncpy(buf, op, oplen);
3503 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003504 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003505 }
3506
3507 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003508 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003509 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003510
3511 // get the second variable
3512 if (compile_expr6(arg, cctx) == FAIL)
3513 return FAIL;
3514
3515 if (*op == '.')
3516 {
3517 if (may_generate_2STRING(-2, cctx) == FAIL
3518 || may_generate_2STRING(-1, cctx) == FAIL)
3519 return FAIL;
3520 generate_instr_drop(cctx, ISN_CONCAT, 1);
3521 }
3522 else
3523 generate_two_op(cctx, op);
3524 }
3525
3526 return OK;
3527}
3528
Bram Moolenaar080457c2020-03-03 21:53:32 +01003529 static exptype_T
3530get_compare_type(char_u *p, int *len, int *type_is)
3531{
3532 exptype_T type = EXPR_UNKNOWN;
3533 int i;
3534
3535 switch (p[0])
3536 {
3537 case '=': if (p[1] == '=')
3538 type = EXPR_EQUAL;
3539 else if (p[1] == '~')
3540 type = EXPR_MATCH;
3541 break;
3542 case '!': if (p[1] == '=')
3543 type = EXPR_NEQUAL;
3544 else if (p[1] == '~')
3545 type = EXPR_NOMATCH;
3546 break;
3547 case '>': if (p[1] != '=')
3548 {
3549 type = EXPR_GREATER;
3550 *len = 1;
3551 }
3552 else
3553 type = EXPR_GEQUAL;
3554 break;
3555 case '<': if (p[1] != '=')
3556 {
3557 type = EXPR_SMALLER;
3558 *len = 1;
3559 }
3560 else
3561 type = EXPR_SEQUAL;
3562 break;
3563 case 'i': if (p[1] == 's')
3564 {
3565 // "is" and "isnot"; but not a prefix of a name
3566 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3567 *len = 5;
3568 i = p[*len];
3569 if (!isalnum(i) && i != '_')
3570 {
3571 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3572 *type_is = TRUE;
3573 }
3574 }
3575 break;
3576 }
3577 return type;
3578}
3579
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003580/*
3581 * expr5a == expr5b
3582 * expr5a =~ expr5b
3583 * expr5a != expr5b
3584 * expr5a !~ expr5b
3585 * expr5a > expr5b
3586 * expr5a >= expr5b
3587 * expr5a < expr5b
3588 * expr5a <= expr5b
3589 * expr5a is expr5b
3590 * expr5a isnot expr5b
3591 *
3592 * Produces instructions:
3593 * EVAL expr5a Push result of "expr5a"
3594 * EVAL expr5b Push result of "expr5b"
3595 * COMPARE one of the compare instructions
3596 */
3597 static int
3598compile_expr4(char_u **arg, cctx_T *cctx)
3599{
3600 exptype_T type = EXPR_UNKNOWN;
3601 char_u *p;
3602 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003603 int type_is = FALSE;
3604
3605 // get the first variable
3606 if (compile_expr5(arg, cctx) == FAIL)
3607 return FAIL;
3608
3609 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003610 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003611
3612 /*
3613 * If there is a comparative operator, use it.
3614 */
3615 if (type != EXPR_UNKNOWN)
3616 {
3617 int ic = FALSE; // Default: do not ignore case
3618
3619 if (type_is && (p[len] == '?' || p[len] == '#'))
3620 {
3621 semsg(_(e_invexpr2), *arg);
3622 return FAIL;
3623 }
3624 // extra question mark appended: ignore case
3625 if (p[len] == '?')
3626 {
3627 ic = TRUE;
3628 ++len;
3629 }
3630 // extra '#' appended: match case (ignored)
3631 else if (p[len] == '#')
3632 ++len;
3633 // nothing appended: match case
3634
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003635 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003636 {
3637 char_u buf[7];
3638
3639 vim_strncpy(buf, p, len);
3640 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003641 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003642 }
3643
3644 // get the second variable
3645 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003646 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003647 return FAIL;
3648
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003649 if (compile_expr5(arg, cctx) == FAIL)
3650 return FAIL;
3651
3652 generate_COMPARE(cctx, type, ic);
3653 }
3654
3655 return OK;
3656}
3657
3658/*
3659 * Compile || or &&.
3660 */
3661 static int
3662compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3663{
3664 char_u *p = skipwhite(*arg);
3665 int opchar = *op;
3666
3667 if (p[0] == opchar && p[1] == opchar)
3668 {
3669 garray_T *instr = &cctx->ctx_instr;
3670 garray_T end_ga;
3671
3672 /*
3673 * Repeat until there is no following "||" or "&&"
3674 */
3675 ga_init2(&end_ga, sizeof(int), 10);
3676 while (p[0] == opchar && p[1] == opchar)
3677 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003678 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3679 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003680 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003681 return FAIL;
3682 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003683
3684 if (ga_grow(&end_ga, 1) == FAIL)
3685 {
3686 ga_clear(&end_ga);
3687 return FAIL;
3688 }
3689 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3690 ++end_ga.ga_len;
3691 generate_JUMP(cctx, opchar == '|'
3692 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3693
3694 // eval the next expression
3695 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003696 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003697 return FAIL;
3698
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003699 if ((opchar == '|' ? compile_expr3(arg, cctx)
3700 : compile_expr4(arg, cctx)) == FAIL)
3701 {
3702 ga_clear(&end_ga);
3703 return FAIL;
3704 }
3705 p = skipwhite(*arg);
3706 }
3707
3708 // Fill in the end label in all jumps.
3709 while (end_ga.ga_len > 0)
3710 {
3711 isn_T *isn;
3712
3713 --end_ga.ga_len;
3714 isn = ((isn_T *)instr->ga_data)
3715 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3716 isn->isn_arg.jump.jump_where = instr->ga_len;
3717 }
3718 ga_clear(&end_ga);
3719 }
3720
3721 return OK;
3722}
3723
3724/*
3725 * expr4a && expr4a && expr4a logical AND
3726 *
3727 * Produces instructions:
3728 * EVAL expr4a Push result of "expr4a"
3729 * JUMP_AND_KEEP_IF_FALSE end
3730 * EVAL expr4b Push result of "expr4b"
3731 * JUMP_AND_KEEP_IF_FALSE end
3732 * EVAL expr4c Push result of "expr4c"
3733 * end:
3734 */
3735 static int
3736compile_expr3(char_u **arg, cctx_T *cctx)
3737{
3738 // get the first variable
3739 if (compile_expr4(arg, cctx) == FAIL)
3740 return FAIL;
3741
3742 // || and && work almost the same
3743 return compile_and_or(arg, cctx, "&&");
3744}
3745
3746/*
3747 * expr3a || expr3b || expr3c logical OR
3748 *
3749 * Produces instructions:
3750 * EVAL expr3a Push result of "expr3a"
3751 * JUMP_AND_KEEP_IF_TRUE end
3752 * EVAL expr3b Push result of "expr3b"
3753 * JUMP_AND_KEEP_IF_TRUE end
3754 * EVAL expr3c Push result of "expr3c"
3755 * end:
3756 */
3757 static int
3758compile_expr2(char_u **arg, cctx_T *cctx)
3759{
3760 // eval the first expression
3761 if (compile_expr3(arg, cctx) == FAIL)
3762 return FAIL;
3763
3764 // || and && work almost the same
3765 return compile_and_or(arg, cctx, "||");
3766}
3767
3768/*
3769 * Toplevel expression: expr2 ? expr1a : expr1b
3770 *
3771 * Produces instructions:
3772 * EVAL expr2 Push result of "expr"
3773 * JUMP_IF_FALSE alt jump if false
3774 * EVAL expr1a
3775 * JUMP_ALWAYS end
3776 * alt: EVAL expr1b
3777 * end:
3778 */
3779 static int
3780compile_expr1(char_u **arg, cctx_T *cctx)
3781{
3782 char_u *p;
3783
3784 // evaluate the first expression
3785 if (compile_expr2(arg, cctx) == FAIL)
3786 return FAIL;
3787
3788 p = skipwhite(*arg);
3789 if (*p == '?')
3790 {
3791 garray_T *instr = &cctx->ctx_instr;
3792 garray_T *stack = &cctx->ctx_type_stack;
3793 int alt_idx = instr->ga_len;
3794 int end_idx;
3795 isn_T *isn;
3796 type_T *type1;
3797 type_T *type2;
3798
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003799 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3800 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003801 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003802 return FAIL;
3803 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003804
3805 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3806
3807 // evaluate the second expression; any type is accepted
3808 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003809 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003810 return FAIL;
3811
Bram Moolenaara6d53682020-01-28 23:04:06 +01003812 if (compile_expr1(arg, cctx) == FAIL)
3813 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003814
3815 // remember the type and drop it
3816 --stack->ga_len;
3817 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3818
3819 end_idx = instr->ga_len;
3820 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3821
3822 // jump here from JUMP_IF_FALSE
3823 isn = ((isn_T *)instr->ga_data) + alt_idx;
3824 isn->isn_arg.jump.jump_where = instr->ga_len;
3825
3826 // Check for the ":".
3827 p = skipwhite(*arg);
3828 if (*p != ':')
3829 {
3830 emsg(_(e_missing_colon));
3831 return FAIL;
3832 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003833 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3834 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003835 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003836 return FAIL;
3837 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003838
3839 // evaluate the third expression
3840 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003841 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003842 return FAIL;
3843
Bram Moolenaara6d53682020-01-28 23:04:06 +01003844 if (compile_expr1(arg, cctx) == FAIL)
3845 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003846
3847 // If the types differ, the result has a more generic type.
3848 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003849 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003850
3851 // jump here from JUMP_ALWAYS
3852 isn = ((isn_T *)instr->ga_data) + end_idx;
3853 isn->isn_arg.jump.jump_where = instr->ga_len;
3854 }
3855 return OK;
3856}
3857
3858/*
3859 * compile "return [expr]"
3860 */
3861 static char_u *
3862compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3863{
3864 char_u *p = arg;
3865 garray_T *stack = &cctx->ctx_type_stack;
3866 type_T *stack_type;
3867
3868 if (*p != NUL && *p != '|' && *p != '\n')
3869 {
3870 // compile return argument into instructions
3871 if (compile_expr1(&p, cctx) == FAIL)
3872 return NULL;
3873
3874 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3875 if (set_return_type)
3876 cctx->ctx_ufunc->uf_ret_type = stack_type;
3877 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3878 == FAIL)
3879 return NULL;
3880 }
3881 else
3882 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003883 // "set_return_type" cannot be TRUE, only used for a lambda which
3884 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003885 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3886 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003887 {
3888 emsg(_("E1003: Missing return value"));
3889 return NULL;
3890 }
3891
3892 // No argument, return zero.
3893 generate_PUSHNR(cctx, 0);
3894 }
3895
3896 if (generate_instr(cctx, ISN_RETURN) == NULL)
3897 return NULL;
3898
3899 // "return val | endif" is possible
3900 return skipwhite(p);
3901}
3902
3903/*
3904 * Return the length of an assignment operator, or zero if there isn't one.
3905 */
3906 int
3907assignment_len(char_u *p, int *heredoc)
3908{
3909 if (*p == '=')
3910 {
3911 if (p[1] == '<' && p[2] == '<')
3912 {
3913 *heredoc = TRUE;
3914 return 3;
3915 }
3916 return 1;
3917 }
3918 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3919 return 2;
3920 if (STRNCMP(p, "..=", 3) == 0)
3921 return 3;
3922 return 0;
3923}
3924
3925// words that cannot be used as a variable
3926static char *reserved[] = {
3927 "true",
3928 "false",
3929 NULL
3930};
3931
3932/*
3933 * Get a line for "=<<".
3934 * Return a pointer to the line in allocated memory.
3935 * Return NULL for end-of-file or some error.
3936 */
3937 static char_u *
3938heredoc_getline(
3939 int c UNUSED,
3940 void *cookie,
3941 int indent UNUSED,
3942 int do_concat UNUSED)
3943{
3944 cctx_T *cctx = (cctx_T *)cookie;
3945
3946 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003947 {
3948 iemsg("Heredoc got to end");
3949 return NULL;
3950 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003951 ++cctx->ctx_lnum;
3952 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3953 [cctx->ctx_lnum]);
3954}
3955
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003956typedef enum {
3957 dest_local,
3958 dest_option,
3959 dest_env,
3960 dest_global,
3961 dest_vimvar,
3962 dest_script,
3963 dest_reg,
3964} assign_dest_T;
3965
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003966/*
3967 * compile "let var [= expr]", "const var = expr" and "var = expr"
3968 * "arg" points to "var".
3969 */
3970 static char_u *
3971compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3972{
3973 char_u *p;
3974 char_u *ret = NULL;
3975 int var_count = 0;
3976 int semicolon = 0;
3977 size_t varlen;
3978 garray_T *instr = &cctx->ctx_instr;
3979 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02003980 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003981 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003982 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003983 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003984 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01003985 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003986 int oplen = 0;
3987 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02003988 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003989 lvar_T *lvar;
3990 char_u *name;
3991 char_u *sp;
3992 int has_type = FALSE;
3993 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
3994 int instr_count = -1;
3995
3996 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
3997 if (p == NULL)
3998 return NULL;
3999 if (var_count > 0)
4000 {
4001 // TODO: let [var, var] = list
4002 emsg("Cannot handle a list yet");
4003 return NULL;
4004 }
4005
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004006 // "a: type" is declaring variable "a" with a type, not "a:".
4007 if (is_decl && p == arg + 2 && p[-1] == ':')
4008 --p;
4009
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004010 varlen = p - arg;
4011 name = vim_strnsave(arg, (int)varlen);
4012 if (name == NULL)
4013 return NULL;
4014
Bram Moolenaar080457c2020-03-03 21:53:32 +01004015 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004016 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004017 if (*arg == '&')
4018 {
4019 int cc;
4020 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004021
Bram Moolenaar080457c2020-03-03 21:53:32 +01004022 dest = dest_option;
4023 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004024 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004025 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004026 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004027 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004028 if (is_decl)
4029 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004030 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004031 goto theend;
4032 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004033 p = arg;
4034 p = find_option_end(&p, &opt_flags);
4035 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004036 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004037 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004038 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004039 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004040 }
4041 cc = *p;
4042 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004043 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004044 *p = cc;
4045 if (opt_type == -3)
4046 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004047 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004048 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004049 }
4050 if (opt_type == -2 || opt_type == 0)
4051 type = &t_string;
4052 else
4053 type = &t_number; // both number and boolean option
4054 }
4055 else if (*arg == '$')
4056 {
4057 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004058 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004059 if (is_decl)
4060 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004061 semsg(_("E1065: Cannot declare an environment variable: %s"),
4062 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004063 goto theend;
4064 }
4065 }
4066 else if (*arg == '@')
4067 {
4068 if (!valid_yank_reg(arg[1], TRUE))
4069 {
4070 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004071 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004072 }
4073 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004074 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004075 if (is_decl)
4076 {
4077 semsg(_("E1066: Cannot declare a register: %s"), name);
4078 goto theend;
4079 }
4080 }
4081 else if (STRNCMP(arg, "g:", 2) == 0)
4082 {
4083 dest = dest_global;
4084 if (is_decl)
4085 {
4086 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4087 goto theend;
4088 }
4089 }
4090 else if (STRNCMP(arg, "v:", 2) == 0)
4091 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004092 typval_T *vtv;
4093 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004094
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004095 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004096 if (vimvaridx < 0)
4097 {
4098 semsg(_(e_var_notfound), arg);
4099 goto theend;
4100 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004101 // We use the current value of "sandbox" here, is that OK?
4102 if (var_check_ro(di_flags, name, FALSE))
4103 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004104 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004105 vtv = get_vim_var_tv(vimvaridx);
4106 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004107 if (is_decl)
4108 {
4109 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4110 goto theend;
4111 }
4112 }
4113 else
4114 {
4115 for (idx = 0; reserved[idx] != NULL; ++idx)
4116 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004117 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004118 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004119 goto theend;
4120 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004121
4122 idx = lookup_local(arg, varlen, cctx);
4123 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004124 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004125 if (is_decl)
4126 {
4127 semsg(_("E1017: Variable already declared: %s"), name);
4128 goto theend;
4129 }
4130 else
4131 {
4132 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4133 if (lvar->lv_const)
4134 {
4135 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4136 goto theend;
4137 }
4138 }
4139 }
4140 else if (STRNCMP(arg, "s:", 2) == 0
4141 || lookup_script(arg, varlen) == OK
4142 || find_imported(arg, varlen, cctx) != NULL)
4143 {
4144 dest = dest_script;
4145 if (is_decl)
4146 {
4147 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004148 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004149 goto theend;
4150 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004151 }
4152 }
4153 }
4154
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004155 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004156 {
4157 if (is_decl && *p == ':')
4158 {
4159 // parse optional type: "let var: type = expr"
4160 p = skipwhite(p + 1);
4161 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004162 has_type = TRUE;
4163 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004164 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004165 {
4166 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4167 type = lvar->lv_type;
4168 }
4169 }
4170
4171 sp = p;
4172 p = skipwhite(p);
4173 op = p;
4174 oplen = assignment_len(p, &heredoc);
4175 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4176 {
4177 char_u buf[4];
4178
4179 vim_strncpy(buf, op, oplen);
4180 semsg(_(e_white_both), buf);
4181 }
4182
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004183 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004184 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004185 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004186 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004187 goto theend;
4188 }
4189
Bram Moolenaar080457c2020-03-03 21:53:32 +01004190 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004191 {
4192 if (oplen > 1 && !heredoc)
4193 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004194 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004195 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4196 name);
4197 goto theend;
4198 }
4199
4200 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004201 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004202 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004203 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4204 if (idx < 0)
4205 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004206 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004207 }
4208
4209 if (heredoc)
4210 {
4211 list_T *l;
4212 listitem_T *li;
4213
4214 // [let] varname =<< [trim] {end}
4215 eap->getline = heredoc_getline;
4216 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004217 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004218
4219 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004220 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004221 {
4222 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4223 li->li_tv.vval.v_string = NULL;
4224 }
4225 generate_NEWLIST(cctx, l->lv_len);
4226 type = &t_list_string;
4227 list_free(l);
4228 p += STRLEN(p);
4229 }
4230 else if (oplen > 0)
4231 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004232 int r;
4233 type_T *stacktype;
4234 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004235
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004236 // for "+=", "*=", "..=" etc. first load the current value
4237 if (*op != '=')
4238 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004239 switch (dest)
4240 {
4241 case dest_option:
4242 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004243 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004244 break;
4245 case dest_global:
4246 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4247 break;
4248 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004249 compile_load_scriptvar(cctx,
4250 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004251 break;
4252 case dest_env:
4253 // Include $ in the name here
4254 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4255 break;
4256 case dest_reg:
4257 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4258 break;
4259 case dest_vimvar:
4260 generate_LOADV(cctx, name + 2, TRUE);
4261 break;
4262 case dest_local:
4263 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4264 break;
4265 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004266 }
4267
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004268 // Compile the expression. Temporarily hide the new local variable
4269 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004270 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004271 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004272 instr_count = instr->ga_len;
4273 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004274 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004275 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004276 ++cctx->ctx_locals.ga_len;
4277 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004278 goto theend;
4279
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004280 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004281 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004282 stack = &cctx->ctx_type_stack;
4283 stacktype = stack->ga_len == 0 ? &t_void
4284 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4285 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004286 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004287 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4288 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004289 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004290 if (stacktype->tt_type == VAR_VOID)
4291 {
4292 emsg(_("E1031: Cannot use void value"));
4293 goto theend;
4294 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004295 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004296 {
4297 // An empty list or dict has a &t_void member, for a
4298 // variable that implies &t_any.
4299 if (stacktype == &t_list_empty)
4300 lvar->lv_type = &t_list_any;
4301 else if (stacktype == &t_dict_empty)
4302 lvar->lv_type = &t_dict_any;
4303 else
4304 lvar->lv_type = stacktype;
4305 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004306 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004307 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4308 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004309 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004310 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004311 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004312 }
4313 }
4314 else if (cmdidx == CMD_const)
4315 {
4316 emsg(_("E1021: const requires a value"));
4317 goto theend;
4318 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004319 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004320 {
4321 emsg(_("E1022: type or initialization required"));
4322 goto theend;
4323 }
4324 else
4325 {
4326 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004327 if (ga_grow(instr, 1) == FAIL)
4328 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004329 switch (type->tt_type)
4330 {
4331 case VAR_BOOL:
4332 generate_PUSHBOOL(cctx, VVAL_FALSE);
4333 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004334 case VAR_FLOAT:
4335#ifdef FEAT_FLOAT
4336 generate_PUSHF(cctx, 0.0);
4337#endif
4338 break;
4339 case VAR_STRING:
4340 generate_PUSHS(cctx, NULL);
4341 break;
4342 case VAR_BLOB:
4343 generate_PUSHBLOB(cctx, NULL);
4344 break;
4345 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004346 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004347 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004348 case VAR_LIST:
4349 generate_NEWLIST(cctx, 0);
4350 break;
4351 case VAR_DICT:
4352 generate_NEWDICT(cctx, 0);
4353 break;
4354 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004355 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004356 break;
4357 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004358 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004359 break;
4360 case VAR_NUMBER:
4361 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004362 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004363 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004364 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004365 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004366 generate_PUSHNR(cctx, 0);
4367 break;
4368 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004369 }
4370
4371 if (oplen > 0 && *op != '=')
4372 {
4373 type_T *expected = &t_number;
4374 garray_T *stack = &cctx->ctx_type_stack;
4375 type_T *stacktype;
4376
4377 // TODO: if type is known use float or any operation
4378
4379 if (*op == '.')
4380 expected = &t_string;
4381 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4382 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4383 goto theend;
4384
4385 if (*op == '.')
4386 generate_instr_drop(cctx, ISN_CONCAT, 1);
4387 else
4388 {
4389 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4390
4391 if (isn == NULL)
4392 goto theend;
4393 switch (*op)
4394 {
4395 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4396 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4397 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4398 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4399 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4400 }
4401 }
4402 }
4403
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004404 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004405 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004406 case dest_option:
4407 generate_STOREOPT(cctx, name + 1, opt_flags);
4408 break;
4409 case dest_global:
4410 // include g: with the name, easier to execute that way
4411 generate_STORE(cctx, ISN_STOREG, 0, name);
4412 break;
4413 case dest_env:
4414 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4415 break;
4416 case dest_reg:
4417 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4418 break;
4419 case dest_vimvar:
4420 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4421 break;
4422 case dest_script:
4423 {
4424 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4425 imported_T *import = NULL;
4426 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004427
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004428 if (name[1] != ':')
4429 {
4430 import = find_imported(name, 0, cctx);
4431 if (import != NULL)
4432 sid = import->imp_sid;
4433 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004434
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004435 idx = get_script_item_idx(sid, rawname, TRUE);
4436 // TODO: specific type
4437 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004438 {
4439 char_u *name_s = name;
4440
4441 // Include s: in the name for store_var()
4442 if (name[1] != ':')
4443 {
4444 int len = (int)STRLEN(name) + 3;
4445
4446 name_s = alloc(len);
4447 if (name_s == NULL)
4448 name_s = name;
4449 else
4450 vim_snprintf((char *)name_s, len, "s:%s", name);
4451 }
4452 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4453 if (name_s != name)
4454 vim_free(name_s);
4455 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004456 else
4457 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4458 sid, idx, &t_any);
4459 }
4460 break;
4461 case dest_local:
4462 {
4463 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004464
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004465 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4466 // into ISN_STORENR
4467 if (instr->ga_len == instr_count + 1
4468 && isn->isn_type == ISN_PUSHNR)
4469 {
4470 varnumber_T val = isn->isn_arg.number;
4471 garray_T *stack = &cctx->ctx_type_stack;
4472
4473 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004474 isn->isn_arg.storenr.stnr_idx = idx;
4475 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004476 if (stack->ga_len > 0)
4477 --stack->ga_len;
4478 }
4479 else
4480 generate_STORE(cctx, ISN_STORE, idx, NULL);
4481 }
4482 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004483 }
4484 ret = p;
4485
4486theend:
4487 vim_free(name);
4488 return ret;
4489}
4490
4491/*
4492 * Compile an :import command.
4493 */
4494 static char_u *
4495compile_import(char_u *arg, cctx_T *cctx)
4496{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004497 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004498}
4499
4500/*
4501 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4502 */
4503 static int
4504compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4505{
4506 garray_T *instr = &cctx->ctx_instr;
4507 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4508
4509 if (endlabel == NULL)
4510 return FAIL;
4511 endlabel->el_next = *el;
4512 *el = endlabel;
4513 endlabel->el_end_label = instr->ga_len;
4514
4515 generate_JUMP(cctx, when, 0);
4516 return OK;
4517}
4518
4519 static void
4520compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4521{
4522 garray_T *instr = &cctx->ctx_instr;
4523
4524 while (*el != NULL)
4525 {
4526 endlabel_T *cur = (*el);
4527 isn_T *isn;
4528
4529 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4530 isn->isn_arg.jump.jump_where = instr->ga_len;
4531 *el = cur->el_next;
4532 vim_free(cur);
4533 }
4534}
4535
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004536 static void
4537compile_free_jump_to_end(endlabel_T **el)
4538{
4539 while (*el != NULL)
4540 {
4541 endlabel_T *cur = (*el);
4542
4543 *el = cur->el_next;
4544 vim_free(cur);
4545 }
4546}
4547
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004548/*
4549 * Create a new scope and set up the generic items.
4550 */
4551 static scope_T *
4552new_scope(cctx_T *cctx, scopetype_T type)
4553{
4554 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4555
4556 if (scope == NULL)
4557 return NULL;
4558 scope->se_outer = cctx->ctx_scope;
4559 cctx->ctx_scope = scope;
4560 scope->se_type = type;
4561 scope->se_local_count = cctx->ctx_locals.ga_len;
4562 return scope;
4563}
4564
4565/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004566 * Free the current scope and go back to the outer scope.
4567 */
4568 static void
4569drop_scope(cctx_T *cctx)
4570{
4571 scope_T *scope = cctx->ctx_scope;
4572
4573 if (scope == NULL)
4574 {
4575 iemsg("calling drop_scope() without a scope");
4576 return;
4577 }
4578 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004579 switch (scope->se_type)
4580 {
4581 case IF_SCOPE:
4582 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4583 case FOR_SCOPE:
4584 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4585 case WHILE_SCOPE:
4586 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4587 case TRY_SCOPE:
4588 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4589 case NO_SCOPE:
4590 case BLOCK_SCOPE:
4591 break;
4592 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004593 vim_free(scope);
4594}
4595
4596/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004597 * Evaluate an expression that is a constant:
4598 * has(arg)
4599 *
4600 * Also handle:
4601 * ! in front logical NOT
4602 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004603 * Return FAIL if the expression is not a constant.
4604 */
4605 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004606evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004607{
4608 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004609 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004610 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004611
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004612 /*
4613 * Skip '!' characters. They are handled later.
4614 */
4615 start_leader = *arg;
4616 while (**arg == '!')
4617 *arg = skipwhite(*arg + 1);
4618 end_leader = *arg;
4619
4620 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004621 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004622 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004623 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4624 {
4625 tv->v_type = VAR_SPECIAL;
4626 tv->vval.v_number = VVAL_TRUE;
4627 *arg += 4;
4628 return OK;
4629 }
4630 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4631 {
4632 tv->v_type = VAR_SPECIAL;
4633 tv->vval.v_number = VVAL_FALSE;
4634 *arg += 5;
4635 return OK;
4636 }
4637
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004638 if (STRNCMP("has(", *arg, 4) == 0)
4639 {
4640 has_call = TRUE;
4641 *arg = skipwhite(*arg + 4);
4642 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004643
4644 if (**arg == '"')
4645 {
4646 if (get_string_tv(arg, tv, TRUE) == FAIL)
4647 return FAIL;
4648 }
4649 else if (**arg == '\'')
4650 {
4651 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4652 return FAIL;
4653 }
4654 else
4655 return FAIL;
4656
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004657 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004658 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004659 *arg = skipwhite(*arg);
4660 if (**arg != ')')
4661 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004662 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004663
4664 argvars[0] = *tv;
4665 argvars[1].v_type = VAR_UNKNOWN;
4666 tv->v_type = VAR_NUMBER;
4667 tv->vval.v_number = 0;
4668 f_has(argvars, tv);
4669 clear_tv(&argvars[0]);
4670
4671 while (start_leader < end_leader)
4672 {
4673 if (*start_leader == '!')
4674 tv->vval.v_number = !tv->vval.v_number;
4675 ++start_leader;
4676 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004677 }
4678
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004679 return OK;
4680}
4681
Bram Moolenaar080457c2020-03-03 21:53:32 +01004682 static int
4683evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4684{
4685 exptype_T type = EXPR_UNKNOWN;
4686 char_u *p;
4687 int len = 2;
4688 int type_is = FALSE;
4689
4690 // get the first variable
4691 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4692 return FAIL;
4693
4694 p = skipwhite(*arg);
4695 type = get_compare_type(p, &len, &type_is);
4696
4697 /*
4698 * If there is a comparative operator, use it.
4699 */
4700 if (type != EXPR_UNKNOWN)
4701 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004702 typval_T tv2;
4703 char_u *s1, *s2;
4704 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4705 int n;
4706
4707 // TODO: Only string == string is supported now
4708 if (tv->v_type != VAR_STRING)
4709 return FAIL;
4710 if (type != EXPR_EQUAL)
4711 return FAIL;
4712
4713 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004714 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004715 *arg = skipwhite(p + len);
4716 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4717 || tv2.v_type != VAR_STRING)
4718 {
4719 clear_tv(&tv2);
4720 return FAIL;
4721 }
4722 s1 = tv_get_string_buf(tv, buf1);
4723 s2 = tv_get_string_buf(&tv2, buf2);
4724 n = STRCMP(s1, s2);
4725 clear_tv(tv);
4726 clear_tv(&tv2);
4727 tv->v_type = VAR_BOOL;
4728 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004729 }
4730
4731 return OK;
4732}
4733
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004734static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4735
4736/*
4737 * Compile constant || or &&.
4738 */
4739 static int
4740evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4741{
4742 char_u *p = skipwhite(*arg);
4743 int opchar = *op;
4744
4745 if (p[0] == opchar && p[1] == opchar)
4746 {
4747 int val = tv2bool(tv);
4748
4749 /*
4750 * Repeat until there is no following "||" or "&&"
4751 */
4752 while (p[0] == opchar && p[1] == opchar)
4753 {
4754 typval_T tv2;
4755
4756 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4757 return FAIL;
4758
4759 // eval the next expression
4760 *arg = skipwhite(p + 2);
4761 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004762 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004763 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004764 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004765 {
4766 clear_tv(&tv2);
4767 return FAIL;
4768 }
4769 if ((opchar == '&') == val)
4770 {
4771 // false || tv2 or true && tv2: use tv2
4772 clear_tv(tv);
4773 *tv = tv2;
4774 val = tv2bool(tv);
4775 }
4776 else
4777 clear_tv(&tv2);
4778 p = skipwhite(*arg);
4779 }
4780 }
4781
4782 return OK;
4783}
4784
4785/*
4786 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4787 * Return FAIL if the expression is not a constant.
4788 */
4789 static int
4790evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4791{
4792 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004793 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004794 return FAIL;
4795
4796 // || and && work almost the same
4797 return evaluate_const_and_or(arg, cctx, "&&", tv);
4798}
4799
4800/*
4801 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4802 * Return FAIL if the expression is not a constant.
4803 */
4804 static int
4805evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4806{
4807 // evaluate the first expression
4808 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4809 return FAIL;
4810
4811 // || and && work almost the same
4812 return evaluate_const_and_or(arg, cctx, "||", tv);
4813}
4814
4815/*
4816 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4817 * E.g. for "has('feature')".
4818 * This does not produce error messages. "tv" should be cleared afterwards.
4819 * Return FAIL if the expression is not a constant.
4820 */
4821 static int
4822evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4823{
4824 char_u *p;
4825
4826 // evaluate the first expression
4827 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4828 return FAIL;
4829
4830 p = skipwhite(*arg);
4831 if (*p == '?')
4832 {
4833 int val = tv2bool(tv);
4834 typval_T tv2;
4835
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004836 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004837 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4838 return FAIL;
4839
4840 // evaluate the second expression; any type is accepted
4841 clear_tv(tv);
4842 *arg = skipwhite(p + 1);
4843 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
4844 return FAIL;
4845
4846 // Check for the ":".
4847 p = skipwhite(*arg);
4848 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4849 return FAIL;
4850
4851 // evaluate the third expression
4852 *arg = skipwhite(p + 1);
4853 tv2.v_type = VAR_UNKNOWN;
4854 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
4855 {
4856 clear_tv(&tv2);
4857 return FAIL;
4858 }
4859 if (val)
4860 {
4861 // use the expr after "?"
4862 clear_tv(&tv2);
4863 }
4864 else
4865 {
4866 // use the expr after ":"
4867 clear_tv(tv);
4868 *tv = tv2;
4869 }
4870 }
4871 return OK;
4872}
4873
4874/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004875 * compile "if expr"
4876 *
4877 * "if expr" Produces instructions:
4878 * EVAL expr Push result of "expr"
4879 * JUMP_IF_FALSE end
4880 * ... body ...
4881 * end:
4882 *
4883 * "if expr | else" Produces instructions:
4884 * EVAL expr Push result of "expr"
4885 * JUMP_IF_FALSE else
4886 * ... body ...
4887 * JUMP_ALWAYS end
4888 * else:
4889 * ... body ...
4890 * end:
4891 *
4892 * "if expr1 | elseif expr2 | else" Produces instructions:
4893 * EVAL expr Push result of "expr"
4894 * JUMP_IF_FALSE elseif
4895 * ... body ...
4896 * JUMP_ALWAYS end
4897 * elseif:
4898 * EVAL expr Push result of "expr"
4899 * JUMP_IF_FALSE else
4900 * ... body ...
4901 * JUMP_ALWAYS end
4902 * else:
4903 * ... body ...
4904 * end:
4905 */
4906 static char_u *
4907compile_if(char_u *arg, cctx_T *cctx)
4908{
4909 char_u *p = arg;
4910 garray_T *instr = &cctx->ctx_instr;
4911 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004912 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004913
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004914 // compile "expr"; if we know it evaluates to FALSE skip the block
4915 tv.v_type = VAR_UNKNOWN;
4916 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4917 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4918 else
4919 cctx->ctx_skip = MAYBE;
4920 clear_tv(&tv);
4921 if (cctx->ctx_skip == MAYBE)
4922 {
4923 p = arg;
4924 if (compile_expr1(&p, cctx) == FAIL)
4925 return NULL;
4926 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004927
4928 scope = new_scope(cctx, IF_SCOPE);
4929 if (scope == NULL)
4930 return NULL;
4931
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004932 if (cctx->ctx_skip == MAYBE)
4933 {
4934 // "where" is set when ":elseif", "else" or ":endif" is found
4935 scope->se_u.se_if.is_if_label = instr->ga_len;
4936 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4937 }
4938 else
4939 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004940
4941 return p;
4942}
4943
4944 static char_u *
4945compile_elseif(char_u *arg, cctx_T *cctx)
4946{
4947 char_u *p = arg;
4948 garray_T *instr = &cctx->ctx_instr;
4949 isn_T *isn;
4950 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004951 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004952
4953 if (scope == NULL || scope->se_type != IF_SCOPE)
4954 {
4955 emsg(_(e_elseif_without_if));
4956 return NULL;
4957 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01004958 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004959
Bram Moolenaar158906c2020-02-06 20:39:45 +01004960 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004961 {
4962 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004963 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004964 return NULL;
4965 // previous "if" or "elseif" jumps here
4966 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
4967 isn->isn_arg.jump.jump_where = instr->ga_len;
4968 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004969
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004970 // compile "expr"; if we know it evaluates to FALSE skip the block
4971 tv.v_type = VAR_UNKNOWN;
4972 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
4973 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
4974 else
4975 cctx->ctx_skip = MAYBE;
4976 clear_tv(&tv);
4977 if (cctx->ctx_skip == MAYBE)
4978 {
4979 p = arg;
4980 if (compile_expr1(&p, cctx) == FAIL)
4981 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004982
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004983 // "where" is set when ":elseif", "else" or ":endif" is found
4984 scope->se_u.se_if.is_if_label = instr->ga_len;
4985 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
4986 }
4987 else
4988 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004989
4990 return p;
4991}
4992
4993 static char_u *
4994compile_else(char_u *arg, cctx_T *cctx)
4995{
4996 char_u *p = arg;
4997 garray_T *instr = &cctx->ctx_instr;
4998 isn_T *isn;
4999 scope_T *scope = cctx->ctx_scope;
5000
5001 if (scope == NULL || scope->se_type != IF_SCOPE)
5002 {
5003 emsg(_(e_else_without_if));
5004 return NULL;
5005 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005006 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005007
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005008 // jump from previous block to the end, unless the else block is empty
5009 if (cctx->ctx_skip == MAYBE)
5010 {
5011 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005012 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005013 return NULL;
5014 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005015
Bram Moolenaar158906c2020-02-06 20:39:45 +01005016 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005017 {
5018 if (scope->se_u.se_if.is_if_label >= 0)
5019 {
5020 // previous "if" or "elseif" jumps here
5021 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5022 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005023 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005024 }
5025 }
5026
5027 if (cctx->ctx_skip != MAYBE)
5028 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005029
5030 return p;
5031}
5032
5033 static char_u *
5034compile_endif(char_u *arg, cctx_T *cctx)
5035{
5036 scope_T *scope = cctx->ctx_scope;
5037 ifscope_T *ifscope;
5038 garray_T *instr = &cctx->ctx_instr;
5039 isn_T *isn;
5040
5041 if (scope == NULL || scope->se_type != IF_SCOPE)
5042 {
5043 emsg(_(e_endif_without_if));
5044 return NULL;
5045 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005046 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005047 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005048
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005049 if (scope->se_u.se_if.is_if_label >= 0)
5050 {
5051 // previous "if" or "elseif" jumps here
5052 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5053 isn->isn_arg.jump.jump_where = instr->ga_len;
5054 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005055 // Fill in the "end" label in jumps at the end of the blocks.
5056 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005057 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005058
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005059 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005060 return arg;
5061}
5062
5063/*
5064 * compile "for var in expr"
5065 *
5066 * Produces instructions:
5067 * PUSHNR -1
5068 * STORE loop-idx Set index to -1
5069 * EVAL expr Push result of "expr"
5070 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5071 * - if beyond end, jump to "end"
5072 * - otherwise get item from list and push it
5073 * STORE var Store item in "var"
5074 * ... body ...
5075 * JUMP top Jump back to repeat
5076 * end: DROP Drop the result of "expr"
5077 *
5078 */
5079 static char_u *
5080compile_for(char_u *arg, cctx_T *cctx)
5081{
5082 char_u *p;
5083 size_t varlen;
5084 garray_T *instr = &cctx->ctx_instr;
5085 garray_T *stack = &cctx->ctx_type_stack;
5086 scope_T *scope;
5087 int loop_idx; // index of loop iteration variable
5088 int var_idx; // index of "var"
5089 type_T *vartype;
5090
5091 // TODO: list of variables: "for [key, value] in dict"
5092 // parse "var"
5093 for (p = arg; eval_isnamec1(*p); ++p)
5094 ;
5095 varlen = p - arg;
5096 var_idx = lookup_local(arg, varlen, cctx);
5097 if (var_idx >= 0)
5098 {
5099 semsg(_("E1023: variable already defined: %s"), arg);
5100 return NULL;
5101 }
5102
5103 // consume "in"
5104 p = skipwhite(p);
5105 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5106 {
5107 emsg(_(e_missing_in));
5108 return NULL;
5109 }
5110 p = skipwhite(p + 2);
5111
5112
5113 scope = new_scope(cctx, FOR_SCOPE);
5114 if (scope == NULL)
5115 return NULL;
5116
5117 // Reserve a variable to store the loop iteration counter.
5118 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5119 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005120 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005121 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005122 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005123 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005124 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005125
5126 // Reserve a variable to store "var"
5127 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5128 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005129 {
5130 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005131 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005132 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005133
5134 generate_STORENR(cctx, loop_idx, -1);
5135
5136 // compile "expr", it remains on the stack until "endfor"
5137 arg = p;
5138 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005139 {
5140 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005141 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005142 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005143
5144 // now we know the type of "var"
5145 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5146 if (vartype->tt_type != VAR_LIST)
5147 {
5148 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005149 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005150 return NULL;
5151 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005152 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005153 {
5154 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
5155
5156 lvar->lv_type = vartype->tt_member;
5157 }
5158
5159 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005160 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005161
5162 generate_FOR(cctx, loop_idx);
5163 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
5164
5165 return arg;
5166}
5167
5168/*
5169 * compile "endfor"
5170 */
5171 static char_u *
5172compile_endfor(char_u *arg, cctx_T *cctx)
5173{
5174 garray_T *instr = &cctx->ctx_instr;
5175 scope_T *scope = cctx->ctx_scope;
5176 forscope_T *forscope;
5177 isn_T *isn;
5178
5179 if (scope == NULL || scope->se_type != FOR_SCOPE)
5180 {
5181 emsg(_(e_for));
5182 return NULL;
5183 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005184 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005185 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005186 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005187
5188 // At end of ":for" scope jump back to the FOR instruction.
5189 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5190
5191 // Fill in the "end" label in the FOR statement so it can jump here
5192 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5193 isn->isn_arg.forloop.for_end = instr->ga_len;
5194
5195 // Fill in the "end" label any BREAK statements
5196 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5197
5198 // Below the ":for" scope drop the "expr" list from the stack.
5199 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5200 return NULL;
5201
5202 vim_free(scope);
5203
5204 return arg;
5205}
5206
5207/*
5208 * compile "while expr"
5209 *
5210 * Produces instructions:
5211 * top: EVAL expr Push result of "expr"
5212 * JUMP_IF_FALSE end jump if false
5213 * ... body ...
5214 * JUMP top Jump back to repeat
5215 * end:
5216 *
5217 */
5218 static char_u *
5219compile_while(char_u *arg, cctx_T *cctx)
5220{
5221 char_u *p = arg;
5222 garray_T *instr = &cctx->ctx_instr;
5223 scope_T *scope;
5224
5225 scope = new_scope(cctx, WHILE_SCOPE);
5226 if (scope == NULL)
5227 return NULL;
5228
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005229 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005230
5231 // compile "expr"
5232 if (compile_expr1(&p, cctx) == FAIL)
5233 return NULL;
5234
5235 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005236 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005237 JUMP_IF_FALSE, cctx) == FAIL)
5238 return FAIL;
5239
5240 return p;
5241}
5242
5243/*
5244 * compile "endwhile"
5245 */
5246 static char_u *
5247compile_endwhile(char_u *arg, cctx_T *cctx)
5248{
5249 scope_T *scope = cctx->ctx_scope;
5250
5251 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5252 {
5253 emsg(_(e_while));
5254 return NULL;
5255 }
5256 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005257 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005258
5259 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005260 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005261
5262 // Fill in the "end" label in the WHILE statement so it can jump here.
5263 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005264 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005265
5266 vim_free(scope);
5267
5268 return arg;
5269}
5270
5271/*
5272 * compile "continue"
5273 */
5274 static char_u *
5275compile_continue(char_u *arg, cctx_T *cctx)
5276{
5277 scope_T *scope = cctx->ctx_scope;
5278
5279 for (;;)
5280 {
5281 if (scope == NULL)
5282 {
5283 emsg(_(e_continue));
5284 return NULL;
5285 }
5286 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5287 break;
5288 scope = scope->se_outer;
5289 }
5290
5291 // Jump back to the FOR or WHILE instruction.
5292 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005293 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5294 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005295 return arg;
5296}
5297
5298/*
5299 * compile "break"
5300 */
5301 static char_u *
5302compile_break(char_u *arg, cctx_T *cctx)
5303{
5304 scope_T *scope = cctx->ctx_scope;
5305 endlabel_T **el;
5306
5307 for (;;)
5308 {
5309 if (scope == NULL)
5310 {
5311 emsg(_(e_break));
5312 return NULL;
5313 }
5314 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5315 break;
5316 scope = scope->se_outer;
5317 }
5318
5319 // Jump to the end of the FOR or WHILE loop.
5320 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005321 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005322 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005323 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005324 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5325 return FAIL;
5326
5327 return arg;
5328}
5329
5330/*
5331 * compile "{" start of block
5332 */
5333 static char_u *
5334compile_block(char_u *arg, cctx_T *cctx)
5335{
5336 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5337 return NULL;
5338 return skipwhite(arg + 1);
5339}
5340
5341/*
5342 * compile end of block: drop one scope
5343 */
5344 static void
5345compile_endblock(cctx_T *cctx)
5346{
5347 scope_T *scope = cctx->ctx_scope;
5348
5349 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005350 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005351 vim_free(scope);
5352}
5353
5354/*
5355 * compile "try"
5356 * Creates a new scope for the try-endtry, pointing to the first catch and
5357 * finally.
5358 * Creates another scope for the "try" block itself.
5359 * TRY instruction sets up exception handling at runtime.
5360 *
5361 * "try"
5362 * TRY -> catch1, -> finally push trystack entry
5363 * ... try block
5364 * "throw {exception}"
5365 * EVAL {exception}
5366 * THROW create exception
5367 * ... try block
5368 * " catch {expr}"
5369 * JUMP -> finally
5370 * catch1: PUSH exeception
5371 * EVAL {expr}
5372 * MATCH
5373 * JUMP nomatch -> catch2
5374 * CATCH remove exception
5375 * ... catch block
5376 * " catch"
5377 * JUMP -> finally
5378 * catch2: CATCH remove exception
5379 * ... catch block
5380 * " finally"
5381 * finally:
5382 * ... finally block
5383 * " endtry"
5384 * ENDTRY pop trystack entry, may rethrow
5385 */
5386 static char_u *
5387compile_try(char_u *arg, cctx_T *cctx)
5388{
5389 garray_T *instr = &cctx->ctx_instr;
5390 scope_T *try_scope;
5391 scope_T *scope;
5392
5393 // scope that holds the jumps that go to catch/finally/endtry
5394 try_scope = new_scope(cctx, TRY_SCOPE);
5395 if (try_scope == NULL)
5396 return NULL;
5397
5398 // "catch" is set when the first ":catch" is found.
5399 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005400 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005401 if (generate_instr(cctx, ISN_TRY) == NULL)
5402 return NULL;
5403
5404 // scope for the try block itself
5405 scope = new_scope(cctx, BLOCK_SCOPE);
5406 if (scope == NULL)
5407 return NULL;
5408
5409 return arg;
5410}
5411
5412/*
5413 * compile "catch {expr}"
5414 */
5415 static char_u *
5416compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5417{
5418 scope_T *scope = cctx->ctx_scope;
5419 garray_T *instr = &cctx->ctx_instr;
5420 char_u *p;
5421 isn_T *isn;
5422
5423 // end block scope from :try or :catch
5424 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5425 compile_endblock(cctx);
5426 scope = cctx->ctx_scope;
5427
5428 // Error if not in a :try scope
5429 if (scope == NULL || scope->se_type != TRY_SCOPE)
5430 {
5431 emsg(_(e_catch));
5432 return NULL;
5433 }
5434
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005435 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005436 {
5437 emsg(_("E1033: catch unreachable after catch-all"));
5438 return NULL;
5439 }
5440
5441 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005442 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005443 JUMP_ALWAYS, cctx) == FAIL)
5444 return NULL;
5445
5446 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005447 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005448 if (isn->isn_arg.try.try_catch == 0)
5449 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005450 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005451 {
5452 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005453 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005454 isn->isn_arg.jump.jump_where = instr->ga_len;
5455 }
5456
5457 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005458 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005459 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005460 scope->se_u.se_try.ts_caught_all = TRUE;
5461 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005462 }
5463 else
5464 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005465 char_u *end;
5466 char_u *pat;
5467 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005468 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005469 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005470
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005471 // Push v:exception, push {expr} and MATCH
5472 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5473
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005474 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005475 if (*end != *p)
5476 {
5477 semsg(_("E1067: Separator mismatch: %s"), p);
5478 vim_free(tofree);
5479 return FAIL;
5480 }
5481 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005482 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005483 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005484 len = (int)(end - tofree);
5485 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005486 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005487 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005488 if (pat == NULL)
5489 return FAIL;
5490 if (generate_PUSHS(cctx, pat) == FAIL)
5491 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005492
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005493 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5494 return NULL;
5495
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005496 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005497 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5498 return NULL;
5499 }
5500
5501 if (generate_instr(cctx, ISN_CATCH) == NULL)
5502 return NULL;
5503
5504 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5505 return NULL;
5506 return p;
5507}
5508
5509 static char_u *
5510compile_finally(char_u *arg, cctx_T *cctx)
5511{
5512 scope_T *scope = cctx->ctx_scope;
5513 garray_T *instr = &cctx->ctx_instr;
5514 isn_T *isn;
5515
5516 // end block scope from :try or :catch
5517 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5518 compile_endblock(cctx);
5519 scope = cctx->ctx_scope;
5520
5521 // Error if not in a :try scope
5522 if (scope == NULL || scope->se_type != TRY_SCOPE)
5523 {
5524 emsg(_(e_finally));
5525 return NULL;
5526 }
5527
5528 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005529 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005530 if (isn->isn_arg.try.try_finally != 0)
5531 {
5532 emsg(_(e_finally_dup));
5533 return NULL;
5534 }
5535
5536 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005537 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005538
Bram Moolenaar585fea72020-04-02 22:33:21 +02005539 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005540 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005541 {
5542 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005543 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005544 isn->isn_arg.jump.jump_where = instr->ga_len;
5545 }
5546
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005547 // TODO: set index in ts_finally_label jumps
5548
5549 return arg;
5550}
5551
5552 static char_u *
5553compile_endtry(char_u *arg, cctx_T *cctx)
5554{
5555 scope_T *scope = cctx->ctx_scope;
5556 garray_T *instr = &cctx->ctx_instr;
5557 isn_T *isn;
5558
5559 // end block scope from :catch or :finally
5560 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5561 compile_endblock(cctx);
5562 scope = cctx->ctx_scope;
5563
5564 // Error if not in a :try scope
5565 if (scope == NULL || scope->se_type != TRY_SCOPE)
5566 {
5567 if (scope == NULL)
5568 emsg(_(e_no_endtry));
5569 else if (scope->se_type == WHILE_SCOPE)
5570 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005571 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005572 emsg(_(e_endfor));
5573 else
5574 emsg(_(e_endif));
5575 return NULL;
5576 }
5577
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005578 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005579 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5580 {
5581 emsg(_("E1032: missing :catch or :finally"));
5582 return NULL;
5583 }
5584
5585 // Fill in the "end" label in jumps at the end of the blocks, if not done
5586 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005587 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005588
5589 // End :catch or :finally scope: set value in ISN_TRY instruction
5590 if (isn->isn_arg.try.try_finally == 0)
5591 isn->isn_arg.try.try_finally = instr->ga_len;
5592 compile_endblock(cctx);
5593
5594 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5595 return NULL;
5596 return arg;
5597}
5598
5599/*
5600 * compile "throw {expr}"
5601 */
5602 static char_u *
5603compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5604{
5605 char_u *p = skipwhite(arg);
5606
5607 if (ends_excmd(*p))
5608 {
5609 emsg(_(e_argreq));
5610 return NULL;
5611 }
5612 if (compile_expr1(&p, cctx) == FAIL)
5613 return NULL;
5614 if (may_generate_2STRING(-1, cctx) == FAIL)
5615 return NULL;
5616 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5617 return NULL;
5618
5619 return p;
5620}
5621
5622/*
5623 * compile "echo expr"
5624 */
5625 static char_u *
5626compile_echo(char_u *arg, int with_white, cctx_T *cctx)
5627{
5628 char_u *p = arg;
5629 int count = 0;
5630
Bram Moolenaarad39c092020-02-26 18:23:43 +01005631 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005632 {
5633 if (compile_expr1(&p, cctx) == FAIL)
5634 return NULL;
5635 ++count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005636 p = skipwhite(p);
5637 if (ends_excmd(*p))
5638 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005639 }
5640
5641 generate_ECHO(cctx, with_white, count);
Bram Moolenaarad39c092020-02-26 18:23:43 +01005642 return p;
5643}
5644
5645/*
5646 * compile "execute expr"
5647 */
5648 static char_u *
5649compile_execute(char_u *arg, cctx_T *cctx)
5650{
5651 char_u *p = arg;
5652 int count = 0;
5653
5654 for (;;)
5655 {
5656 if (compile_expr1(&p, cctx) == FAIL)
5657 return NULL;
5658 ++count;
5659 p = skipwhite(p);
5660 if (ends_excmd(*p))
5661 break;
5662 }
5663
5664 generate_EXECUTE(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005665
5666 return p;
5667}
5668
5669/*
5670 * After ex_function() has collected all the function lines: parse and compile
5671 * the lines into instructions.
5672 * Adds the function to "def_functions".
5673 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5674 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005675 * This can be used recursively through compile_lambda(), which may reallocate
5676 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005677 */
5678 void
5679compile_def_function(ufunc_T *ufunc, int set_return_type)
5680{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005681 char_u *line = NULL;
5682 char_u *p;
5683 exarg_T ea;
5684 char *errormsg = NULL; // error message
5685 int had_return = FALSE;
5686 cctx_T cctx;
5687 garray_T *instr;
5688 int called_emsg_before = called_emsg;
5689 int ret = FAIL;
5690 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005691 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005692
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005693 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005694 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005695
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005696 if (ufunc->uf_dfunc_idx >= 0)
5697 {
5698 // Redefining a function that was compiled before.
5699 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5700
5701 // Free old instructions.
5702 delete_def_function_contents(dfunc);
5703 }
5704 else
5705 {
5706 // Add the function to "def_functions".
5707 if (ga_grow(&def_functions, 1) == FAIL)
5708 return;
5709 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005710 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005711 dfunc->df_idx = def_functions.ga_len;
5712 ufunc->uf_dfunc_idx = dfunc->df_idx;
5713 dfunc->df_ufunc = ufunc;
5714 ++def_functions.ga_len;
5715 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005716 }
5717
Bram Moolenaara80faa82020-04-12 19:37:17 +02005718 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005719 cctx.ctx_ufunc = ufunc;
5720 cctx.ctx_lnum = -1;
5721 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5722 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5723 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5724 cctx.ctx_type_list = &ufunc->uf_type_list;
5725 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5726 instr = &cctx.ctx_instr;
5727
5728 // Most modern script version.
5729 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5730
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005731 if (ufunc->uf_def_args.ga_len > 0)
5732 {
5733 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005734 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005735 int i;
5736 char_u *arg;
5737 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5738
5739 // Produce instructions for the default values of optional arguments.
5740 // Store the instruction index in uf_def_arg_idx[] so that we know
5741 // where to start when the function is called, depending on the number
5742 // of arguments.
5743 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5744 if (ufunc->uf_def_arg_idx == NULL)
5745 goto erret;
5746 for (i = 0; i < count; ++i)
5747 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005748 garray_T *stack = &cctx.ctx_type_stack;
5749 type_T *val_type;
5750 int arg_idx = first_def_arg + i;
5751
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005752 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5753 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005754 if (compile_expr1(&arg, &cctx) == FAIL)
5755 goto erret;
5756
5757 // If no type specified use the type of the default value.
5758 // Otherwise check that the default value type matches the
5759 // specified type.
5760 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5761 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
5762 ufunc->uf_arg_types[arg_idx] = val_type;
5763 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
5764 == FAIL)
5765 {
5766 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
5767 arg_idx + 1);
5768 goto erret;
5769 }
5770
5771 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005772 goto erret;
5773 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005774 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5775 }
5776
5777 /*
5778 * Loop over all the lines of the function and generate instructions.
5779 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005780 for (;;)
5781 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005782 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005783
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005784 // Bail out on the first error to avoid a flood of errors and report
5785 // the right line number when inside try/catch.
5786 if (emsg_before != called_emsg)
5787 goto erret;
5788
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005789 if (line != NULL && *line == '|')
5790 // the line continues after a '|'
5791 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02005792 else if (line != NULL && *line != NUL
5793 && !(*line == '#' && (line == cctx.ctx_line_start
5794 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005795 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005796 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005797 goto erret;
5798 }
5799 else
5800 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02005801 line = next_line_from_context(&cctx);
5802 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005803 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005804 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005805 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005806 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005807
5808 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005809 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005810 ea.cmdlinep = &line;
5811 ea.cmd = skipwhite(line);
5812
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005813 // Some things can be recognized by the first character.
5814 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005815 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005816 case '#':
5817 // "#" starts a comment, but not "#{".
5818 if (ea.cmd[1] != '{')
5819 {
5820 line = (char_u *)"";
5821 continue;
5822 }
5823 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005824
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005825 case '}':
5826 {
5827 // "}" ends a block scope
5828 scopetype_T stype = cctx.ctx_scope == NULL
5829 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005830
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005831 if (stype == BLOCK_SCOPE)
5832 {
5833 compile_endblock(&cctx);
5834 line = ea.cmd;
5835 }
5836 else
5837 {
5838 emsg(_("E1025: using } outside of a block scope"));
5839 goto erret;
5840 }
5841 if (line != NULL)
5842 line = skipwhite(ea.cmd + 1);
5843 continue;
5844 }
5845
5846 case '{':
5847 // "{" starts a block scope
5848 // "{'a': 1}->func() is something else
5849 if (ends_excmd(*skipwhite(ea.cmd + 1)))
5850 {
5851 line = compile_block(ea.cmd, &cctx);
5852 continue;
5853 }
5854 break;
5855
5856 case ':':
5857 is_ex_command = TRUE;
5858 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005859 }
5860
5861 /*
5862 * COMMAND MODIFIERS
5863 */
5864 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
5865 {
5866 if (errormsg != NULL)
5867 goto erret;
5868 // empty line or comment
5869 line = (char_u *)"";
5870 continue;
5871 }
5872
5873 // Skip ":call" to get to the function name.
5874 if (checkforcmd(&ea.cmd, "call", 3))
5875 ea.cmd = skipwhite(ea.cmd);
5876
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005877 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005878 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005879 // Assuming the command starts with a variable or function name,
5880 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
5881 // val".
5882 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
5883 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005884 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02005885 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005886 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005887 int oplen;
5888 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005889
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005890 oplen = assignment_len(skipwhite(p), &heredoc);
5891 if (oplen > 0)
5892 {
5893 // Recognize an assignment if we recognize the variable
5894 // name:
5895 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01005896 // "local = expr" where "local" is a local var.
5897 // "script = expr" where "script" is a script-local var.
5898 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005899 // "&opt = expr"
5900 // "$ENV = expr"
5901 // "@r = expr"
5902 if (*ea.cmd == '&'
5903 || *ea.cmd == '$'
5904 || *ea.cmd == '@'
5905 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
5906 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
5907 || lookup_script(ea.cmd, p - ea.cmd) == OK
5908 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
5909 {
5910 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
5911 if (line == NULL)
5912 goto erret;
5913 continue;
5914 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005915 }
5916 }
5917 }
5918
5919 /*
5920 * COMMAND after range
5921 */
5922 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005923 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
5924 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005925
5926 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
5927 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005928 if (cctx.ctx_skip == TRUE)
5929 {
5930 line += STRLEN(line);
5931 continue;
5932 }
5933
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005934 // Expression or function call.
5935 if (ea.cmdidx == CMD_eval)
5936 {
5937 p = ea.cmd;
5938 if (compile_expr1(&p, &cctx) == FAIL)
5939 goto erret;
5940
5941 // drop the return value
5942 generate_instr_drop(&cctx, ISN_DROP, 1);
5943 line = p;
5944 continue;
5945 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02005946 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005947 iemsg("Command from find_ex_command() not handled");
5948 goto erret;
5949 }
5950
5951 p = skipwhite(p);
5952
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005953 if (cctx.ctx_skip == TRUE
5954 && ea.cmdidx != CMD_elseif
5955 && ea.cmdidx != CMD_else
5956 && ea.cmdidx != CMD_endif)
5957 {
5958 line += STRLEN(line);
5959 continue;
5960 }
5961
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005962 switch (ea.cmdidx)
5963 {
5964 case CMD_def:
5965 case CMD_function:
5966 // TODO: Nested function
5967 emsg("Nested function not implemented yet");
5968 goto erret;
5969
5970 case CMD_return:
5971 line = compile_return(p, set_return_type, &cctx);
5972 had_return = TRUE;
5973 break;
5974
5975 case CMD_let:
5976 case CMD_const:
5977 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
5978 break;
5979
5980 case CMD_import:
5981 line = compile_import(p, &cctx);
5982 break;
5983
5984 case CMD_if:
5985 line = compile_if(p, &cctx);
5986 break;
5987 case CMD_elseif:
5988 line = compile_elseif(p, &cctx);
5989 break;
5990 case CMD_else:
5991 line = compile_else(p, &cctx);
5992 break;
5993 case CMD_endif:
5994 line = compile_endif(p, &cctx);
5995 break;
5996
5997 case CMD_while:
5998 line = compile_while(p, &cctx);
5999 break;
6000 case CMD_endwhile:
6001 line = compile_endwhile(p, &cctx);
6002 break;
6003
6004 case CMD_for:
6005 line = compile_for(p, &cctx);
6006 break;
6007 case CMD_endfor:
6008 line = compile_endfor(p, &cctx);
6009 break;
6010 case CMD_continue:
6011 line = compile_continue(p, &cctx);
6012 break;
6013 case CMD_break:
6014 line = compile_break(p, &cctx);
6015 break;
6016
6017 case CMD_try:
6018 line = compile_try(p, &cctx);
6019 break;
6020 case CMD_catch:
6021 line = compile_catch(p, &cctx);
6022 break;
6023 case CMD_finally:
6024 line = compile_finally(p, &cctx);
6025 break;
6026 case CMD_endtry:
6027 line = compile_endtry(p, &cctx);
6028 break;
6029 case CMD_throw:
6030 line = compile_throw(p, &cctx);
6031 break;
6032
6033 case CMD_echo:
6034 line = compile_echo(p, TRUE, &cctx);
6035 break;
6036 case CMD_echon:
6037 line = compile_echo(p, FALSE, &cctx);
6038 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01006039 case CMD_execute:
6040 line = compile_execute(p, &cctx);
6041 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006042
6043 default:
6044 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01006045 // TODO:
6046 // CMD_echomsg
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01006047 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006048 generate_EXEC(&cctx, line);
6049 line = (char_u *)"";
6050 break;
6051 }
6052 if (line == NULL)
6053 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006054 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006055
6056 if (cctx.ctx_type_stack.ga_len < 0)
6057 {
6058 iemsg("Type stack underflow");
6059 goto erret;
6060 }
6061 }
6062
6063 if (cctx.ctx_scope != NULL)
6064 {
6065 if (cctx.ctx_scope->se_type == IF_SCOPE)
6066 emsg(_(e_endif));
6067 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6068 emsg(_(e_endwhile));
6069 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6070 emsg(_(e_endfor));
6071 else
6072 emsg(_("E1026: Missing }"));
6073 goto erret;
6074 }
6075
6076 if (!had_return)
6077 {
6078 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6079 {
6080 emsg(_("E1027: Missing return statement"));
6081 goto erret;
6082 }
6083
6084 // Return zero if there is no return at the end.
6085 generate_PUSHNR(&cctx, 0);
6086 generate_instr(&cctx, ISN_RETURN);
6087 }
6088
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006089 {
6090 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6091 + ufunc->uf_dfunc_idx;
6092 dfunc->df_deleted = FALSE;
6093 dfunc->df_instr = instr->ga_data;
6094 dfunc->df_instr_count = instr->ga_len;
6095 dfunc->df_varcount = cctx.ctx_max_local;
6096 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006097
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006098 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006099 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006100 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006101
6102 // Create a type for the function, with the return type and any
6103 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006104 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6105 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006106 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006107 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006108 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6109 argcount, &ufunc->uf_type_list);
6110 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006111 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006112 argcount + varargs,
6113 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006114 {
6115 ret = FAIL;
6116 goto erret;
6117 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006118 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6119 ufunc->uf_func_type->tt_min_argcount =
6120 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006121 if (ufunc->uf_arg_types == NULL)
6122 {
6123 int i;
6124
6125 // lambda does not have argument types.
6126 for (i = 0; i < argcount; ++i)
6127 ufunc->uf_func_type->tt_args[i] = &t_any;
6128 }
6129 else
6130 mch_memmove(ufunc->uf_func_type->tt_args,
6131 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006132 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006133 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006134 ufunc->uf_func_type->tt_args[argcount] =
6135 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006136 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6137 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006138 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006139 else
6140 // No arguments, can use a predefined type.
6141 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6142 argcount, &ufunc->uf_type_list);
6143
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006144 }
6145
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006146 ret = OK;
6147
6148erret:
6149 if (ret == FAIL)
6150 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006151 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006152 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6153 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006154
6155 for (idx = 0; idx < instr->ga_len; ++idx)
6156 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006157 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006158
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006159 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006160 if (!dfunc->df_deleted)
6161 --def_functions.ga_len;
6162
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006163 while (cctx.ctx_scope != NULL)
6164 drop_scope(&cctx);
6165
Bram Moolenaar20431c92020-03-20 18:39:46 +01006166 // Don't execute this function body.
6167 ga_clear_strings(&ufunc->uf_lines);
6168
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006169 if (errormsg != NULL)
6170 emsg(errormsg);
6171 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006172 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006173 }
6174
6175 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006176 free_imported(&cctx);
6177 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006178 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006179}
6180
6181/*
6182 * Delete an instruction, free what it contains.
6183 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006184 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006185delete_instr(isn_T *isn)
6186{
6187 switch (isn->isn_type)
6188 {
6189 case ISN_EXEC:
6190 case ISN_LOADENV:
6191 case ISN_LOADG:
6192 case ISN_LOADOPT:
6193 case ISN_MEMBER:
6194 case ISN_PUSHEXC:
6195 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006196 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006197 case ISN_STOREG:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006198 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006199 vim_free(isn->isn_arg.string);
6200 break;
6201
6202 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006203 case ISN_STORES:
6204 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006205 break;
6206
6207 case ISN_STOREOPT:
6208 vim_free(isn->isn_arg.storeopt.so_name);
6209 break;
6210
6211 case ISN_PUSHBLOB: // push blob isn_arg.blob
6212 blob_unref(isn->isn_arg.blob);
6213 break;
6214
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006215 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006216#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006217 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006218#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006219 break;
6220
6221 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006222#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006223 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006224#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006225 break;
6226
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006227 case ISN_UCALL:
6228 vim_free(isn->isn_arg.ufunc.cuf_name);
6229 break;
6230
6231 case ISN_2BOOL:
6232 case ISN_2STRING:
6233 case ISN_ADDBLOB:
6234 case ISN_ADDLIST:
6235 case ISN_BCALL:
6236 case ISN_CATCH:
6237 case ISN_CHECKNR:
6238 case ISN_CHECKTYPE:
6239 case ISN_COMPAREANY:
6240 case ISN_COMPAREBLOB:
6241 case ISN_COMPAREBOOL:
6242 case ISN_COMPAREDICT:
6243 case ISN_COMPAREFLOAT:
6244 case ISN_COMPAREFUNC:
6245 case ISN_COMPARELIST:
6246 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006247 case ISN_COMPARESPECIAL:
6248 case ISN_COMPARESTRING:
6249 case ISN_CONCAT:
6250 case ISN_DCALL:
6251 case ISN_DROP:
6252 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006253 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006254 case ISN_ENDTRY:
6255 case ISN_FOR:
6256 case ISN_FUNCREF:
6257 case ISN_INDEX:
6258 case ISN_JUMP:
6259 case ISN_LOAD:
6260 case ISN_LOADSCRIPT:
6261 case ISN_LOADREG:
6262 case ISN_LOADV:
6263 case ISN_NEGATENR:
6264 case ISN_NEWDICT:
6265 case ISN_NEWLIST:
6266 case ISN_OPNR:
6267 case ISN_OPFLOAT:
6268 case ISN_OPANY:
6269 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006270 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006271 case ISN_PUSHF:
6272 case ISN_PUSHNR:
6273 case ISN_PUSHBOOL:
6274 case ISN_PUSHSPEC:
6275 case ISN_RETURN:
6276 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006277 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006278 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006279 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006280 case ISN_STORESCRIPT:
6281 case ISN_THROW:
6282 case ISN_TRY:
6283 // nothing allocated
6284 break;
6285 }
6286}
6287
6288/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006289 * Free all instructions for "dfunc".
6290 */
6291 static void
6292delete_def_function_contents(dfunc_T *dfunc)
6293{
6294 int idx;
6295
6296 ga_clear(&dfunc->df_def_args_isn);
6297
6298 if (dfunc->df_instr != NULL)
6299 {
6300 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6301 delete_instr(dfunc->df_instr + idx);
6302 VIM_CLEAR(dfunc->df_instr);
6303 }
6304
6305 dfunc->df_deleted = TRUE;
6306}
6307
6308/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006309 * When a user function is deleted, delete any associated def function.
6310 */
6311 void
6312delete_def_function(ufunc_T *ufunc)
6313{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006314 if (ufunc->uf_dfunc_idx >= 0)
6315 {
6316 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6317 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006318
Bram Moolenaar20431c92020-03-20 18:39:46 +01006319 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006320 }
6321}
6322
6323#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006324/*
6325 * Free all functions defined with ":def".
6326 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006327 void
6328free_def_functions(void)
6329{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006330 int idx;
6331
6332 for (idx = 0; idx < def_functions.ga_len; ++idx)
6333 {
6334 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6335
6336 delete_def_function_contents(dfunc);
6337 }
6338
6339 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006340}
6341#endif
6342
6343
6344#endif // FEAT_EVAL