blob: 393d2b824c942b288f1d751bc1088452d0d778cb [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9compile.c: :def and dealing with instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#define DEFINE_VIM9_GLOBALS
24#include "vim9.h"
25
26/*
27 * Chain of jump instructions where the end label needs to be set.
28 */
29typedef struct endlabel_S endlabel_T;
30struct endlabel_S {
31 endlabel_T *el_next; // chain end_label locations
32 int el_end_label; // instruction idx where to set end
33};
34
35/*
36 * info specific for the scope of :if / elseif / else
37 */
38typedef struct {
39 int is_if_label; // instruction idx at IF or ELSEIF
40 endlabel_T *is_end_label; // instructions to set end label
41} ifscope_T;
42
43/*
44 * info specific for the scope of :while
45 */
46typedef struct {
47 int ws_top_label; // instruction idx at WHILE
48 endlabel_T *ws_end_label; // instructions to set end
49} whilescope_T;
50
51/*
52 * info specific for the scope of :for
53 */
54typedef struct {
55 int fs_top_label; // instruction idx at FOR
56 endlabel_T *fs_end_label; // break instructions
57} forscope_T;
58
59/*
60 * info specific for the scope of :try
61 */
62typedef struct {
63 int ts_try_label; // instruction idx at TRY
64 endlabel_T *ts_end_label; // jump to :finally or :endtry
65 int ts_catch_label; // instruction idx of last CATCH
66 int ts_caught_all; // "catch" without argument encountered
67} tryscope_T;
68
69typedef enum {
70 NO_SCOPE,
71 IF_SCOPE,
72 WHILE_SCOPE,
73 FOR_SCOPE,
74 TRY_SCOPE,
75 BLOCK_SCOPE
76} scopetype_T;
77
78/*
79 * Info for one scope, pointed to by "ctx_scope".
80 */
81typedef struct scope_S scope_T;
82struct scope_S {
83 scope_T *se_outer; // scope containing this one
84 scopetype_T se_type;
85 int se_local_count; // ctx_locals.ga_len before scope
86 union {
87 ifscope_T se_if;
88 whilescope_T se_while;
89 forscope_T se_for;
90 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +010091 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010092};
93
94/*
95 * Entry for "ctx_locals". Used for arguments and local variables.
96 */
97typedef struct {
98 char_u *lv_name;
99 type_T *lv_type;
100 int lv_const; // when TRUE cannot be assigned to
101 int lv_arg; // when TRUE this is an argument
102} lvar_T;
103
104/*
105 * Context for compiling lines of Vim script.
106 * Stores info about the local variables and condition stack.
107 */
108struct cctx_S {
109 ufunc_T *ctx_ufunc; // current function
110 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200111 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100112 garray_T ctx_instr; // generated instructions
113
114 garray_T ctx_locals; // currently visible local variables
115 int ctx_max_local; // maximum number of locals at one time
116
117 garray_T ctx_imports; // imported items
118
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100119 int ctx_skip; // when TRUE skip commands, when FALSE skip
120 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100121 scope_T *ctx_scope; // current scope, NULL at toplevel
122
123 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200124 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100125};
126
127static char e_var_notfound[] = N_("E1001: variable not found: %s");
128static char e_syntax_at[] = N_("E1002: Syntax error at %s");
129
130static int compile_expr1(char_u **arg, cctx_T *cctx);
131static int compile_expr2(char_u **arg, cctx_T *cctx);
132static int compile_expr3(char_u **arg, cctx_T *cctx);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100133static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200134static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
135static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100136
137/*
138 * Lookup variable "name" in the local scope and return the index.
139 */
140 static int
141lookup_local(char_u *name, size_t len, cctx_T *cctx)
142{
143 int idx;
144
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100145 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146 return -1;
147 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
148 {
149 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
150
151 if (STRNCMP(name, lvar->lv_name, len) == 0
152 && STRLEN(lvar->lv_name) == len)
153 return idx;
154 }
155 return -1;
156}
157
158/*
159 * Lookup an argument in the current function.
160 * Returns the argument index or -1 if not found.
161 */
162 static int
163lookup_arg(char_u *name, size_t len, cctx_T *cctx)
164{
165 int idx;
166
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100167 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100168 return -1;
169 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
170 {
171 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
172
173 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
174 return idx;
175 }
176 return -1;
177}
178
179/*
180 * Lookup a vararg argument in the current function.
181 * Returns TRUE if there is a match.
182 */
183 static int
184lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
185{
186 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
187
188 return len > 0 && va_name != NULL
189 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
190}
191
192/*
193 * Lookup a variable in the current script.
194 * Returns OK or FAIL.
195 */
196 static int
197lookup_script(char_u *name, size_t len)
198{
199 int cc;
200 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
201 dictitem_T *di;
202
203 cc = name[len];
204 name[len] = NUL;
205 di = find_var_in_ht(ht, 0, name, TRUE);
206 name[len] = cc;
207 return di == NULL ? FAIL: OK;
208}
209
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100210/*
211 * Check if "p[len]" is already defined, either in script "import_sid" or in
212 * compilation context "cctx".
213 * Return FAIL and give an error if it defined.
214 */
215 int
216check_defined(char_u *p, int len, cctx_T *cctx)
217{
218 if (lookup_script(p, len) == OK
219 || (cctx != NULL
220 && (lookup_local(p, len, cctx) >= 0
221 || find_imported(p, len, cctx) != NULL)))
222 {
223 semsg("E1073: imported name already defined: %s", p);
224 return FAIL;
225 }
226 return OK;
227}
228
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200229/*
230 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
231 * be freed later.
232 */
233 static type_T *
234alloc_type(garray_T *type_gap)
235{
236 type_T *type;
237
238 if (ga_grow(type_gap, 1) == FAIL)
239 return NULL;
240 type = ALLOC_CLEAR_ONE(type_T);
241 if (type != NULL)
242 {
243 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
244 ++type_gap->ga_len;
245 }
246 return type;
247}
248
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100249 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200250get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100251{
252 type_T *type;
253
254 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200255 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100256 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200257 if (member_type->tt_type == VAR_VOID
258 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100259 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100260 if (member_type->tt_type == VAR_BOOL)
261 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100262 if (member_type->tt_type == VAR_NUMBER)
263 return &t_list_number;
264 if (member_type->tt_type == VAR_STRING)
265 return &t_list_string;
266
267 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200268 type = alloc_type(type_gap);
269 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100270 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 type->tt_type = VAR_LIST;
272 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200273 type->tt_argcount = 0;
274 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100275 return type;
276}
277
278 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200279get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100280{
281 type_T *type;
282
283 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200284 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100285 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200286 if (member_type->tt_type == VAR_VOID
287 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100288 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100289 if (member_type->tt_type == VAR_BOOL)
290 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100291 if (member_type->tt_type == VAR_NUMBER)
292 return &t_dict_number;
293 if (member_type->tt_type == VAR_STRING)
294 return &t_dict_string;
295
296 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200297 type = alloc_type(type_gap);
298 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100299 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100300 type->tt_type = VAR_DICT;
301 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200302 type->tt_argcount = 0;
303 type->tt_args = NULL;
304 return type;
305}
306
307/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200308 * Allocate a new type for a function.
309 */
310 static type_T *
311alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
312{
313 type_T *type = alloc_type(type_gap);
314
315 if (type == NULL)
316 return &t_any;
317 type->tt_type = VAR_FUNC;
318 type->tt_member = ret_type;
319 type->tt_argcount = argcount;
320 type->tt_args = NULL;
321 return type;
322}
323
324/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200325 * Get a function type, based on the return type "ret_type".
326 * If "argcount" is -1 or 0 a predefined type can be used.
327 * If "argcount" > 0 always create a new type, so that arguments can be added.
328 */
329 static type_T *
330get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
331{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200332 // recognize commonly used types
333 if (argcount <= 0)
334 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200335 if (ret_type == &t_unknown)
336 {
337 // (argcount == 0) is not possible
338 return &t_func_unknown;
339 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200340 if (ret_type == &t_void)
341 {
342 if (argcount == 0)
343 return &t_func_0_void;
344 else
345 return &t_func_void;
346 }
347 if (ret_type == &t_any)
348 {
349 if (argcount == 0)
350 return &t_func_0_any;
351 else
352 return &t_func_any;
353 }
354 if (ret_type == &t_number)
355 {
356 if (argcount == 0)
357 return &t_func_0_number;
358 else
359 return &t_func_number;
360 }
361 if (ret_type == &t_string)
362 {
363 if (argcount == 0)
364 return &t_func_0_string;
365 else
366 return &t_func_string;
367 }
368 }
369
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200370 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100371}
372
Bram Moolenaara8c17702020-04-01 21:17:24 +0200373/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200374 * For a function type, reserve space for "argcount" argument types (including
375 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200376 */
377 static int
378func_type_add_arg_types(
379 type_T *functype,
380 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200381 garray_T *type_gap)
382{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200383 // To make it easy to free the space needed for the argument types, add the
384 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200385 if (ga_grow(type_gap, 1) == FAIL)
386 return FAIL;
387 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
388 if (functype->tt_args == NULL)
389 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200390 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
391 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200392 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200393 return OK;
394}
395
396/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200397 * Return the type_T for a typval. Only for primitive types.
398 */
399 static type_T *
400typval2type(typval_T *tv)
401{
402 if (tv->v_type == VAR_NUMBER)
403 return &t_number;
404 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200405 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200406 if (tv->v_type == VAR_STRING)
407 return &t_string;
408 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
409 return &t_list_string;
410 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
411 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200412 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200413}
414
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100415/////////////////////////////////////////////////////////////////////
416// Following generate_ functions expect the caller to call ga_grow().
417
Bram Moolenaar080457c2020-03-03 21:53:32 +0100418#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
419#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
420
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100421/*
422 * Generate an instruction without arguments.
423 * Returns a pointer to the new instruction, NULL if failed.
424 */
425 static isn_T *
426generate_instr(cctx_T *cctx, isntype_T isn_type)
427{
428 garray_T *instr = &cctx->ctx_instr;
429 isn_T *isn;
430
Bram Moolenaar080457c2020-03-03 21:53:32 +0100431 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100432 if (ga_grow(instr, 1) == FAIL)
433 return NULL;
434 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
435 isn->isn_type = isn_type;
436 isn->isn_lnum = cctx->ctx_lnum + 1;
437 ++instr->ga_len;
438
439 return isn;
440}
441
442/*
443 * Generate an instruction without arguments.
444 * "drop" will be removed from the stack.
445 * Returns a pointer to the new instruction, NULL if failed.
446 */
447 static isn_T *
448generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
449{
450 garray_T *stack = &cctx->ctx_type_stack;
451
Bram Moolenaar080457c2020-03-03 21:53:32 +0100452 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100453 stack->ga_len -= drop;
454 return generate_instr(cctx, isn_type);
455}
456
457/*
458 * Generate instruction "isn_type" and put "type" on the type stack.
459 */
460 static isn_T *
461generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
462{
463 isn_T *isn;
464 garray_T *stack = &cctx->ctx_type_stack;
465
466 if ((isn = generate_instr(cctx, isn_type)) == NULL)
467 return NULL;
468
469 if (ga_grow(stack, 1) == FAIL)
470 return NULL;
471 ((type_T **)stack->ga_data)[stack->ga_len] = type;
472 ++stack->ga_len;
473
474 return isn;
475}
476
477/*
478 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
479 */
480 static int
481may_generate_2STRING(int offset, cctx_T *cctx)
482{
483 isn_T *isn;
484 garray_T *stack = &cctx->ctx_type_stack;
485 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
486
487 if ((*type)->tt_type == VAR_STRING)
488 return OK;
489 *type = &t_string;
490
491 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
492 return FAIL;
493 isn->isn_arg.number = offset;
494
495 return OK;
496}
497
498 static int
499check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
500{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200501 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100502 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200503 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100504 {
505 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100506 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100507 else
508 semsg(_("E1036: %c requires number or float arguments"), *op);
509 return FAIL;
510 }
511 return OK;
512}
513
514/*
515 * Generate an instruction with two arguments. The instruction depends on the
516 * type of the arguments.
517 */
518 static int
519generate_two_op(cctx_T *cctx, char_u *op)
520{
521 garray_T *stack = &cctx->ctx_type_stack;
522 type_T *type1;
523 type_T *type2;
524 vartype_T vartype;
525 isn_T *isn;
526
Bram Moolenaar080457c2020-03-03 21:53:32 +0100527 RETURN_OK_IF_SKIP(cctx);
528
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100529 // Get the known type of the two items on the stack. If they are matching
530 // use a type-specific instruction. Otherwise fall back to runtime type
531 // checking.
532 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
533 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200534 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100535 if (type1->tt_type == type2->tt_type
536 && (type1->tt_type == VAR_NUMBER
537 || type1->tt_type == VAR_LIST
538#ifdef FEAT_FLOAT
539 || type1->tt_type == VAR_FLOAT
540#endif
541 || type1->tt_type == VAR_BLOB))
542 vartype = type1->tt_type;
543
544 switch (*op)
545 {
546 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200547 && type1->tt_type != VAR_ANY
548 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100549 && check_number_or_float(
550 type1->tt_type, type2->tt_type, op) == FAIL)
551 return FAIL;
552 isn = generate_instr_drop(cctx,
553 vartype == VAR_NUMBER ? ISN_OPNR
554 : vartype == VAR_LIST ? ISN_ADDLIST
555 : vartype == VAR_BLOB ? ISN_ADDBLOB
556#ifdef FEAT_FLOAT
557 : vartype == VAR_FLOAT ? ISN_OPFLOAT
558#endif
559 : ISN_OPANY, 1);
560 if (isn != NULL)
561 isn->isn_arg.op.op_type = EXPR_ADD;
562 break;
563
564 case '-':
565 case '*':
566 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
567 op) == FAIL)
568 return FAIL;
569 if (vartype == VAR_NUMBER)
570 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
571#ifdef FEAT_FLOAT
572 else if (vartype == VAR_FLOAT)
573 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
574#endif
575 else
576 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
577 if (isn != NULL)
578 isn->isn_arg.op.op_type = *op == '*'
579 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
580 break;
581
Bram Moolenaar4c683752020-04-05 21:38:23 +0200582 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100583 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200584 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100585 && type2->tt_type != VAR_NUMBER))
586 {
587 emsg(_("E1035: % requires number arguments"));
588 return FAIL;
589 }
590 isn = generate_instr_drop(cctx,
591 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
592 if (isn != NULL)
593 isn->isn_arg.op.op_type = EXPR_REM;
594 break;
595 }
596
597 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200598 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100599 {
600 type_T *type = &t_any;
601
602#ifdef FEAT_FLOAT
603 // float+number and number+float results in float
604 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
605 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
606 type = &t_float;
607#endif
608 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
609 }
610
611 return OK;
612}
613
614/*
615 * Generate an ISN_COMPARE* instruction with a boolean result.
616 */
617 static int
618generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
619{
620 isntype_T isntype = ISN_DROP;
621 isn_T *isn;
622 garray_T *stack = &cctx->ctx_type_stack;
623 vartype_T type1;
624 vartype_T type2;
625
Bram Moolenaar080457c2020-03-03 21:53:32 +0100626 RETURN_OK_IF_SKIP(cctx);
627
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100628 // Get the known type of the two items on the stack. If they are matching
629 // use a type-specific instruction. Otherwise fall back to runtime type
630 // checking.
631 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
632 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200633 if (type1 == VAR_UNKNOWN)
634 type1 = VAR_ANY;
635 if (type2 == VAR_UNKNOWN)
636 type2 = VAR_ANY;
637
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100638 if (type1 == type2)
639 {
640 switch (type1)
641 {
642 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
643 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
644 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
645 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
646 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
647 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
648 case VAR_LIST: isntype = ISN_COMPARELIST; break;
649 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
650 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100651 default: isntype = ISN_COMPAREANY; break;
652 }
653 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200654 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100655 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
656 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
657 isntype = ISN_COMPAREANY;
658
659 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
660 && (isntype == ISN_COMPAREBOOL
661 || isntype == ISN_COMPARESPECIAL
662 || isntype == ISN_COMPARENR
663 || isntype == ISN_COMPAREFLOAT))
664 {
665 semsg(_("E1037: Cannot use \"%s\" with %s"),
666 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
667 return FAIL;
668 }
669 if (isntype == ISN_DROP
670 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
671 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
672 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
673 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
674 && exptype != EXPR_IS && exptype != EXPR_ISNOT
675 && (type1 == VAR_BLOB || type2 == VAR_BLOB
676 || type1 == VAR_LIST || type2 == VAR_LIST))))
677 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100678 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100679 vartype_name(type1), vartype_name(type2));
680 return FAIL;
681 }
682
683 if ((isn = generate_instr(cctx, isntype)) == NULL)
684 return FAIL;
685 isn->isn_arg.op.op_type = exptype;
686 isn->isn_arg.op.op_ic = ic;
687
688 // takes two arguments, puts one bool back
689 if (stack->ga_len >= 2)
690 {
691 --stack->ga_len;
692 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
693 }
694
695 return OK;
696}
697
698/*
699 * Generate an ISN_2BOOL instruction.
700 */
701 static int
702generate_2BOOL(cctx_T *cctx, int invert)
703{
704 isn_T *isn;
705 garray_T *stack = &cctx->ctx_type_stack;
706
Bram Moolenaar080457c2020-03-03 21:53:32 +0100707 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100708 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
709 return FAIL;
710 isn->isn_arg.number = invert;
711
712 // type becomes bool
713 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
714
715 return OK;
716}
717
718 static int
719generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
720{
721 isn_T *isn;
722 garray_T *stack = &cctx->ctx_type_stack;
723
Bram Moolenaar080457c2020-03-03 21:53:32 +0100724 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100725 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
726 return FAIL;
727 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
728 isn->isn_arg.type.ct_off = offset;
729
730 // type becomes vartype
731 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
732
733 return OK;
734}
735
736/*
737 * Generate an ISN_PUSHNR instruction.
738 */
739 static int
740generate_PUSHNR(cctx_T *cctx, varnumber_T number)
741{
742 isn_T *isn;
743
Bram Moolenaar080457c2020-03-03 21:53:32 +0100744 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100745 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
746 return FAIL;
747 isn->isn_arg.number = number;
748
749 return OK;
750}
751
752/*
753 * Generate an ISN_PUSHBOOL instruction.
754 */
755 static int
756generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
757{
758 isn_T *isn;
759
Bram Moolenaar080457c2020-03-03 21:53:32 +0100760 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100761 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
762 return FAIL;
763 isn->isn_arg.number = number;
764
765 return OK;
766}
767
768/*
769 * Generate an ISN_PUSHSPEC instruction.
770 */
771 static int
772generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
773{
774 isn_T *isn;
775
Bram Moolenaar080457c2020-03-03 21:53:32 +0100776 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100777 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
778 return FAIL;
779 isn->isn_arg.number = number;
780
781 return OK;
782}
783
784#ifdef FEAT_FLOAT
785/*
786 * Generate an ISN_PUSHF instruction.
787 */
788 static int
789generate_PUSHF(cctx_T *cctx, float_T fnumber)
790{
791 isn_T *isn;
792
Bram Moolenaar080457c2020-03-03 21:53:32 +0100793 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100794 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
795 return FAIL;
796 isn->isn_arg.fnumber = fnumber;
797
798 return OK;
799}
800#endif
801
802/*
803 * Generate an ISN_PUSHS instruction.
804 * Consumes "str".
805 */
806 static int
807generate_PUSHS(cctx_T *cctx, char_u *str)
808{
809 isn_T *isn;
810
Bram Moolenaar080457c2020-03-03 21:53:32 +0100811 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100812 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
813 return FAIL;
814 isn->isn_arg.string = str;
815
816 return OK;
817}
818
819/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100820 * Generate an ISN_PUSHCHANNEL instruction.
821 * Consumes "channel".
822 */
823 static int
824generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
825{
826 isn_T *isn;
827
Bram Moolenaar080457c2020-03-03 21:53:32 +0100828 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100829 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
830 return FAIL;
831 isn->isn_arg.channel = channel;
832
833 return OK;
834}
835
836/*
837 * Generate an ISN_PUSHJOB instruction.
838 * Consumes "job".
839 */
840 static int
841generate_PUSHJOB(cctx_T *cctx, job_T *job)
842{
843 isn_T *isn;
844
Bram Moolenaar080457c2020-03-03 21:53:32 +0100845 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100846 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100847 return FAIL;
848 isn->isn_arg.job = job;
849
850 return OK;
851}
852
853/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100854 * Generate an ISN_PUSHBLOB instruction.
855 * Consumes "blob".
856 */
857 static int
858generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
859{
860 isn_T *isn;
861
Bram Moolenaar080457c2020-03-03 21:53:32 +0100862 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100863 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
864 return FAIL;
865 isn->isn_arg.blob = blob;
866
867 return OK;
868}
869
870/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100871 * Generate an ISN_PUSHFUNC instruction with name "name".
872 * Consumes "name".
873 */
874 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200875generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100876{
877 isn_T *isn;
878
Bram Moolenaar080457c2020-03-03 21:53:32 +0100879 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200880 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100881 return FAIL;
882 isn->isn_arg.string = name;
883
884 return OK;
885}
886
887/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100888 * Generate an ISN_STORE instruction.
889 */
890 static int
891generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
892{
893 isn_T *isn;
894
Bram Moolenaar080457c2020-03-03 21:53:32 +0100895 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100896 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
897 return FAIL;
898 if (name != NULL)
899 isn->isn_arg.string = vim_strsave(name);
900 else
901 isn->isn_arg.number = idx;
902
903 return OK;
904}
905
906/*
907 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
908 */
909 static int
910generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
911{
912 isn_T *isn;
913
Bram Moolenaar080457c2020-03-03 21:53:32 +0100914 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100915 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
916 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100917 isn->isn_arg.storenr.stnr_idx = idx;
918 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100919
920 return OK;
921}
922
923/*
924 * Generate an ISN_STOREOPT instruction
925 */
926 static int
927generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
928{
929 isn_T *isn;
930
Bram Moolenaar080457c2020-03-03 21:53:32 +0100931 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100932 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
933 return FAIL;
934 isn->isn_arg.storeopt.so_name = vim_strsave(name);
935 isn->isn_arg.storeopt.so_flags = opt_flags;
936
937 return OK;
938}
939
940/*
941 * Generate an ISN_LOAD or similar instruction.
942 */
943 static int
944generate_LOAD(
945 cctx_T *cctx,
946 isntype_T isn_type,
947 int idx,
948 char_u *name,
949 type_T *type)
950{
951 isn_T *isn;
952
Bram Moolenaar080457c2020-03-03 21:53:32 +0100953 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100954 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
955 return FAIL;
956 if (name != NULL)
957 isn->isn_arg.string = vim_strsave(name);
958 else
959 isn->isn_arg.number = idx;
960
961 return OK;
962}
963
964/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200965 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100966 */
967 static int
968generate_LOADV(
969 cctx_T *cctx,
970 char_u *name,
971 int error)
972{
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200973 int di_flags;
974 int vidx = find_vim_var(name, &di_flags);
975 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100976
Bram Moolenaar080457c2020-03-03 21:53:32 +0100977 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100978 if (vidx < 0)
979 {
980 if (error)
981 semsg(_(e_var_notfound), name);
982 return FAIL;
983 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200984 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100985
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200986 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100987}
988
989/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200990 * Generate an ISN_UNLET instruction.
991 */
992 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200993generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200994{
995 isn_T *isn;
996
997 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200998 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200999 return FAIL;
1000 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1001 isn->isn_arg.unlet.ul_forceit = forceit;
1002
1003 return OK;
1004}
1005
1006/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001007 * Generate an ISN_LOADS instruction.
1008 */
1009 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001010generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001012 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001013 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001014 int sid,
1015 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001016{
1017 isn_T *isn;
1018
Bram Moolenaar080457c2020-03-03 21:53:32 +01001019 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001020 if (isn_type == ISN_LOADS)
1021 isn = generate_instr_type(cctx, isn_type, type);
1022 else
1023 isn = generate_instr_drop(cctx, isn_type, 1);
1024 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001025 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001026 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1027 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001028
1029 return OK;
1030}
1031
1032/*
1033 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1034 */
1035 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001036generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001037 cctx_T *cctx,
1038 isntype_T isn_type,
1039 int sid,
1040 int idx,
1041 type_T *type)
1042{
1043 isn_T *isn;
1044
Bram Moolenaar080457c2020-03-03 21:53:32 +01001045 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001046 if (isn_type == ISN_LOADSCRIPT)
1047 isn = generate_instr_type(cctx, isn_type, type);
1048 else
1049 isn = generate_instr_drop(cctx, isn_type, 1);
1050 if (isn == NULL)
1051 return FAIL;
1052 isn->isn_arg.script.script_sid = sid;
1053 isn->isn_arg.script.script_idx = idx;
1054 return OK;
1055}
1056
1057/*
1058 * Generate an ISN_NEWLIST instruction.
1059 */
1060 static int
1061generate_NEWLIST(cctx_T *cctx, int count)
1062{
1063 isn_T *isn;
1064 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001065 type_T *type;
1066 type_T *member;
1067
Bram Moolenaar080457c2020-03-03 21:53:32 +01001068 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001069 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1070 return FAIL;
1071 isn->isn_arg.number = count;
1072
1073 // drop the value types
1074 stack->ga_len -= count;
1075
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001076 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001077 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001078 if (count > 0)
1079 member = ((type_T **)stack->ga_data)[stack->ga_len];
1080 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001081 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001082 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001083
1084 // add the list type to the type stack
1085 if (ga_grow(stack, 1) == FAIL)
1086 return FAIL;
1087 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1088 ++stack->ga_len;
1089
1090 return OK;
1091}
1092
1093/*
1094 * Generate an ISN_NEWDICT instruction.
1095 */
1096 static int
1097generate_NEWDICT(cctx_T *cctx, int count)
1098{
1099 isn_T *isn;
1100 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001101 type_T *type;
1102 type_T *member;
1103
Bram Moolenaar080457c2020-03-03 21:53:32 +01001104 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001105 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1106 return FAIL;
1107 isn->isn_arg.number = count;
1108
1109 // drop the key and value types
1110 stack->ga_len -= 2 * count;
1111
Bram Moolenaar436472f2020-02-20 22:54:43 +01001112 // Use the first value type for the list member type. Use "void" for an
1113 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001114 if (count > 0)
1115 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1116 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001117 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001118 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001119
1120 // add the dict type to the type stack
1121 if (ga_grow(stack, 1) == FAIL)
1122 return FAIL;
1123 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1124 ++stack->ga_len;
1125
1126 return OK;
1127}
1128
1129/*
1130 * Generate an ISN_FUNCREF instruction.
1131 */
1132 static int
1133generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1134{
1135 isn_T *isn;
1136 garray_T *stack = &cctx->ctx_type_stack;
1137
Bram Moolenaar080457c2020-03-03 21:53:32 +01001138 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001139 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1140 return FAIL;
1141 isn->isn_arg.number = dfunc_idx;
1142
1143 if (ga_grow(stack, 1) == FAIL)
1144 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001145 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001146 // TODO: argument and return types
1147 ++stack->ga_len;
1148
1149 return OK;
1150}
1151
1152/*
1153 * Generate an ISN_JUMP instruction.
1154 */
1155 static int
1156generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1157{
1158 isn_T *isn;
1159 garray_T *stack = &cctx->ctx_type_stack;
1160
Bram Moolenaar080457c2020-03-03 21:53:32 +01001161 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001162 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1163 return FAIL;
1164 isn->isn_arg.jump.jump_when = when;
1165 isn->isn_arg.jump.jump_where = where;
1166
1167 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1168 --stack->ga_len;
1169
1170 return OK;
1171}
1172
1173 static int
1174generate_FOR(cctx_T *cctx, int loop_idx)
1175{
1176 isn_T *isn;
1177 garray_T *stack = &cctx->ctx_type_stack;
1178
Bram Moolenaar080457c2020-03-03 21:53:32 +01001179 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001180 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1181 return FAIL;
1182 isn->isn_arg.forloop.for_idx = loop_idx;
1183
1184 if (ga_grow(stack, 1) == FAIL)
1185 return FAIL;
1186 // type doesn't matter, will be stored next
1187 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1188 ++stack->ga_len;
1189
1190 return OK;
1191}
1192
1193/*
1194 * Generate an ISN_BCALL instruction.
1195 * Return FAIL if the number of arguments is wrong.
1196 */
1197 static int
1198generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1199{
1200 isn_T *isn;
1201 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001202 type_T *argtypes[MAX_FUNC_ARGS];
1203 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001204
Bram Moolenaar080457c2020-03-03 21:53:32 +01001205 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001206 if (check_internal_func(func_idx, argcount) == FAIL)
1207 return FAIL;
1208
1209 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1210 return FAIL;
1211 isn->isn_arg.bfunc.cbf_idx = func_idx;
1212 isn->isn_arg.bfunc.cbf_argcount = argcount;
1213
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001214 for (i = 0; i < argcount; ++i)
1215 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1216
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001217 stack->ga_len -= argcount; // drop the arguments
1218 if (ga_grow(stack, 1) == FAIL)
1219 return FAIL;
1220 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001221 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001222 ++stack->ga_len; // add return value
1223
1224 return OK;
1225}
1226
1227/*
1228 * Generate an ISN_DCALL or ISN_UCALL instruction.
1229 * Return FAIL if the number of arguments is wrong.
1230 */
1231 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001232generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001233{
1234 isn_T *isn;
1235 garray_T *stack = &cctx->ctx_type_stack;
1236 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001237 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001238
Bram Moolenaar080457c2020-03-03 21:53:32 +01001239 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001240 if (argcount > regular_args && !has_varargs(ufunc))
1241 {
1242 semsg(_(e_toomanyarg), ufunc->uf_name);
1243 return FAIL;
1244 }
1245 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1246 {
1247 semsg(_(e_toofewarg), ufunc->uf_name);
1248 return FAIL;
1249 }
1250
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001251 if (ufunc->uf_dfunc_idx >= 0)
1252 {
1253 int i;
1254
1255 for (i = 0; i < argcount; ++i)
1256 {
1257 type_T *expected;
1258 type_T *actual;
1259
1260 if (i < regular_args)
1261 {
1262 if (ufunc->uf_arg_types == NULL)
1263 continue;
1264 expected = ufunc->uf_arg_types[i];
1265 }
1266 else
1267 expected = ufunc->uf_va_type->tt_member;
1268 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1269 if (check_type(expected, actual, FALSE) == FAIL)
1270 {
1271 arg_type_mismatch(expected, actual, i + 1);
1272 return FAIL;
1273 }
1274 }
1275 }
1276
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001277 if ((isn = generate_instr(cctx,
1278 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1279 return FAIL;
1280 if (ufunc->uf_dfunc_idx >= 0)
1281 {
1282 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1283 isn->isn_arg.dfunc.cdf_argcount = argcount;
1284 }
1285 else
1286 {
1287 // A user function may be deleted and redefined later, can't use the
1288 // ufunc pointer, need to look it up again at runtime.
1289 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1290 isn->isn_arg.ufunc.cuf_argcount = argcount;
1291 }
1292
1293 stack->ga_len -= argcount; // drop the arguments
1294 if (ga_grow(stack, 1) == FAIL)
1295 return FAIL;
1296 // add return value
1297 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1298 ++stack->ga_len;
1299
1300 return OK;
1301}
1302
1303/*
1304 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1305 */
1306 static int
1307generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1308{
1309 isn_T *isn;
1310 garray_T *stack = &cctx->ctx_type_stack;
1311
Bram Moolenaar080457c2020-03-03 21:53:32 +01001312 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001313 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1314 return FAIL;
1315 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1316 isn->isn_arg.ufunc.cuf_argcount = argcount;
1317
1318 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001319 if (ga_grow(stack, 1) == FAIL)
1320 return FAIL;
1321 // add return value
1322 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1323 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001324
1325 return OK;
1326}
1327
1328/*
1329 * Generate an ISN_PCALL instruction.
1330 */
1331 static int
1332generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1333{
1334 isn_T *isn;
1335 garray_T *stack = &cctx->ctx_type_stack;
1336
Bram Moolenaar080457c2020-03-03 21:53:32 +01001337 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001338
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001339 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1340 return FAIL;
1341 isn->isn_arg.pfunc.cpf_top = at_top;
1342 isn->isn_arg.pfunc.cpf_argcount = argcount;
1343
1344 stack->ga_len -= argcount; // drop the arguments
1345
1346 // drop the funcref/partial, get back the return value
1347 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1348
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001349 // If partial is above the arguments it must be cleared and replaced with
1350 // the return value.
1351 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1352 return FAIL;
1353
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001354 return OK;
1355}
1356
1357/*
1358 * Generate an ISN_MEMBER instruction.
1359 */
1360 static int
1361generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1362{
1363 isn_T *isn;
1364 garray_T *stack = &cctx->ctx_type_stack;
1365 type_T *type;
1366
Bram Moolenaar080457c2020-03-03 21:53:32 +01001367 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001368 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1369 return FAIL;
1370 isn->isn_arg.string = vim_strnsave(name, (int)len);
1371
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001372 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001373 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001374 if (type->tt_type != VAR_DICT && type != &t_any)
1375 {
1376 emsg(_(e_dictreq));
1377 return FAIL;
1378 }
1379 // change dict type to dict member type
1380 if (type->tt_type == VAR_DICT)
1381 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001382
1383 return OK;
1384}
1385
1386/*
1387 * Generate an ISN_ECHO instruction.
1388 */
1389 static int
1390generate_ECHO(cctx_T *cctx, int with_white, int count)
1391{
1392 isn_T *isn;
1393
Bram Moolenaar080457c2020-03-03 21:53:32 +01001394 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001395 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1396 return FAIL;
1397 isn->isn_arg.echo.echo_with_white = with_white;
1398 isn->isn_arg.echo.echo_count = count;
1399
1400 return OK;
1401}
1402
Bram Moolenaarad39c092020-02-26 18:23:43 +01001403/*
1404 * Generate an ISN_EXECUTE instruction.
1405 */
1406 static int
1407generate_EXECUTE(cctx_T *cctx, int count)
1408{
1409 isn_T *isn;
1410
1411 if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL)
1412 return FAIL;
1413 isn->isn_arg.number = count;
1414
1415 return OK;
1416}
1417
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001418 static int
1419generate_EXEC(cctx_T *cctx, char_u *line)
1420{
1421 isn_T *isn;
1422
Bram Moolenaar080457c2020-03-03 21:53:32 +01001423 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001424 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1425 return FAIL;
1426 isn->isn_arg.string = vim_strsave(line);
1427 return OK;
1428}
1429
1430static char e_white_both[] =
1431 N_("E1004: white space required before and after '%s'");
Bram Moolenaard77a8522020-04-03 21:59:57 +02001432static char e_white_after[] = N_("E1069: white space required after '%s'");
1433static char e_no_white_before[] = N_("E1068: No white space allowed before '%s'");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001434
1435/*
1436 * Reserve space for a local variable.
1437 * Return the index or -1 if it failed.
1438 */
1439 static int
1440reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1441{
1442 int idx;
1443 lvar_T *lvar;
1444
1445 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1446 {
1447 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1448 return -1;
1449 }
1450
1451 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1452 return -1;
1453 idx = cctx->ctx_locals.ga_len;
1454 if (cctx->ctx_max_local < idx + 1)
1455 cctx->ctx_max_local = idx + 1;
1456 ++cctx->ctx_locals.ga_len;
1457
1458 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1459 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1460 lvar->lv_const = isConst;
1461 lvar->lv_type = type;
1462
1463 return idx;
1464}
1465
1466/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001467 * Remove local variables above "new_top".
1468 */
1469 static void
1470unwind_locals(cctx_T *cctx, int new_top)
1471{
1472 if (cctx->ctx_locals.ga_len > new_top)
1473 {
1474 int idx;
1475 lvar_T *lvar;
1476
1477 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1478 {
1479 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1480 vim_free(lvar->lv_name);
1481 }
1482 }
1483 cctx->ctx_locals.ga_len = new_top;
1484}
1485
1486/*
1487 * Free all local variables.
1488 */
1489 static void
1490free_local(cctx_T *cctx)
1491{
1492 unwind_locals(cctx, 0);
1493 ga_clear(&cctx->ctx_locals);
1494}
1495
1496/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001497 * Skip over a type definition and return a pointer to just after it.
1498 */
1499 char_u *
1500skip_type(char_u *start)
1501{
1502 char_u *p = start;
1503
1504 while (ASCII_ISALNUM(*p) || *p == '_')
1505 ++p;
1506
1507 // Skip over "<type>"; this is permissive about white space.
1508 if (*skipwhite(p) == '<')
1509 {
1510 p = skipwhite(p);
1511 p = skip_type(skipwhite(p + 1));
1512 p = skipwhite(p);
1513 if (*p == '>')
1514 ++p;
1515 }
1516 return p;
1517}
1518
1519/*
1520 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001521 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001522 * Returns NULL in case of failure.
1523 */
1524 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001525parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001526{
1527 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001528 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001529
1530 if (**arg != '<')
1531 {
1532 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001533 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001534 else
1535 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001536 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001537 }
1538 *arg = skipwhite(*arg + 1);
1539
Bram Moolenaard77a8522020-04-03 21:59:57 +02001540 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001541
1542 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001543 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001544 {
1545 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001546 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001547 }
1548 ++*arg;
1549
1550 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001551 return get_list_type(member_type, type_gap);
1552 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001553}
1554
1555/*
1556 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001557 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001558 */
1559 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001560parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001561{
1562 char_u *p = *arg;
1563 size_t len;
1564
1565 // skip over the first word
1566 while (ASCII_ISALNUM(*p) || *p == '_')
1567 ++p;
1568 len = p - *arg;
1569
1570 switch (**arg)
1571 {
1572 case 'a':
1573 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1574 {
1575 *arg += len;
1576 return &t_any;
1577 }
1578 break;
1579 case 'b':
1580 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1581 {
1582 *arg += len;
1583 return &t_bool;
1584 }
1585 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1586 {
1587 *arg += len;
1588 return &t_blob;
1589 }
1590 break;
1591 case 'c':
1592 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1593 {
1594 *arg += len;
1595 return &t_channel;
1596 }
1597 break;
1598 case 'd':
1599 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1600 {
1601 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001602 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001603 }
1604 break;
1605 case 'f':
1606 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1607 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001608#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001609 *arg += len;
1610 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001611#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001612 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001613 return &t_any;
1614#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001615 }
1616 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1617 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001618 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001619 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001620 int argcount = -1;
1621 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001622 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001623 type_T *arg_type[MAX_FUNC_ARGS + 1];
1624
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001625 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001626 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001627 if (**arg == '(')
1628 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001629 // "func" may or may not return a value, "func()" does
1630 // not return a value.
1631 ret_type = &t_void;
1632
Bram Moolenaard77a8522020-04-03 21:59:57 +02001633 p = ++*arg;
1634 argcount = 0;
1635 while (*p != NUL && *p != ')')
1636 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001637 if (*p == '?')
1638 {
1639 if (first_optional == -1)
1640 first_optional = argcount;
1641 ++p;
1642 }
1643 else if (first_optional != -1)
1644 {
1645 emsg(_("E1007: mandatory argument after optional argument"));
1646 return &t_any;
1647 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001648 else if (STRNCMP(p, "...", 3) == 0)
1649 {
1650 flags |= TTFLAG_VARARGS;
1651 p += 3;
1652 }
1653
1654 arg_type[argcount++] = parse_type(&p, type_gap);
1655
1656 // Nothing comes after "...{type}".
1657 if (flags & TTFLAG_VARARGS)
1658 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001659
Bram Moolenaard77a8522020-04-03 21:59:57 +02001660 if (*p != ',' && *skipwhite(p) == ',')
1661 {
1662 semsg(_(e_no_white_before), ",");
1663 return &t_any;
1664 }
1665 if (*p == ',')
1666 {
1667 ++p;
1668 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001669 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001670 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001671 return &t_any;
1672 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001673 }
1674 p = skipwhite(p);
1675 if (argcount == MAX_FUNC_ARGS)
1676 {
1677 emsg(_("E740: Too many argument types"));
1678 return &t_any;
1679 }
1680 }
1681
1682 p = skipwhite(p);
1683 if (*p != ')')
1684 {
1685 emsg(_(e_missing_close));
1686 return &t_any;
1687 }
1688 *arg = p + 1;
1689 }
1690 if (**arg == ':')
1691 {
1692 // parse return type
1693 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001694 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001695 semsg(_(e_white_after), ":");
1696 *arg = skipwhite(*arg);
1697 ret_type = parse_type(arg, type_gap);
1698 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001699 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001700 type = get_func_type(ret_type, argcount, type_gap);
1701 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001702 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001703 type = alloc_func_type(ret_type, argcount, type_gap);
1704 type->tt_flags = flags;
1705 if (argcount > 0)
1706 {
1707 type->tt_argcount = argcount;
1708 type->tt_min_argcount = first_optional == -1
1709 ? argcount : first_optional;
1710 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001711 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001712 return &t_any;
1713 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001714 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001715 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001716 }
1717 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001718 }
1719 break;
1720 case 'j':
1721 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1722 {
1723 *arg += len;
1724 return &t_job;
1725 }
1726 break;
1727 case 'l':
1728 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1729 {
1730 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001731 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001732 }
1733 break;
1734 case 'n':
1735 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1736 {
1737 *arg += len;
1738 return &t_number;
1739 }
1740 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001741 case 's':
1742 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1743 {
1744 *arg += len;
1745 return &t_string;
1746 }
1747 break;
1748 case 'v':
1749 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1750 {
1751 *arg += len;
1752 return &t_void;
1753 }
1754 break;
1755 }
1756
1757 semsg(_("E1010: Type not recognized: %s"), *arg);
1758 return &t_any;
1759}
1760
1761/*
1762 * Check if "type1" and "type2" are exactly the same.
1763 */
1764 static int
1765equal_type(type_T *type1, type_T *type2)
1766{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001767 int i;
1768
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001769 if (type1->tt_type != type2->tt_type)
1770 return FALSE;
1771 switch (type1->tt_type)
1772 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001773 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001774 case VAR_ANY:
1775 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001776 case VAR_SPECIAL:
1777 case VAR_BOOL:
1778 case VAR_NUMBER:
1779 case VAR_FLOAT:
1780 case VAR_STRING:
1781 case VAR_BLOB:
1782 case VAR_JOB:
1783 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001784 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001785 case VAR_LIST:
1786 case VAR_DICT:
1787 return equal_type(type1->tt_member, type2->tt_member);
1788 case VAR_FUNC:
1789 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001790 if (!equal_type(type1->tt_member, type2->tt_member)
1791 || type1->tt_argcount != type2->tt_argcount)
1792 return FALSE;
1793 if (type1->tt_argcount < 0
1794 || type1->tt_args == NULL || type2->tt_args == NULL)
1795 return TRUE;
1796 for (i = 0; i < type1->tt_argcount; ++i)
1797 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1798 return FALSE;
1799 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001800 }
1801 return TRUE;
1802}
1803
1804/*
1805 * Find the common type of "type1" and "type2" and put it in "dest".
1806 * "type2" and "dest" may be the same.
1807 */
1808 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001809common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001810{
1811 if (equal_type(type1, type2))
1812 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001813 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001814 return;
1815 }
1816
1817 if (type1->tt_type == type2->tt_type)
1818 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001819 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1820 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001821 type_T *common;
1822
Bram Moolenaard77a8522020-04-03 21:59:57 +02001823 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001824 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001825 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001826 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001827 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001828 return;
1829 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001830 if (type1->tt_type == VAR_FUNC)
1831 {
1832 type_T *common;
1833
1834 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1835 if (type1->tt_argcount == type2->tt_argcount
1836 && type1->tt_argcount >= 0)
1837 {
1838 int argcount = type1->tt_argcount;
1839 int i;
1840
1841 *dest = alloc_func_type(common, argcount, type_gap);
1842 if (type1->tt_args != NULL && type2->tt_args != NULL)
1843 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001844 if (func_type_add_arg_types(*dest, argcount,
1845 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001846 for (i = 0; i < argcount; ++i)
1847 common_type(type1->tt_args[i], type2->tt_args[i],
1848 &(*dest)->tt_args[i], type_gap);
1849 }
1850 }
1851 else
1852 *dest = alloc_func_type(common, -1, type_gap);
1853 return;
1854 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001855 }
1856
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001857 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001858}
1859
1860 char *
1861vartype_name(vartype_T type)
1862{
1863 switch (type)
1864 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001865 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001866 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001867 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001868 case VAR_SPECIAL: return "special";
1869 case VAR_BOOL: return "bool";
1870 case VAR_NUMBER: return "number";
1871 case VAR_FLOAT: return "float";
1872 case VAR_STRING: return "string";
1873 case VAR_BLOB: return "blob";
1874 case VAR_JOB: return "job";
1875 case VAR_CHANNEL: return "channel";
1876 case VAR_LIST: return "list";
1877 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001878
1879 case VAR_FUNC:
1880 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001881 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001882 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001883}
1884
1885/*
1886 * Return the name of a type.
1887 * The result may be in allocated memory, in which case "tofree" is set.
1888 */
1889 char *
1890type_name(type_T *type, char **tofree)
1891{
1892 char *name = vartype_name(type->tt_type);
1893
1894 *tofree = NULL;
1895 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1896 {
1897 char *member_free;
1898 char *member_name = type_name(type->tt_member, &member_free);
1899 size_t len;
1900
1901 len = STRLEN(name) + STRLEN(member_name) + 3;
1902 *tofree = alloc(len);
1903 if (*tofree != NULL)
1904 {
1905 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1906 vim_free(member_free);
1907 return *tofree;
1908 }
1909 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001910 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001911 {
1912 garray_T ga;
1913 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001914 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001915
1916 ga_init2(&ga, 1, 100);
1917 if (ga_grow(&ga, 20) == FAIL)
1918 return "[unknown]";
1919 *tofree = ga.ga_data;
1920 STRCPY(ga.ga_data, "func(");
1921 ga.ga_len += 5;
1922
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001923 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001924 {
1925 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001926 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001927 int len;
1928
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001929 if (type->tt_args == NULL)
1930 arg_type = "[unknown]";
1931 else
1932 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001933 if (i > 0)
1934 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001935 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001936 ga.ga_len += 2;
1937 }
1938 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001939 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001940 {
1941 vim_free(arg_free);
1942 return "[unknown]";
1943 }
1944 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001945 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001946 {
1947 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1948 ga.ga_len += 3;
1949 }
1950 else if (i >= type->tt_min_argcount)
1951 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001952 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001953 ga.ga_len += len;
1954 vim_free(arg_free);
1955 }
1956
1957 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001958 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001959 else
1960 {
1961 char *ret_free;
1962 char *ret_name = type_name(type->tt_member, &ret_free);
1963 int len;
1964
1965 len = (int)STRLEN(ret_name) + 4;
1966 if (ga_grow(&ga, len) == FAIL)
1967 {
1968 vim_free(ret_free);
1969 return "[unknown]";
1970 }
1971 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001972 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1973 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001974 vim_free(ret_free);
1975 }
1976 return ga.ga_data;
1977 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001978
1979 return name;
1980}
1981
1982/*
1983 * Find "name" in script-local items of script "sid".
1984 * Returns the index in "sn_var_vals" if found.
1985 * If found but not in "sn_var_vals" returns -1.
1986 * If not found returns -2.
1987 */
1988 int
1989get_script_item_idx(int sid, char_u *name, int check_writable)
1990{
1991 hashtab_T *ht;
1992 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001993 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001994 int idx;
1995
1996 // First look the name up in the hashtable.
1997 if (sid <= 0 || sid > script_items.ga_len)
1998 return -1;
1999 ht = &SCRIPT_VARS(sid);
2000 di = find_var_in_ht(ht, 0, name, TRUE);
2001 if (di == NULL)
2002 return -2;
2003
2004 // Now find the svar_T index in sn_var_vals.
2005 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2006 {
2007 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2008
2009 if (sv->sv_tv == &di->di_tv)
2010 {
2011 if (check_writable && sv->sv_const)
2012 semsg(_(e_readonlyvar), name);
2013 return idx;
2014 }
2015 }
2016 return -1;
2017}
2018
2019/*
2020 * Find "name" in imported items of the current script/
2021 */
2022 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002023find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002024{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002025 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002026 int idx;
2027
2028 if (cctx != NULL)
2029 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2030 {
2031 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2032 + idx;
2033
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002034 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2035 : STRLEN(import->imp_name) == len
2036 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002037 return import;
2038 }
2039
2040 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2041 {
2042 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2043
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002044 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2045 : STRLEN(import->imp_name) == len
2046 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002047 return import;
2048 }
2049 return NULL;
2050}
2051
2052/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002053 * Free all imported variables.
2054 */
2055 static void
2056free_imported(cctx_T *cctx)
2057{
2058 int idx;
2059
2060 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2061 {
2062 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2063
2064 vim_free(import->imp_name);
2065 }
2066 ga_clear(&cctx->ctx_imports);
2067}
2068
2069/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002070 * Get the next line of the function from "cctx".
2071 * Returns NULL when at the end.
2072 */
2073 static char_u *
2074next_line_from_context(cctx_T *cctx)
2075{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002076 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002077
2078 do
2079 {
2080 ++cctx->ctx_lnum;
2081 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002082 {
2083 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002084 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002085 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002086 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002087 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002088 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2089 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002090 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002091 return line;
2092}
2093
2094/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002095 * Return TRUE if "p" points at a "#" but not at "#{".
2096 */
2097 static int
2098comment_start(char_u *p)
2099{
2100 return p[0] == '#' && p[1] != '{';
2101}
2102
2103/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002104 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002105 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002106 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2107 */
2108 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002109may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002110{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002111 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002112 {
2113 char_u *next = next_line_from_context(cctx);
2114
2115 if (next == NULL)
2116 return FAIL;
2117 *arg = skipwhite(next);
2118 }
2119 return OK;
2120}
2121
2122/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002123 * Generate an instruction to load script-local variable "name", without the
2124 * leading "s:".
2125 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002126 */
2127 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002128compile_load_scriptvar(
2129 cctx_T *cctx,
2130 char_u *name, // variable NUL terminated
2131 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002132 char_u **end, // end of variable
2133 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002134{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002135 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002136 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2137 imported_T *import;
2138
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002139 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002140 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002141 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002142 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2143 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002144 }
2145 if (idx >= 0)
2146 {
2147 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2148
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002149 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002150 current_sctx.sc_sid, idx, sv->sv_type);
2151 return OK;
2152 }
2153
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002154 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002155 if (import != NULL)
2156 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002157 if (import->imp_all)
2158 {
2159 char_u *p = skipwhite(*end);
2160 int name_len;
2161 ufunc_T *ufunc;
2162 type_T *type;
2163
2164 // Used "import * as Name", need to lookup the member.
2165 if (*p != '.')
2166 {
2167 semsg(_("E1060: expected dot after name: %s"), start);
2168 return FAIL;
2169 }
2170 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002171 if (VIM_ISWHITE(*p))
2172 {
2173 emsg(_("E1074: no white space allowed after dot"));
2174 return FAIL;
2175 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002176
2177 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2178 // TODO: what if it is a function?
2179 if (idx < 0)
2180 return FAIL;
2181 *end = p;
2182
2183 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2184 import->imp_sid,
2185 idx,
2186 type);
2187 }
2188 else
2189 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002190 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002191 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2192 import->imp_sid,
2193 import->imp_var_vals_idx,
2194 import->imp_type);
2195 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002196 return OK;
2197 }
2198
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002199 if (error)
2200 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002201 return FAIL;
2202}
2203
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002204 static int
2205generate_funcref(cctx_T *cctx, char_u *name)
2206{
2207 ufunc_T *ufunc = find_func(name, cctx);
2208
2209 if (ufunc == NULL)
2210 return FAIL;
2211
2212 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2213}
2214
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002215/*
2216 * Compile a variable name into a load instruction.
2217 * "end" points to just after the name.
2218 * When "error" is FALSE do not give an error when not found.
2219 */
2220 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002221compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002222{
2223 type_T *type;
2224 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002225 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002226 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002227 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002228
2229 if (*(*arg + 1) == ':')
2230 {
2231 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002232 if (end <= *arg + 2)
2233 name = vim_strsave((char_u *)"[empty]");
2234 else
2235 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002236 if (name == NULL)
2237 return FAIL;
2238
2239 if (**arg == 'v')
2240 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002241 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002242 }
2243 else if (**arg == 'g')
2244 {
2245 // Global variables can be defined later, thus we don't check if it
2246 // exists, give error at runtime.
2247 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2248 }
2249 else if (**arg == 's')
2250 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002251 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002252 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002253 else if (**arg == 'b')
2254 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002255 // Buffer-local variables can be defined later, thus we don't check
2256 // if it exists, give error at runtime.
2257 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002258 }
2259 else if (**arg == 'w')
2260 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002261 // Window-local variables can be defined later, thus we don't check
2262 // if it exists, give error at runtime.
2263 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002264 }
2265 else if (**arg == 't')
2266 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002267 // Tabpage-local variables can be defined later, thus we don't
2268 // check if it exists, give error at runtime.
2269 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002270 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002271 else
2272 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002273 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002274 goto theend;
2275 }
2276 }
2277 else
2278 {
2279 size_t len = end - *arg;
2280 int idx;
2281 int gen_load = FALSE;
2282
2283 name = vim_strnsave(*arg, end - *arg);
2284 if (name == NULL)
2285 return FAIL;
2286
2287 idx = lookup_arg(*arg, len, cctx);
2288 if (idx >= 0)
2289 {
2290 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2291 type = cctx->ctx_ufunc->uf_arg_types[idx];
2292 else
2293 type = &t_any;
2294
2295 // Arguments are located above the frame pointer.
2296 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2297 if (cctx->ctx_ufunc->uf_va_name != NULL)
2298 --idx;
2299 gen_load = TRUE;
2300 }
2301 else if (lookup_vararg(*arg, len, cctx))
2302 {
2303 // varargs is always the last argument
2304 idx = -STACK_FRAME_SIZE - 1;
2305 type = cctx->ctx_ufunc->uf_va_type;
2306 gen_load = TRUE;
2307 }
2308 else
2309 {
2310 idx = lookup_local(*arg, len, cctx);
2311 if (idx >= 0)
2312 {
2313 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2314 gen_load = TRUE;
2315 }
2316 else
2317 {
2318 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2319 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2320 res = generate_PUSHBOOL(cctx, **arg == 't'
2321 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002322 else
2323 {
2324 // "var" can be script-local even without using "s:" if it
2325 // already exists.
2326 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2327 == SCRIPT_VERSION_VIM9
2328 || lookup_script(*arg, len) == OK)
2329 res = compile_load_scriptvar(cctx, name, *arg, &end,
2330 FALSE);
2331
2332 // When the name starts with an uppercase letter or "x:" it
2333 // can be a user defined function.
2334 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2335 res = generate_funcref(cctx, name);
2336 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002337 }
2338 }
2339 if (gen_load)
2340 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2341 }
2342
2343 *arg = end;
2344
2345theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002346 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002347 semsg(_(e_var_notfound), name);
2348 vim_free(name);
2349 return res;
2350}
2351
2352/*
2353 * Compile the argument expressions.
2354 * "arg" points to just after the "(" and is advanced to after the ")"
2355 */
2356 static int
2357compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2358{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002359 char_u *p = *arg;
2360 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002361
Bram Moolenaare6085c52020-04-12 20:19:16 +02002362 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002363 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002364 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002365 {
2366 p = next_line_from_context(cctx);
2367 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002368 goto failret;
2369 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002370 p = skipwhite(p);
2371 }
2372 if (*p == ')')
2373 {
2374 *arg = p + 1;
2375 return OK;
2376 }
2377
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002378 if (compile_expr1(&p, cctx) == FAIL)
2379 return FAIL;
2380 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002381
2382 if (*p != ',' && *skipwhite(p) == ',')
2383 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002384 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002385 p = skipwhite(p);
2386 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002387 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002388 {
2389 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002390 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002391 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002392 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002393 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002394 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002396failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002397 emsg(_(e_missing_close));
2398 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002399}
2400
2401/*
2402 * Compile a function call: name(arg1, arg2)
2403 * "arg" points to "name", "arg + varlen" to the "(".
2404 * "argcount_init" is 1 for "value->method()"
2405 * Instructions:
2406 * EVAL arg1
2407 * EVAL arg2
2408 * BCALL / DCALL / UCALL
2409 */
2410 static int
2411compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2412{
2413 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002414 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002415 int argcount = argcount_init;
2416 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002417 char_u fname_buf[FLEN_FIXED + 1];
2418 char_u *tofree = NULL;
2419 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002420 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002421 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002422
2423 if (varlen >= sizeof(namebuf))
2424 {
2425 semsg(_("E1011: name too long: %s"), name);
2426 return FAIL;
2427 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002428 vim_strncpy(namebuf, *arg, varlen);
2429 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002430
2431 *arg = skipwhite(*arg + varlen + 1);
2432 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002433 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002434
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002435 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002436 {
2437 int idx;
2438
2439 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002440 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002441 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002442 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002443 else
2444 semsg(_(e_unknownfunc), namebuf);
2445 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002446 }
2447
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002448 // If we can find the function by name generate the right call.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002449 ufunc = find_func(name, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002450 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002451 {
2452 res = generate_CALL(cctx, ufunc, argcount);
2453 goto theend;
2454 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002455
2456 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002457 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002458 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002459 if (STRNCMP(namebuf, "g:", 2) != 0
2460 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002461 {
2462 res = generate_PCALL(cctx, argcount, FALSE);
2463 goto theend;
2464 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002465
2466 // The function may be defined only later. Need to figure out at runtime.
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002467 res = generate_UCALL(cctx, name, argcount);
2468
2469theend:
2470 vim_free(tofree);
2471 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002472}
2473
2474// like NAMESPACE_CHAR but with 'a' and 'l'.
2475#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2476
2477/*
2478 * Find the end of a variable or function name. Unlike find_name_end() this
2479 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002480 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002481 * Return a pointer to just after the name. Equal to "arg" if there is no
2482 * valid name.
2483 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002484 static char_u *
2485to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002486{
2487 char_u *p;
2488
2489 // Quick check for valid starting character.
2490 if (!eval_isnamec1(*arg))
2491 return arg;
2492
2493 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2494 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2495 // and can be used in slice "[n:]".
2496 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002497 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002498 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2499 break;
2500 return p;
2501}
2502
2503/*
2504 * Like to_name_end() but also skip over a list or dict constant.
2505 */
2506 char_u *
2507to_name_const_end(char_u *arg)
2508{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002509 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002510 typval_T rettv;
2511
2512 if (p == arg && *arg == '[')
2513 {
2514
2515 // Can be "[1, 2, 3]->Func()".
2516 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2517 p = arg;
2518 }
2519 else if (p == arg && *arg == '#' && arg[1] == '{')
2520 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002521 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002522 ++p;
2523 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2524 p = arg;
2525 }
2526 else if (p == arg && *arg == '{')
2527 {
2528 int ret = get_lambda_tv(&p, &rettv, FALSE);
2529
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002530 // Can be "{x -> ret}()".
2531 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002532 if (ret == NOTDONE)
2533 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2534 if (ret != OK)
2535 p = arg;
2536 }
2537
2538 return p;
2539}
2540
2541 static void
2542type_mismatch(type_T *expected, type_T *actual)
2543{
2544 char *tofree1, *tofree2;
2545
2546 semsg(_("E1013: type mismatch, expected %s but got %s"),
2547 type_name(expected, &tofree1), type_name(actual, &tofree2));
2548 vim_free(tofree1);
2549 vim_free(tofree2);
2550}
2551
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002552 static void
2553arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2554{
2555 char *tofree1, *tofree2;
2556
2557 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2558 argidx,
2559 type_name(expected, &tofree1), type_name(actual, &tofree2));
2560 vim_free(tofree1);
2561 vim_free(tofree2);
2562}
2563
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002564/*
2565 * Check if the expected and actual types match.
2566 */
2567 static int
2568check_type(type_T *expected, type_T *actual, int give_msg)
2569{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002570 int ret = OK;
2571
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002572 // When expected is "unknown" we accept any actual type.
2573 // When expected is "any" we accept any actual type except "void".
2574 if (expected->tt_type != VAR_UNKNOWN
2575 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002576 {
2577 if (expected->tt_type != actual->tt_type)
2578 {
2579 if (give_msg)
2580 type_mismatch(expected, actual);
2581 return FAIL;
2582 }
2583 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2584 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002585 // "unknown" is used for an empty list or dict
2586 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002587 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002588 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002589 else if (expected->tt_type == VAR_FUNC)
2590 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002591 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002592 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2593 if (ret == OK && expected->tt_argcount != -1
2594 && (actual->tt_argcount < expected->tt_min_argcount
2595 || actual->tt_argcount > expected->tt_argcount))
2596 ret = FAIL;
2597 }
2598 if (ret == FAIL && give_msg)
2599 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002600 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002601 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002602}
2603
2604/*
2605 * Check that
2606 * - "actual" is "expected" type or
2607 * - "actual" is a type that can be "expected" type: add a runtime check; or
2608 * - return FAIL.
2609 */
2610 static int
2611need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2612{
Bram Moolenaar89228602020-04-05 22:14:54 +02002613 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002614 return OK;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002615 if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002616 {
2617 type_mismatch(expected, actual);
2618 return FAIL;
2619 }
2620 generate_TYPECHECK(cctx, expected, offset);
2621 return OK;
2622}
2623
2624/*
2625 * parse a list: [expr, expr]
2626 * "*arg" points to the '['.
2627 */
2628 static int
2629compile_list(char_u **arg, cctx_T *cctx)
2630{
2631 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002632 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002633 int count = 0;
2634
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002635 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002636 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002637 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002638 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002639 p = next_line_from_context(cctx);
2640 if (p == NULL)
2641 {
2642 semsg(_(e_list_end), *arg);
2643 return FAIL;
2644 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002645 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002646 p = skipwhite(p);
2647 }
2648 if (*p == ']')
2649 {
2650 ++p;
2651 // Allow for following comment, after at least one space.
2652 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2653 p += STRLEN(p);
2654 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002655 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002656 if (compile_expr1(&p, cctx) == FAIL)
2657 break;
2658 ++count;
2659 if (*p == ',')
2660 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002661 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002662 p = skipwhite(p);
2663 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002664 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002665
2666 generate_NEWLIST(cctx, count);
2667 return OK;
2668}
2669
2670/*
2671 * parse a lambda: {arg, arg -> expr}
2672 * "*arg" points to the '{'.
2673 */
2674 static int
2675compile_lambda(char_u **arg, cctx_T *cctx)
2676{
2677 garray_T *instr = &cctx->ctx_instr;
2678 typval_T rettv;
2679 ufunc_T *ufunc;
2680
2681 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002682 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002683 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002684
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002685 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002686 ++ufunc->uf_refcount;
2687 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002688 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002689
2690 // The function will have one line: "return {expr}".
2691 // Compile it into instructions.
2692 compile_def_function(ufunc, TRUE);
2693
2694 if (ufunc->uf_dfunc_idx >= 0)
2695 {
2696 if (ga_grow(instr, 1) == FAIL)
2697 return FAIL;
2698 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2699 return OK;
2700 }
2701 return FAIL;
2702}
2703
2704/*
2705 * Compile a lamda call: expr->{lambda}(args)
2706 * "arg" points to the "{".
2707 */
2708 static int
2709compile_lambda_call(char_u **arg, cctx_T *cctx)
2710{
2711 ufunc_T *ufunc;
2712 typval_T rettv;
2713 int argcount = 1;
2714 int ret = FAIL;
2715
2716 // Get the funcref in "rettv".
2717 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2718 return FAIL;
2719
2720 if (**arg != '(')
2721 {
2722 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002723 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002724 else
2725 semsg(_(e_missing_paren), "lambda");
2726 clear_tv(&rettv);
2727 return FAIL;
2728 }
2729
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002730 ufunc = rettv.vval.v_partial->pt_func;
2731 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002732 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002733 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002734
2735 // The function will have one line: "return {expr}".
2736 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002737 compile_def_function(ufunc, TRUE);
2738
2739 // compile the arguments
2740 *arg = skipwhite(*arg + 1);
2741 if (compile_arguments(arg, cctx, &argcount) == OK)
2742 // call the compiled function
2743 ret = generate_CALL(cctx, ufunc, argcount);
2744
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002745 return ret;
2746}
2747
2748/*
2749 * parse a dict: {'key': val} or #{key: val}
2750 * "*arg" points to the '{'.
2751 */
2752 static int
2753compile_dict(char_u **arg, cctx_T *cctx, int literal)
2754{
2755 garray_T *instr = &cctx->ctx_instr;
2756 int count = 0;
2757 dict_T *d = dict_alloc();
2758 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002759 char_u *whitep = *arg;
2760 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002761
2762 if (d == NULL)
2763 return FAIL;
2764 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002765 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002766 {
2767 char_u *key = NULL;
2768
Bram Moolenaar2c330432020-04-13 14:41:35 +02002769 while (**arg == NUL || (literal && **arg == '"')
2770 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002771 {
2772 *arg = next_line_from_context(cctx);
2773 if (*arg == NULL)
2774 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002775 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002776 *arg = skipwhite(*arg);
2777 }
2778
2779 if (**arg == '}')
2780 break;
2781
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002782 if (literal)
2783 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002784 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002785
Bram Moolenaar2c330432020-04-13 14:41:35 +02002786 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002787 {
2788 semsg(_("E1014: Invalid key: %s"), *arg);
2789 return FAIL;
2790 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002791 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002792 if (generate_PUSHS(cctx, key) == FAIL)
2793 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002794 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002795 }
2796 else
2797 {
2798 isn_T *isn;
2799
2800 if (compile_expr1(arg, cctx) == FAIL)
2801 return FAIL;
2802 // TODO: check type is string
2803 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2804 if (isn->isn_type == ISN_PUSHS)
2805 key = isn->isn_arg.string;
2806 }
2807
2808 // Check for duplicate keys, if using string keys.
2809 if (key != NULL)
2810 {
2811 item = dict_find(d, key, -1);
2812 if (item != NULL)
2813 {
2814 semsg(_(e_duplicate_key), key);
2815 goto failret;
2816 }
2817 item = dictitem_alloc(key);
2818 if (item != NULL)
2819 {
2820 item->di_tv.v_type = VAR_UNKNOWN;
2821 item->di_tv.v_lock = 0;
2822 if (dict_add(d, item) == FAIL)
2823 dictitem_free(item);
2824 }
2825 }
2826
2827 *arg = skipwhite(*arg);
2828 if (**arg != ':')
2829 {
2830 semsg(_(e_missing_dict_colon), *arg);
2831 return FAIL;
2832 }
2833
Bram Moolenaar2c330432020-04-13 14:41:35 +02002834 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002835 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002836 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002837 {
2838 *arg = next_line_from_context(cctx);
2839 if (*arg == NULL)
2840 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002841 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002842 *arg = skipwhite(*arg);
2843 }
2844
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002845 if (compile_expr1(arg, cctx) == FAIL)
2846 return FAIL;
2847 ++count;
2848
Bram Moolenaar2c330432020-04-13 14:41:35 +02002849 whitep = *arg;
2850 p = skipwhite(*arg);
2851 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002852 {
2853 *arg = next_line_from_context(cctx);
2854 if (*arg == NULL)
2855 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002856 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002857 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002858 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002859 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002860 if (**arg == '}')
2861 break;
2862 if (**arg != ',')
2863 {
2864 semsg(_(e_missing_dict_comma), *arg);
2865 goto failret;
2866 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002867 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002868 *arg = skipwhite(*arg + 1);
2869 }
2870
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002871 *arg = *arg + 1;
2872
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002873 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002874 p = skipwhite(*arg);
2875 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002876 *arg += STRLEN(*arg);
2877
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002878 dict_unref(d);
2879 return generate_NEWDICT(cctx, count);
2880
2881failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002882 if (*arg == NULL)
2883 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002884 dict_unref(d);
2885 return FAIL;
2886}
2887
2888/*
2889 * Compile "&option".
2890 */
2891 static int
2892compile_get_option(char_u **arg, cctx_T *cctx)
2893{
2894 typval_T rettv;
2895 char_u *start = *arg;
2896 int ret;
2897
2898 // parse the option and get the current value to get the type.
2899 rettv.v_type = VAR_UNKNOWN;
2900 ret = get_option_tv(arg, &rettv, TRUE);
2901 if (ret == OK)
2902 {
2903 // include the '&' in the name, get_option_tv() expects it.
2904 char_u *name = vim_strnsave(start, *arg - start);
2905 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2906
2907 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2908 vim_free(name);
2909 }
2910 clear_tv(&rettv);
2911
2912 return ret;
2913}
2914
2915/*
2916 * Compile "$VAR".
2917 */
2918 static int
2919compile_get_env(char_u **arg, cctx_T *cctx)
2920{
2921 char_u *start = *arg;
2922 int len;
2923 int ret;
2924 char_u *name;
2925
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002926 ++*arg;
2927 len = get_env_len(arg);
2928 if (len == 0)
2929 {
2930 semsg(_(e_syntax_at), start - 1);
2931 return FAIL;
2932 }
2933
2934 // include the '$' in the name, get_env_tv() expects it.
2935 name = vim_strnsave(start, len + 1);
2936 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2937 vim_free(name);
2938 return ret;
2939}
2940
2941/*
2942 * Compile "@r".
2943 */
2944 static int
2945compile_get_register(char_u **arg, cctx_T *cctx)
2946{
2947 int ret;
2948
2949 ++*arg;
2950 if (**arg == NUL)
2951 {
2952 semsg(_(e_syntax_at), *arg - 1);
2953 return FAIL;
2954 }
2955 if (!valid_yank_reg(**arg, TRUE))
2956 {
2957 emsg_invreg(**arg);
2958 return FAIL;
2959 }
2960 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2961 ++*arg;
2962 return ret;
2963}
2964
2965/*
2966 * Apply leading '!', '-' and '+' to constant "rettv".
2967 */
2968 static int
2969apply_leader(typval_T *rettv, char_u *start, char_u *end)
2970{
2971 char_u *p = end;
2972
2973 // this works from end to start
2974 while (p > start)
2975 {
2976 --p;
2977 if (*p == '-' || *p == '+')
2978 {
2979 // only '-' has an effect, for '+' we only check the type
2980#ifdef FEAT_FLOAT
2981 if (rettv->v_type == VAR_FLOAT)
2982 {
2983 if (*p == '-')
2984 rettv->vval.v_float = -rettv->vval.v_float;
2985 }
2986 else
2987#endif
2988 {
2989 varnumber_T val;
2990 int error = FALSE;
2991
2992 // tv_get_number_chk() accepts a string, but we don't want that
2993 // here
2994 if (check_not_string(rettv) == FAIL)
2995 return FAIL;
2996 val = tv_get_number_chk(rettv, &error);
2997 clear_tv(rettv);
2998 if (error)
2999 return FAIL;
3000 if (*p == '-')
3001 val = -val;
3002 rettv->v_type = VAR_NUMBER;
3003 rettv->vval.v_number = val;
3004 }
3005 }
3006 else
3007 {
3008 int v = tv2bool(rettv);
3009
3010 // '!' is permissive in the type.
3011 clear_tv(rettv);
3012 rettv->v_type = VAR_BOOL;
3013 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3014 }
3015 }
3016 return OK;
3017}
3018
3019/*
3020 * Recognize v: variables that are constants and set "rettv".
3021 */
3022 static void
3023get_vim_constant(char_u **arg, typval_T *rettv)
3024{
3025 if (STRNCMP(*arg, "v:true", 6) == 0)
3026 {
3027 rettv->v_type = VAR_BOOL;
3028 rettv->vval.v_number = VVAL_TRUE;
3029 *arg += 6;
3030 }
3031 else if (STRNCMP(*arg, "v:false", 7) == 0)
3032 {
3033 rettv->v_type = VAR_BOOL;
3034 rettv->vval.v_number = VVAL_FALSE;
3035 *arg += 7;
3036 }
3037 else if (STRNCMP(*arg, "v:null", 6) == 0)
3038 {
3039 rettv->v_type = VAR_SPECIAL;
3040 rettv->vval.v_number = VVAL_NULL;
3041 *arg += 6;
3042 }
3043 else if (STRNCMP(*arg, "v:none", 6) == 0)
3044 {
3045 rettv->v_type = VAR_SPECIAL;
3046 rettv->vval.v_number = VVAL_NONE;
3047 *arg += 6;
3048 }
3049}
3050
3051/*
3052 * Compile code to apply '-', '+' and '!'.
3053 */
3054 static int
3055compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3056{
3057 char_u *p = end;
3058
3059 // this works from end to start
3060 while (p > start)
3061 {
3062 --p;
3063 if (*p == '-' || *p == '+')
3064 {
3065 int negate = *p == '-';
3066 isn_T *isn;
3067
3068 // TODO: check type
3069 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3070 {
3071 --p;
3072 if (*p == '-')
3073 negate = !negate;
3074 }
3075 // only '-' has an effect, for '+' we only check the type
3076 if (negate)
3077 isn = generate_instr(cctx, ISN_NEGATENR);
3078 else
3079 isn = generate_instr(cctx, ISN_CHECKNR);
3080 if (isn == NULL)
3081 return FAIL;
3082 }
3083 else
3084 {
3085 int invert = TRUE;
3086
3087 while (p > start && p[-1] == '!')
3088 {
3089 --p;
3090 invert = !invert;
3091 }
3092 if (generate_2BOOL(cctx, invert) == FAIL)
3093 return FAIL;
3094 }
3095 }
3096 return OK;
3097}
3098
3099/*
3100 * Compile whatever comes after "name" or "name()".
3101 */
3102 static int
3103compile_subscript(
3104 char_u **arg,
3105 cctx_T *cctx,
3106 char_u **start_leader,
3107 char_u *end_leader)
3108{
3109 for (;;)
3110 {
3111 if (**arg == '(')
3112 {
3113 int argcount = 0;
3114
3115 // funcref(arg)
3116 *arg = skipwhite(*arg + 1);
3117 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3118 return FAIL;
3119 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
3120 return FAIL;
3121 }
3122 else if (**arg == '-' && (*arg)[1] == '>')
3123 {
3124 char_u *p;
3125
3126 // something->method()
3127 // Apply the '!', '-' and '+' first:
3128 // -1.0->func() works like (-1.0)->func()
3129 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3130 return FAIL;
3131 *start_leader = end_leader; // don't apply again later
3132
3133 *arg = skipwhite(*arg + 2);
3134 if (**arg == '{')
3135 {
3136 // lambda call: list->{lambda}
3137 if (compile_lambda_call(arg, cctx) == FAIL)
3138 return FAIL;
3139 }
3140 else
3141 {
3142 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003143 p = *arg;
3144 if (ASCII_ISALPHA(*p) && p[1] == ':')
3145 p += 2;
3146 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003147 ;
3148 if (*p != '(')
3149 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003150 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003151 return FAIL;
3152 }
3153 // TODO: base value may not be the first argument
3154 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3155 return FAIL;
3156 }
3157 }
3158 else if (**arg == '[')
3159 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003160 garray_T *stack;
3161 type_T **typep;
3162
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003163 // list index: list[123]
3164 // TODO: more arguments
3165 // TODO: dict member dict['name']
3166 *arg = skipwhite(*arg + 1);
3167 if (compile_expr1(arg, cctx) == FAIL)
3168 return FAIL;
3169
3170 if (**arg != ']')
3171 {
3172 emsg(_(e_missbrac));
3173 return FAIL;
3174 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003175 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003176
3177 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3178 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003179 stack = &cctx->ctx_type_stack;
3180 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3181 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3182 {
3183 emsg(_(e_listreq));
3184 return FAIL;
3185 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003186 if ((*typep)->tt_type == VAR_LIST)
3187 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003188 }
3189 else if (**arg == '.' && (*arg)[1] != '.')
3190 {
3191 char_u *p;
3192
3193 ++*arg;
3194 p = *arg;
3195 // dictionary member: dict.name
3196 if (eval_isnamec1(*p))
3197 while (eval_isnamec(*p))
3198 MB_PTR_ADV(p);
3199 if (p == *arg)
3200 {
3201 semsg(_(e_syntax_at), *arg);
3202 return FAIL;
3203 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003204 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3205 return FAIL;
3206 *arg = p;
3207 }
3208 else
3209 break;
3210 }
3211
3212 // TODO - see handle_subscript():
3213 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3214 // Don't do this when "Func" is already a partial that was bound
3215 // explicitly (pt_auto is FALSE).
3216
3217 return OK;
3218}
3219
3220/*
3221 * Compile an expression at "*p" and add instructions to "instr".
3222 * "p" is advanced until after the expression, skipping white space.
3223 *
3224 * This is the equivalent of eval1(), eval2(), etc.
3225 */
3226
3227/*
3228 * number number constant
3229 * 0zFFFFFFFF Blob constant
3230 * "string" string constant
3231 * 'string' literal string constant
3232 * &option-name option value
3233 * @r register contents
3234 * identifier variable value
3235 * function() function call
3236 * $VAR environment variable
3237 * (expression) nested expression
3238 * [expr, expr] List
3239 * {key: val, key: val} Dictionary
3240 * #{key: val, key: val} Dictionary with literal keys
3241 *
3242 * Also handle:
3243 * ! in front logical NOT
3244 * - in front unary minus
3245 * + in front unary plus (ignored)
3246 * trailing (arg) funcref/partial call
3247 * trailing [] subscript in String or List
3248 * trailing .name entry in Dictionary
3249 * trailing ->name() method call
3250 */
3251 static int
3252compile_expr7(char_u **arg, cctx_T *cctx)
3253{
3254 typval_T rettv;
3255 char_u *start_leader, *end_leader;
3256 int ret = OK;
3257
3258 /*
3259 * Skip '!', '-' and '+' characters. They are handled later.
3260 */
3261 start_leader = *arg;
3262 while (**arg == '!' || **arg == '-' || **arg == '+')
3263 *arg = skipwhite(*arg + 1);
3264 end_leader = *arg;
3265
3266 rettv.v_type = VAR_UNKNOWN;
3267 switch (**arg)
3268 {
3269 /*
3270 * Number constant.
3271 */
3272 case '0': // also for blob starting with 0z
3273 case '1':
3274 case '2':
3275 case '3':
3276 case '4':
3277 case '5':
3278 case '6':
3279 case '7':
3280 case '8':
3281 case '9':
3282 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3283 return FAIL;
3284 break;
3285
3286 /*
3287 * String constant: "string".
3288 */
3289 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3290 return FAIL;
3291 break;
3292
3293 /*
3294 * Literal string constant: 'str''ing'.
3295 */
3296 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3297 return FAIL;
3298 break;
3299
3300 /*
3301 * Constant Vim variable.
3302 */
3303 case 'v': get_vim_constant(arg, &rettv);
3304 ret = NOTDONE;
3305 break;
3306
3307 /*
3308 * List: [expr, expr]
3309 */
3310 case '[': ret = compile_list(arg, cctx);
3311 break;
3312
3313 /*
3314 * Dictionary: #{key: val, key: val}
3315 */
3316 case '#': if ((*arg)[1] == '{')
3317 {
3318 ++*arg;
3319 ret = compile_dict(arg, cctx, TRUE);
3320 }
3321 else
3322 ret = NOTDONE;
3323 break;
3324
3325 /*
3326 * Lambda: {arg, arg -> expr}
3327 * Dictionary: {'key': val, 'key': val}
3328 */
3329 case '{': {
3330 char_u *start = skipwhite(*arg + 1);
3331
3332 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003333 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003334 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003335 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003336 if (ret != FAIL && *start == '>')
3337 ret = compile_lambda(arg, cctx);
3338 else
3339 ret = compile_dict(arg, cctx, FALSE);
3340 }
3341 break;
3342
3343 /*
3344 * Option value: &name
3345 */
3346 case '&': ret = compile_get_option(arg, cctx);
3347 break;
3348
3349 /*
3350 * Environment variable: $VAR.
3351 */
3352 case '$': ret = compile_get_env(arg, cctx);
3353 break;
3354
3355 /*
3356 * Register contents: @r.
3357 */
3358 case '@': ret = compile_get_register(arg, cctx);
3359 break;
3360 /*
3361 * nested expression: (expression).
3362 */
3363 case '(': *arg = skipwhite(*arg + 1);
3364 ret = compile_expr1(arg, cctx); // recursive!
3365 *arg = skipwhite(*arg);
3366 if (**arg == ')')
3367 ++*arg;
3368 else if (ret == OK)
3369 {
3370 emsg(_(e_missing_close));
3371 ret = FAIL;
3372 }
3373 break;
3374
3375 default: ret = NOTDONE;
3376 break;
3377 }
3378 if (ret == FAIL)
3379 return FAIL;
3380
3381 if (rettv.v_type != VAR_UNKNOWN)
3382 {
3383 // apply the '!', '-' and '+' before the constant
3384 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3385 {
3386 clear_tv(&rettv);
3387 return FAIL;
3388 }
3389 start_leader = end_leader; // don't apply again below
3390
3391 // push constant
3392 switch (rettv.v_type)
3393 {
3394 case VAR_BOOL:
3395 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3396 break;
3397 case VAR_SPECIAL:
3398 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3399 break;
3400 case VAR_NUMBER:
3401 generate_PUSHNR(cctx, rettv.vval.v_number);
3402 break;
3403#ifdef FEAT_FLOAT
3404 case VAR_FLOAT:
3405 generate_PUSHF(cctx, rettv.vval.v_float);
3406 break;
3407#endif
3408 case VAR_BLOB:
3409 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3410 rettv.vval.v_blob = NULL;
3411 break;
3412 case VAR_STRING:
3413 generate_PUSHS(cctx, rettv.vval.v_string);
3414 rettv.vval.v_string = NULL;
3415 break;
3416 default:
3417 iemsg("constant type missing");
3418 return FAIL;
3419 }
3420 }
3421 else if (ret == NOTDONE)
3422 {
3423 char_u *p;
3424 int r;
3425
3426 if (!eval_isnamec1(**arg))
3427 {
3428 semsg(_("E1015: Name expected: %s"), *arg);
3429 return FAIL;
3430 }
3431
3432 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003433 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003434 if (*p == '(')
3435 r = compile_call(arg, p - *arg, cctx, 0);
3436 else
3437 r = compile_load(arg, p, cctx, TRUE);
3438 if (r == FAIL)
3439 return FAIL;
3440 }
3441
3442 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3443 return FAIL;
3444
3445 // Now deal with prefixed '-', '+' and '!', if not done already.
3446 return compile_leader(cctx, start_leader, end_leader);
3447}
3448
3449/*
3450 * * number multiplication
3451 * / number division
3452 * % number modulo
3453 */
3454 static int
3455compile_expr6(char_u **arg, cctx_T *cctx)
3456{
3457 char_u *op;
3458
3459 // get the first variable
3460 if (compile_expr7(arg, cctx) == FAIL)
3461 return FAIL;
3462
3463 /*
3464 * Repeat computing, until no "*", "/" or "%" is following.
3465 */
3466 for (;;)
3467 {
3468 op = skipwhite(*arg);
3469 if (*op != '*' && *op != '/' && *op != '%')
3470 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003471 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003472 {
3473 char_u buf[3];
3474
3475 vim_strncpy(buf, op, 1);
3476 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003477 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003478 }
3479 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003480 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003481 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003482
3483 // get the second variable
3484 if (compile_expr7(arg, cctx) == FAIL)
3485 return FAIL;
3486
3487 generate_two_op(cctx, op);
3488 }
3489
3490 return OK;
3491}
3492
3493/*
3494 * + number addition
3495 * - number subtraction
3496 * .. string concatenation
3497 */
3498 static int
3499compile_expr5(char_u **arg, cctx_T *cctx)
3500{
3501 char_u *op;
3502 int oplen;
3503
3504 // get the first variable
3505 if (compile_expr6(arg, cctx) == FAIL)
3506 return FAIL;
3507
3508 /*
3509 * Repeat computing, until no "+", "-" or ".." is following.
3510 */
3511 for (;;)
3512 {
3513 op = skipwhite(*arg);
3514 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3515 break;
3516 oplen = (*op == '.' ? 2 : 1);
3517
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003518 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003519 {
3520 char_u buf[3];
3521
3522 vim_strncpy(buf, op, oplen);
3523 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003524 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003525 }
3526
3527 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003528 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003529 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003530
3531 // get the second variable
3532 if (compile_expr6(arg, cctx) == FAIL)
3533 return FAIL;
3534
3535 if (*op == '.')
3536 {
3537 if (may_generate_2STRING(-2, cctx) == FAIL
3538 || may_generate_2STRING(-1, cctx) == FAIL)
3539 return FAIL;
3540 generate_instr_drop(cctx, ISN_CONCAT, 1);
3541 }
3542 else
3543 generate_two_op(cctx, op);
3544 }
3545
3546 return OK;
3547}
3548
Bram Moolenaar080457c2020-03-03 21:53:32 +01003549 static exptype_T
3550get_compare_type(char_u *p, int *len, int *type_is)
3551{
3552 exptype_T type = EXPR_UNKNOWN;
3553 int i;
3554
3555 switch (p[0])
3556 {
3557 case '=': if (p[1] == '=')
3558 type = EXPR_EQUAL;
3559 else if (p[1] == '~')
3560 type = EXPR_MATCH;
3561 break;
3562 case '!': if (p[1] == '=')
3563 type = EXPR_NEQUAL;
3564 else if (p[1] == '~')
3565 type = EXPR_NOMATCH;
3566 break;
3567 case '>': if (p[1] != '=')
3568 {
3569 type = EXPR_GREATER;
3570 *len = 1;
3571 }
3572 else
3573 type = EXPR_GEQUAL;
3574 break;
3575 case '<': if (p[1] != '=')
3576 {
3577 type = EXPR_SMALLER;
3578 *len = 1;
3579 }
3580 else
3581 type = EXPR_SEQUAL;
3582 break;
3583 case 'i': if (p[1] == 's')
3584 {
3585 // "is" and "isnot"; but not a prefix of a name
3586 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3587 *len = 5;
3588 i = p[*len];
3589 if (!isalnum(i) && i != '_')
3590 {
3591 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3592 *type_is = TRUE;
3593 }
3594 }
3595 break;
3596 }
3597 return type;
3598}
3599
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003600/*
3601 * expr5a == expr5b
3602 * expr5a =~ expr5b
3603 * expr5a != expr5b
3604 * expr5a !~ expr5b
3605 * expr5a > expr5b
3606 * expr5a >= expr5b
3607 * expr5a < expr5b
3608 * expr5a <= expr5b
3609 * expr5a is expr5b
3610 * expr5a isnot expr5b
3611 *
3612 * Produces instructions:
3613 * EVAL expr5a Push result of "expr5a"
3614 * EVAL expr5b Push result of "expr5b"
3615 * COMPARE one of the compare instructions
3616 */
3617 static int
3618compile_expr4(char_u **arg, cctx_T *cctx)
3619{
3620 exptype_T type = EXPR_UNKNOWN;
3621 char_u *p;
3622 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003623 int type_is = FALSE;
3624
3625 // get the first variable
3626 if (compile_expr5(arg, cctx) == FAIL)
3627 return FAIL;
3628
3629 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003630 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003631
3632 /*
3633 * If there is a comparative operator, use it.
3634 */
3635 if (type != EXPR_UNKNOWN)
3636 {
3637 int ic = FALSE; // Default: do not ignore case
3638
3639 if (type_is && (p[len] == '?' || p[len] == '#'))
3640 {
3641 semsg(_(e_invexpr2), *arg);
3642 return FAIL;
3643 }
3644 // extra question mark appended: ignore case
3645 if (p[len] == '?')
3646 {
3647 ic = TRUE;
3648 ++len;
3649 }
3650 // extra '#' appended: match case (ignored)
3651 else if (p[len] == '#')
3652 ++len;
3653 // nothing appended: match case
3654
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003655 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003656 {
3657 char_u buf[7];
3658
3659 vim_strncpy(buf, p, len);
3660 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003661 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003662 }
3663
3664 // get the second variable
3665 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003666 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003667 return FAIL;
3668
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003669 if (compile_expr5(arg, cctx) == FAIL)
3670 return FAIL;
3671
3672 generate_COMPARE(cctx, type, ic);
3673 }
3674
3675 return OK;
3676}
3677
3678/*
3679 * Compile || or &&.
3680 */
3681 static int
3682compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3683{
3684 char_u *p = skipwhite(*arg);
3685 int opchar = *op;
3686
3687 if (p[0] == opchar && p[1] == opchar)
3688 {
3689 garray_T *instr = &cctx->ctx_instr;
3690 garray_T end_ga;
3691
3692 /*
3693 * Repeat until there is no following "||" or "&&"
3694 */
3695 ga_init2(&end_ga, sizeof(int), 10);
3696 while (p[0] == opchar && p[1] == opchar)
3697 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003698 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3699 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003700 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003701 return FAIL;
3702 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003703
3704 if (ga_grow(&end_ga, 1) == FAIL)
3705 {
3706 ga_clear(&end_ga);
3707 return FAIL;
3708 }
3709 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3710 ++end_ga.ga_len;
3711 generate_JUMP(cctx, opchar == '|'
3712 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3713
3714 // eval the next expression
3715 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003716 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003717 return FAIL;
3718
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003719 if ((opchar == '|' ? compile_expr3(arg, cctx)
3720 : compile_expr4(arg, cctx)) == FAIL)
3721 {
3722 ga_clear(&end_ga);
3723 return FAIL;
3724 }
3725 p = skipwhite(*arg);
3726 }
3727
3728 // Fill in the end label in all jumps.
3729 while (end_ga.ga_len > 0)
3730 {
3731 isn_T *isn;
3732
3733 --end_ga.ga_len;
3734 isn = ((isn_T *)instr->ga_data)
3735 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3736 isn->isn_arg.jump.jump_where = instr->ga_len;
3737 }
3738 ga_clear(&end_ga);
3739 }
3740
3741 return OK;
3742}
3743
3744/*
3745 * expr4a && expr4a && expr4a logical AND
3746 *
3747 * Produces instructions:
3748 * EVAL expr4a Push result of "expr4a"
3749 * JUMP_AND_KEEP_IF_FALSE end
3750 * EVAL expr4b Push result of "expr4b"
3751 * JUMP_AND_KEEP_IF_FALSE end
3752 * EVAL expr4c Push result of "expr4c"
3753 * end:
3754 */
3755 static int
3756compile_expr3(char_u **arg, cctx_T *cctx)
3757{
3758 // get the first variable
3759 if (compile_expr4(arg, cctx) == FAIL)
3760 return FAIL;
3761
3762 // || and && work almost the same
3763 return compile_and_or(arg, cctx, "&&");
3764}
3765
3766/*
3767 * expr3a || expr3b || expr3c logical OR
3768 *
3769 * Produces instructions:
3770 * EVAL expr3a Push result of "expr3a"
3771 * JUMP_AND_KEEP_IF_TRUE end
3772 * EVAL expr3b Push result of "expr3b"
3773 * JUMP_AND_KEEP_IF_TRUE end
3774 * EVAL expr3c Push result of "expr3c"
3775 * end:
3776 */
3777 static int
3778compile_expr2(char_u **arg, cctx_T *cctx)
3779{
3780 // eval the first expression
3781 if (compile_expr3(arg, cctx) == FAIL)
3782 return FAIL;
3783
3784 // || and && work almost the same
3785 return compile_and_or(arg, cctx, "||");
3786}
3787
3788/*
3789 * Toplevel expression: expr2 ? expr1a : expr1b
3790 *
3791 * Produces instructions:
3792 * EVAL expr2 Push result of "expr"
3793 * JUMP_IF_FALSE alt jump if false
3794 * EVAL expr1a
3795 * JUMP_ALWAYS end
3796 * alt: EVAL expr1b
3797 * end:
3798 */
3799 static int
3800compile_expr1(char_u **arg, cctx_T *cctx)
3801{
3802 char_u *p;
3803
3804 // evaluate the first expression
3805 if (compile_expr2(arg, cctx) == FAIL)
3806 return FAIL;
3807
3808 p = skipwhite(*arg);
3809 if (*p == '?')
3810 {
3811 garray_T *instr = &cctx->ctx_instr;
3812 garray_T *stack = &cctx->ctx_type_stack;
3813 int alt_idx = instr->ga_len;
3814 int end_idx;
3815 isn_T *isn;
3816 type_T *type1;
3817 type_T *type2;
3818
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003819 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3820 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003821 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003822 return FAIL;
3823 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003824
3825 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3826
3827 // evaluate the second expression; any type is accepted
3828 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003829 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003830 return FAIL;
3831
Bram Moolenaara6d53682020-01-28 23:04:06 +01003832 if (compile_expr1(arg, cctx) == FAIL)
3833 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003834
3835 // remember the type and drop it
3836 --stack->ga_len;
3837 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3838
3839 end_idx = instr->ga_len;
3840 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3841
3842 // jump here from JUMP_IF_FALSE
3843 isn = ((isn_T *)instr->ga_data) + alt_idx;
3844 isn->isn_arg.jump.jump_where = instr->ga_len;
3845
3846 // Check for the ":".
3847 p = skipwhite(*arg);
3848 if (*p != ':')
3849 {
3850 emsg(_(e_missing_colon));
3851 return FAIL;
3852 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003853 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3854 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003855 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003856 return FAIL;
3857 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003858
3859 // evaluate the third expression
3860 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003861 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003862 return FAIL;
3863
Bram Moolenaara6d53682020-01-28 23:04:06 +01003864 if (compile_expr1(arg, cctx) == FAIL)
3865 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003866
3867 // If the types differ, the result has a more generic type.
3868 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003869 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003870
3871 // jump here from JUMP_ALWAYS
3872 isn = ((isn_T *)instr->ga_data) + end_idx;
3873 isn->isn_arg.jump.jump_where = instr->ga_len;
3874 }
3875 return OK;
3876}
3877
3878/*
3879 * compile "return [expr]"
3880 */
3881 static char_u *
3882compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3883{
3884 char_u *p = arg;
3885 garray_T *stack = &cctx->ctx_type_stack;
3886 type_T *stack_type;
3887
3888 if (*p != NUL && *p != '|' && *p != '\n')
3889 {
3890 // compile return argument into instructions
3891 if (compile_expr1(&p, cctx) == FAIL)
3892 return NULL;
3893
3894 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3895 if (set_return_type)
3896 cctx->ctx_ufunc->uf_ret_type = stack_type;
3897 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3898 == FAIL)
3899 return NULL;
3900 }
3901 else
3902 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003903 // "set_return_type" cannot be TRUE, only used for a lambda which
3904 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003905 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3906 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003907 {
3908 emsg(_("E1003: Missing return value"));
3909 return NULL;
3910 }
3911
3912 // No argument, return zero.
3913 generate_PUSHNR(cctx, 0);
3914 }
3915
3916 if (generate_instr(cctx, ISN_RETURN) == NULL)
3917 return NULL;
3918
3919 // "return val | endif" is possible
3920 return skipwhite(p);
3921}
3922
3923/*
3924 * Return the length of an assignment operator, or zero if there isn't one.
3925 */
3926 int
3927assignment_len(char_u *p, int *heredoc)
3928{
3929 if (*p == '=')
3930 {
3931 if (p[1] == '<' && p[2] == '<')
3932 {
3933 *heredoc = TRUE;
3934 return 3;
3935 }
3936 return 1;
3937 }
3938 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3939 return 2;
3940 if (STRNCMP(p, "..=", 3) == 0)
3941 return 3;
3942 return 0;
3943}
3944
3945// words that cannot be used as a variable
3946static char *reserved[] = {
3947 "true",
3948 "false",
3949 NULL
3950};
3951
3952/*
3953 * Get a line for "=<<".
3954 * Return a pointer to the line in allocated memory.
3955 * Return NULL for end-of-file or some error.
3956 */
3957 static char_u *
3958heredoc_getline(
3959 int c UNUSED,
3960 void *cookie,
3961 int indent UNUSED,
3962 int do_concat UNUSED)
3963{
3964 cctx_T *cctx = (cctx_T *)cookie;
3965
3966 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003967 {
3968 iemsg("Heredoc got to end");
3969 return NULL;
3970 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003971 ++cctx->ctx_lnum;
3972 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3973 [cctx->ctx_lnum]);
3974}
3975
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003976typedef enum {
3977 dest_local,
3978 dest_option,
3979 dest_env,
3980 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02003981 dest_buffer,
3982 dest_window,
3983 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003984 dest_vimvar,
3985 dest_script,
3986 dest_reg,
3987} assign_dest_T;
3988
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003989/*
3990 * compile "let var [= expr]", "const var = expr" and "var = expr"
3991 * "arg" points to "var".
3992 */
3993 static char_u *
3994compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
3995{
3996 char_u *p;
3997 char_u *ret = NULL;
3998 int var_count = 0;
3999 int semicolon = 0;
4000 size_t varlen;
4001 garray_T *instr = &cctx->ctx_instr;
4002 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004003 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004004 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004005 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004006 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004007 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004008 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004009 int oplen = 0;
4010 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004011 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004012 lvar_T *lvar;
4013 char_u *name;
4014 char_u *sp;
4015 int has_type = FALSE;
4016 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4017 int instr_count = -1;
4018
4019 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4020 if (p == NULL)
4021 return NULL;
4022 if (var_count > 0)
4023 {
4024 // TODO: let [var, var] = list
4025 emsg("Cannot handle a list yet");
4026 return NULL;
4027 }
4028
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004029 // "a: type" is declaring variable "a" with a type, not "a:".
4030 if (is_decl && p == arg + 2 && p[-1] == ':')
4031 --p;
4032
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004033 varlen = p - arg;
4034 name = vim_strnsave(arg, (int)varlen);
4035 if (name == NULL)
4036 return NULL;
4037
Bram Moolenaar080457c2020-03-03 21:53:32 +01004038 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004039 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004040 if (*arg == '&')
4041 {
4042 int cc;
4043 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004044
Bram Moolenaar080457c2020-03-03 21:53:32 +01004045 dest = dest_option;
4046 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004047 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004048 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004049 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004050 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004051 if (is_decl)
4052 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004053 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004054 goto theend;
4055 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004056 p = arg;
4057 p = find_option_end(&p, &opt_flags);
4058 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004059 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004060 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004061 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004062 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004063 }
4064 cc = *p;
4065 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004066 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004067 *p = cc;
4068 if (opt_type == -3)
4069 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004070 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004071 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004072 }
4073 if (opt_type == -2 || opt_type == 0)
4074 type = &t_string;
4075 else
4076 type = &t_number; // both number and boolean option
4077 }
4078 else if (*arg == '$')
4079 {
4080 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004081 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004082 if (is_decl)
4083 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004084 semsg(_("E1065: Cannot declare an environment variable: %s"),
4085 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004086 goto theend;
4087 }
4088 }
4089 else if (*arg == '@')
4090 {
4091 if (!valid_yank_reg(arg[1], TRUE))
4092 {
4093 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004094 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004095 }
4096 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004097 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004098 if (is_decl)
4099 {
4100 semsg(_("E1066: Cannot declare a register: %s"), name);
4101 goto theend;
4102 }
4103 }
4104 else if (STRNCMP(arg, "g:", 2) == 0)
4105 {
4106 dest = dest_global;
4107 if (is_decl)
4108 {
4109 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4110 goto theend;
4111 }
4112 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004113 else if (STRNCMP(arg, "b:", 2) == 0)
4114 {
4115 dest = dest_buffer;
4116 if (is_decl)
4117 {
4118 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4119 goto theend;
4120 }
4121 }
4122 else if (STRNCMP(arg, "w:", 2) == 0)
4123 {
4124 dest = dest_window;
4125 if (is_decl)
4126 {
4127 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4128 goto theend;
4129 }
4130 }
4131 else if (STRNCMP(arg, "t:", 2) == 0)
4132 {
4133 dest = dest_tab;
4134 if (is_decl)
4135 {
4136 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4137 goto theend;
4138 }
4139 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004140 else if (STRNCMP(arg, "v:", 2) == 0)
4141 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004142 typval_T *vtv;
4143 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004144
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004145 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004146 if (vimvaridx < 0)
4147 {
4148 semsg(_(e_var_notfound), arg);
4149 goto theend;
4150 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004151 // We use the current value of "sandbox" here, is that OK?
4152 if (var_check_ro(di_flags, name, FALSE))
4153 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004154 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004155 vtv = get_vim_var_tv(vimvaridx);
4156 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004157 if (is_decl)
4158 {
4159 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4160 goto theend;
4161 }
4162 }
4163 else
4164 {
4165 for (idx = 0; reserved[idx] != NULL; ++idx)
4166 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004167 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004168 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004169 goto theend;
4170 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004171
4172 idx = lookup_local(arg, varlen, cctx);
4173 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004174 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004175 if (is_decl)
4176 {
4177 semsg(_("E1017: Variable already declared: %s"), name);
4178 goto theend;
4179 }
4180 else
4181 {
4182 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4183 if (lvar->lv_const)
4184 {
4185 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4186 goto theend;
4187 }
4188 }
4189 }
4190 else if (STRNCMP(arg, "s:", 2) == 0
4191 || lookup_script(arg, varlen) == OK
4192 || find_imported(arg, varlen, cctx) != NULL)
4193 {
4194 dest = dest_script;
4195 if (is_decl)
4196 {
4197 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004198 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004199 goto theend;
4200 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004201 }
4202 }
4203 }
4204
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004205 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004206 {
4207 if (is_decl && *p == ':')
4208 {
4209 // parse optional type: "let var: type = expr"
4210 p = skipwhite(p + 1);
4211 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004212 has_type = TRUE;
4213 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004214 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004215 {
4216 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4217 type = lvar->lv_type;
4218 }
4219 }
4220
4221 sp = p;
4222 p = skipwhite(p);
4223 op = p;
4224 oplen = assignment_len(p, &heredoc);
4225 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4226 {
4227 char_u buf[4];
4228
4229 vim_strncpy(buf, op, oplen);
4230 semsg(_(e_white_both), buf);
4231 }
4232
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004233 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004234 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004235 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004236 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004237 goto theend;
4238 }
4239
Bram Moolenaar080457c2020-03-03 21:53:32 +01004240 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004241 {
4242 if (oplen > 1 && !heredoc)
4243 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004244 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004245 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4246 name);
4247 goto theend;
4248 }
4249
4250 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004251 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004252 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004253 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4254 if (idx < 0)
4255 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004256 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004257 }
4258
4259 if (heredoc)
4260 {
4261 list_T *l;
4262 listitem_T *li;
4263
4264 // [let] varname =<< [trim] {end}
4265 eap->getline = heredoc_getline;
4266 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004267 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004268
4269 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004270 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004271 {
4272 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4273 li->li_tv.vval.v_string = NULL;
4274 }
4275 generate_NEWLIST(cctx, l->lv_len);
4276 type = &t_list_string;
4277 list_free(l);
4278 p += STRLEN(p);
4279 }
4280 else if (oplen > 0)
4281 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004282 int r;
4283 type_T *stacktype;
4284 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004285
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004286 // for "+=", "*=", "..=" etc. first load the current value
4287 if (*op != '=')
4288 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004289 switch (dest)
4290 {
4291 case dest_option:
4292 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004293 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004294 break;
4295 case dest_global:
4296 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4297 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004298 case dest_buffer:
4299 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4300 break;
4301 case dest_window:
4302 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4303 break;
4304 case dest_tab:
4305 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4306 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004307 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004308 compile_load_scriptvar(cctx,
4309 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004310 break;
4311 case dest_env:
4312 // Include $ in the name here
4313 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4314 break;
4315 case dest_reg:
4316 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4317 break;
4318 case dest_vimvar:
4319 generate_LOADV(cctx, name + 2, TRUE);
4320 break;
4321 case dest_local:
4322 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4323 break;
4324 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004325 }
4326
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004327 // Compile the expression. Temporarily hide the new local variable
4328 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004329 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004330 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004331 instr_count = instr->ga_len;
4332 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004333 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004334 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004335 ++cctx->ctx_locals.ga_len;
4336 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004337 goto theend;
4338
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004339 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004340 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004341 stack = &cctx->ctx_type_stack;
4342 stacktype = stack->ga_len == 0 ? &t_void
4343 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4344 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004345 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004346 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4347 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004348 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004349 if (stacktype->tt_type == VAR_VOID)
4350 {
4351 emsg(_("E1031: Cannot use void value"));
4352 goto theend;
4353 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004354 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004355 {
4356 // An empty list or dict has a &t_void member, for a
4357 // variable that implies &t_any.
4358 if (stacktype == &t_list_empty)
4359 lvar->lv_type = &t_list_any;
4360 else if (stacktype == &t_dict_empty)
4361 lvar->lv_type = &t_dict_any;
4362 else
4363 lvar->lv_type = stacktype;
4364 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004365 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004366 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4367 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004368 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004369 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004370 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004371 }
4372 }
4373 else if (cmdidx == CMD_const)
4374 {
4375 emsg(_("E1021: const requires a value"));
4376 goto theend;
4377 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004378 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004379 {
4380 emsg(_("E1022: type or initialization required"));
4381 goto theend;
4382 }
4383 else
4384 {
4385 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004386 if (ga_grow(instr, 1) == FAIL)
4387 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004388 switch (type->tt_type)
4389 {
4390 case VAR_BOOL:
4391 generate_PUSHBOOL(cctx, VVAL_FALSE);
4392 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004393 case VAR_FLOAT:
4394#ifdef FEAT_FLOAT
4395 generate_PUSHF(cctx, 0.0);
4396#endif
4397 break;
4398 case VAR_STRING:
4399 generate_PUSHS(cctx, NULL);
4400 break;
4401 case VAR_BLOB:
4402 generate_PUSHBLOB(cctx, NULL);
4403 break;
4404 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004405 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004406 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004407 case VAR_LIST:
4408 generate_NEWLIST(cctx, 0);
4409 break;
4410 case VAR_DICT:
4411 generate_NEWDICT(cctx, 0);
4412 break;
4413 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004414 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004415 break;
4416 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004417 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004418 break;
4419 case VAR_NUMBER:
4420 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004421 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004422 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004423 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004424 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004425 generate_PUSHNR(cctx, 0);
4426 break;
4427 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004428 }
4429
4430 if (oplen > 0 && *op != '=')
4431 {
4432 type_T *expected = &t_number;
4433 garray_T *stack = &cctx->ctx_type_stack;
4434 type_T *stacktype;
4435
4436 // TODO: if type is known use float or any operation
4437
4438 if (*op == '.')
4439 expected = &t_string;
4440 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4441 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4442 goto theend;
4443
4444 if (*op == '.')
4445 generate_instr_drop(cctx, ISN_CONCAT, 1);
4446 else
4447 {
4448 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4449
4450 if (isn == NULL)
4451 goto theend;
4452 switch (*op)
4453 {
4454 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4455 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4456 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4457 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4458 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4459 }
4460 }
4461 }
4462
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004463 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004464 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004465 case dest_option:
4466 generate_STOREOPT(cctx, name + 1, opt_flags);
4467 break;
4468 case dest_global:
4469 // include g: with the name, easier to execute that way
4470 generate_STORE(cctx, ISN_STOREG, 0, name);
4471 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004472 case dest_buffer:
4473 // include b: with the name, easier to execute that way
4474 generate_STORE(cctx, ISN_STOREB, 0, name);
4475 break;
4476 case dest_window:
4477 // include w: with the name, easier to execute that way
4478 generate_STORE(cctx, ISN_STOREW, 0, name);
4479 break;
4480 case dest_tab:
4481 // include t: with the name, easier to execute that way
4482 generate_STORE(cctx, ISN_STORET, 0, name);
4483 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004484 case dest_env:
4485 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4486 break;
4487 case dest_reg:
4488 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4489 break;
4490 case dest_vimvar:
4491 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4492 break;
4493 case dest_script:
4494 {
4495 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4496 imported_T *import = NULL;
4497 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004498
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004499 if (name[1] != ':')
4500 {
4501 import = find_imported(name, 0, cctx);
4502 if (import != NULL)
4503 sid = import->imp_sid;
4504 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004505
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004506 idx = get_script_item_idx(sid, rawname, TRUE);
4507 // TODO: specific type
4508 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004509 {
4510 char_u *name_s = name;
4511
4512 // Include s: in the name for store_var()
4513 if (name[1] != ':')
4514 {
4515 int len = (int)STRLEN(name) + 3;
4516
4517 name_s = alloc(len);
4518 if (name_s == NULL)
4519 name_s = name;
4520 else
4521 vim_snprintf((char *)name_s, len, "s:%s", name);
4522 }
4523 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4524 if (name_s != name)
4525 vim_free(name_s);
4526 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004527 else
4528 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4529 sid, idx, &t_any);
4530 }
4531 break;
4532 case dest_local:
4533 {
4534 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004535
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004536 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4537 // into ISN_STORENR
4538 if (instr->ga_len == instr_count + 1
4539 && isn->isn_type == ISN_PUSHNR)
4540 {
4541 varnumber_T val = isn->isn_arg.number;
4542 garray_T *stack = &cctx->ctx_type_stack;
4543
4544 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004545 isn->isn_arg.storenr.stnr_idx = idx;
4546 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004547 if (stack->ga_len > 0)
4548 --stack->ga_len;
4549 }
4550 else
4551 generate_STORE(cctx, ISN_STORE, idx, NULL);
4552 }
4553 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004554 }
4555 ret = p;
4556
4557theend:
4558 vim_free(name);
4559 return ret;
4560}
4561
4562/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004563 * Check if "name" can be "unlet".
4564 */
4565 int
4566check_vim9_unlet(char_u *name)
4567{
4568 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
4569 {
4570 semsg(_("E1081: Cannot unlet %s"), name);
4571 return FAIL;
4572 }
4573 return OK;
4574}
4575
4576/*
4577 * Callback passed to ex_unletlock().
4578 */
4579 static int
4580compile_unlet(
4581 lval_T *lvp,
4582 char_u *name_end,
4583 exarg_T *eap,
4584 int deep UNUSED,
4585 void *coookie)
4586{
4587 cctx_T *cctx = coookie;
4588
4589 if (lvp->ll_tv == NULL)
4590 {
4591 char_u *p = lvp->ll_name;
4592 int cc = *name_end;
4593 int ret = OK;
4594
4595 // Normal name. Only supports g:, w:, t: and b: namespaces.
4596 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004597 if (*p == '$')
4598 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
4599 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004600 ret = FAIL;
4601 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004602 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004603
4604 *name_end = cc;
4605 return ret;
4606 }
4607
4608 // TODO: unlet {list}[idx]
4609 // TODO: unlet {dict}[key]
4610 emsg("Sorry, :unlet not fully implemented yet");
4611 return FAIL;
4612}
4613
4614/*
4615 * compile "unlet var", "lock var" and "unlock var"
4616 * "arg" points to "var".
4617 */
4618 static char_u *
4619compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
4620{
4621 char_u *p = arg;
4622
4623 if (eap->cmdidx != CMD_unlet)
4624 {
4625 emsg("Sorry, :lock and unlock not implemented yet");
4626 return NULL;
4627 }
4628
4629 if (*p == '!')
4630 {
4631 p = skipwhite(p + 1);
4632 eap->forceit = TRUE;
4633 }
4634
4635 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
4636 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
4637}
4638
4639/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004640 * Compile an :import command.
4641 */
4642 static char_u *
4643compile_import(char_u *arg, cctx_T *cctx)
4644{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004645 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004646}
4647
4648/*
4649 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4650 */
4651 static int
4652compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4653{
4654 garray_T *instr = &cctx->ctx_instr;
4655 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4656
4657 if (endlabel == NULL)
4658 return FAIL;
4659 endlabel->el_next = *el;
4660 *el = endlabel;
4661 endlabel->el_end_label = instr->ga_len;
4662
4663 generate_JUMP(cctx, when, 0);
4664 return OK;
4665}
4666
4667 static void
4668compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4669{
4670 garray_T *instr = &cctx->ctx_instr;
4671
4672 while (*el != NULL)
4673 {
4674 endlabel_T *cur = (*el);
4675 isn_T *isn;
4676
4677 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4678 isn->isn_arg.jump.jump_where = instr->ga_len;
4679 *el = cur->el_next;
4680 vim_free(cur);
4681 }
4682}
4683
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004684 static void
4685compile_free_jump_to_end(endlabel_T **el)
4686{
4687 while (*el != NULL)
4688 {
4689 endlabel_T *cur = (*el);
4690
4691 *el = cur->el_next;
4692 vim_free(cur);
4693 }
4694}
4695
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004696/*
4697 * Create a new scope and set up the generic items.
4698 */
4699 static scope_T *
4700new_scope(cctx_T *cctx, scopetype_T type)
4701{
4702 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4703
4704 if (scope == NULL)
4705 return NULL;
4706 scope->se_outer = cctx->ctx_scope;
4707 cctx->ctx_scope = scope;
4708 scope->se_type = type;
4709 scope->se_local_count = cctx->ctx_locals.ga_len;
4710 return scope;
4711}
4712
4713/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004714 * Free the current scope and go back to the outer scope.
4715 */
4716 static void
4717drop_scope(cctx_T *cctx)
4718{
4719 scope_T *scope = cctx->ctx_scope;
4720
4721 if (scope == NULL)
4722 {
4723 iemsg("calling drop_scope() without a scope");
4724 return;
4725 }
4726 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004727 switch (scope->se_type)
4728 {
4729 case IF_SCOPE:
4730 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4731 case FOR_SCOPE:
4732 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4733 case WHILE_SCOPE:
4734 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4735 case TRY_SCOPE:
4736 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4737 case NO_SCOPE:
4738 case BLOCK_SCOPE:
4739 break;
4740 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004741 vim_free(scope);
4742}
4743
4744/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004745 * Evaluate an expression that is a constant:
4746 * has(arg)
4747 *
4748 * Also handle:
4749 * ! in front logical NOT
4750 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004751 * Return FAIL if the expression is not a constant.
4752 */
4753 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004754evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004755{
4756 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004757 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004758 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004759
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004760 /*
4761 * Skip '!' characters. They are handled later.
4762 */
4763 start_leader = *arg;
4764 while (**arg == '!')
4765 *arg = skipwhite(*arg + 1);
4766 end_leader = *arg;
4767
4768 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004769 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004770 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004771 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4772 {
4773 tv->v_type = VAR_SPECIAL;
4774 tv->vval.v_number = VVAL_TRUE;
4775 *arg += 4;
4776 return OK;
4777 }
4778 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4779 {
4780 tv->v_type = VAR_SPECIAL;
4781 tv->vval.v_number = VVAL_FALSE;
4782 *arg += 5;
4783 return OK;
4784 }
4785
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004786 if (STRNCMP("has(", *arg, 4) == 0)
4787 {
4788 has_call = TRUE;
4789 *arg = skipwhite(*arg + 4);
4790 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004791
4792 if (**arg == '"')
4793 {
4794 if (get_string_tv(arg, tv, TRUE) == FAIL)
4795 return FAIL;
4796 }
4797 else if (**arg == '\'')
4798 {
4799 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4800 return FAIL;
4801 }
4802 else
4803 return FAIL;
4804
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004805 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004806 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004807 *arg = skipwhite(*arg);
4808 if (**arg != ')')
4809 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004810 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004811
4812 argvars[0] = *tv;
4813 argvars[1].v_type = VAR_UNKNOWN;
4814 tv->v_type = VAR_NUMBER;
4815 tv->vval.v_number = 0;
4816 f_has(argvars, tv);
4817 clear_tv(&argvars[0]);
4818
4819 while (start_leader < end_leader)
4820 {
4821 if (*start_leader == '!')
4822 tv->vval.v_number = !tv->vval.v_number;
4823 ++start_leader;
4824 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004825 }
4826
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004827 return OK;
4828}
4829
Bram Moolenaar080457c2020-03-03 21:53:32 +01004830 static int
4831evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4832{
4833 exptype_T type = EXPR_UNKNOWN;
4834 char_u *p;
4835 int len = 2;
4836 int type_is = FALSE;
4837
4838 // get the first variable
4839 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4840 return FAIL;
4841
4842 p = skipwhite(*arg);
4843 type = get_compare_type(p, &len, &type_is);
4844
4845 /*
4846 * If there is a comparative operator, use it.
4847 */
4848 if (type != EXPR_UNKNOWN)
4849 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004850 typval_T tv2;
4851 char_u *s1, *s2;
4852 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4853 int n;
4854
4855 // TODO: Only string == string is supported now
4856 if (tv->v_type != VAR_STRING)
4857 return FAIL;
4858 if (type != EXPR_EQUAL)
4859 return FAIL;
4860
4861 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004862 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004863 *arg = skipwhite(p + len);
4864 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4865 || tv2.v_type != VAR_STRING)
4866 {
4867 clear_tv(&tv2);
4868 return FAIL;
4869 }
4870 s1 = tv_get_string_buf(tv, buf1);
4871 s2 = tv_get_string_buf(&tv2, buf2);
4872 n = STRCMP(s1, s2);
4873 clear_tv(tv);
4874 clear_tv(&tv2);
4875 tv->v_type = VAR_BOOL;
4876 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004877 }
4878
4879 return OK;
4880}
4881
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004882static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4883
4884/*
4885 * Compile constant || or &&.
4886 */
4887 static int
4888evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4889{
4890 char_u *p = skipwhite(*arg);
4891 int opchar = *op;
4892
4893 if (p[0] == opchar && p[1] == opchar)
4894 {
4895 int val = tv2bool(tv);
4896
4897 /*
4898 * Repeat until there is no following "||" or "&&"
4899 */
4900 while (p[0] == opchar && p[1] == opchar)
4901 {
4902 typval_T tv2;
4903
4904 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4905 return FAIL;
4906
4907 // eval the next expression
4908 *arg = skipwhite(p + 2);
4909 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004910 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004911 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004912 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004913 {
4914 clear_tv(&tv2);
4915 return FAIL;
4916 }
4917 if ((opchar == '&') == val)
4918 {
4919 // false || tv2 or true && tv2: use tv2
4920 clear_tv(tv);
4921 *tv = tv2;
4922 val = tv2bool(tv);
4923 }
4924 else
4925 clear_tv(&tv2);
4926 p = skipwhite(*arg);
4927 }
4928 }
4929
4930 return OK;
4931}
4932
4933/*
4934 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4935 * Return FAIL if the expression is not a constant.
4936 */
4937 static int
4938evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4939{
4940 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004941 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004942 return FAIL;
4943
4944 // || and && work almost the same
4945 return evaluate_const_and_or(arg, cctx, "&&", tv);
4946}
4947
4948/*
4949 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4950 * Return FAIL if the expression is not a constant.
4951 */
4952 static int
4953evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4954{
4955 // evaluate the first expression
4956 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4957 return FAIL;
4958
4959 // || and && work almost the same
4960 return evaluate_const_and_or(arg, cctx, "||", tv);
4961}
4962
4963/*
4964 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4965 * E.g. for "has('feature')".
4966 * This does not produce error messages. "tv" should be cleared afterwards.
4967 * Return FAIL if the expression is not a constant.
4968 */
4969 static int
4970evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4971{
4972 char_u *p;
4973
4974 // evaluate the first expression
4975 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4976 return FAIL;
4977
4978 p = skipwhite(*arg);
4979 if (*p == '?')
4980 {
4981 int val = tv2bool(tv);
4982 typval_T tv2;
4983
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004984 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004985 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4986 return FAIL;
4987
4988 // evaluate the second expression; any type is accepted
4989 clear_tv(tv);
4990 *arg = skipwhite(p + 1);
4991 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
4992 return FAIL;
4993
4994 // Check for the ":".
4995 p = skipwhite(*arg);
4996 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
4997 return FAIL;
4998
4999 // evaluate the third expression
5000 *arg = skipwhite(p + 1);
5001 tv2.v_type = VAR_UNKNOWN;
5002 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
5003 {
5004 clear_tv(&tv2);
5005 return FAIL;
5006 }
5007 if (val)
5008 {
5009 // use the expr after "?"
5010 clear_tv(&tv2);
5011 }
5012 else
5013 {
5014 // use the expr after ":"
5015 clear_tv(tv);
5016 *tv = tv2;
5017 }
5018 }
5019 return OK;
5020}
5021
5022/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005023 * compile "if expr"
5024 *
5025 * "if expr" Produces instructions:
5026 * EVAL expr Push result of "expr"
5027 * JUMP_IF_FALSE end
5028 * ... body ...
5029 * end:
5030 *
5031 * "if expr | else" Produces instructions:
5032 * EVAL expr Push result of "expr"
5033 * JUMP_IF_FALSE else
5034 * ... body ...
5035 * JUMP_ALWAYS end
5036 * else:
5037 * ... body ...
5038 * end:
5039 *
5040 * "if expr1 | elseif expr2 | else" Produces instructions:
5041 * EVAL expr Push result of "expr"
5042 * JUMP_IF_FALSE elseif
5043 * ... body ...
5044 * JUMP_ALWAYS end
5045 * elseif:
5046 * EVAL expr Push result of "expr"
5047 * JUMP_IF_FALSE else
5048 * ... body ...
5049 * JUMP_ALWAYS end
5050 * else:
5051 * ... body ...
5052 * end:
5053 */
5054 static char_u *
5055compile_if(char_u *arg, cctx_T *cctx)
5056{
5057 char_u *p = arg;
5058 garray_T *instr = &cctx->ctx_instr;
5059 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005060 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005061
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005062 // compile "expr"; if we know it evaluates to FALSE skip the block
5063 tv.v_type = VAR_UNKNOWN;
5064 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5065 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5066 else
5067 cctx->ctx_skip = MAYBE;
5068 clear_tv(&tv);
5069 if (cctx->ctx_skip == MAYBE)
5070 {
5071 p = arg;
5072 if (compile_expr1(&p, cctx) == FAIL)
5073 return NULL;
5074 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005075
5076 scope = new_scope(cctx, IF_SCOPE);
5077 if (scope == NULL)
5078 return NULL;
5079
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005080 if (cctx->ctx_skip == MAYBE)
5081 {
5082 // "where" is set when ":elseif", "else" or ":endif" is found
5083 scope->se_u.se_if.is_if_label = instr->ga_len;
5084 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5085 }
5086 else
5087 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005088
5089 return p;
5090}
5091
5092 static char_u *
5093compile_elseif(char_u *arg, cctx_T *cctx)
5094{
5095 char_u *p = arg;
5096 garray_T *instr = &cctx->ctx_instr;
5097 isn_T *isn;
5098 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005099 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005100
5101 if (scope == NULL || scope->se_type != IF_SCOPE)
5102 {
5103 emsg(_(e_elseif_without_if));
5104 return NULL;
5105 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005106 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005107
Bram Moolenaar158906c2020-02-06 20:39:45 +01005108 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005109 {
5110 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005111 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005112 return NULL;
5113 // previous "if" or "elseif" jumps here
5114 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5115 isn->isn_arg.jump.jump_where = instr->ga_len;
5116 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005117
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005118 // compile "expr"; if we know it evaluates to FALSE skip the block
5119 tv.v_type = VAR_UNKNOWN;
5120 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5121 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5122 else
5123 cctx->ctx_skip = MAYBE;
5124 clear_tv(&tv);
5125 if (cctx->ctx_skip == MAYBE)
5126 {
5127 p = arg;
5128 if (compile_expr1(&p, cctx) == FAIL)
5129 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005130
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005131 // "where" is set when ":elseif", "else" or ":endif" is found
5132 scope->se_u.se_if.is_if_label = instr->ga_len;
5133 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5134 }
5135 else
5136 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005137
5138 return p;
5139}
5140
5141 static char_u *
5142compile_else(char_u *arg, cctx_T *cctx)
5143{
5144 char_u *p = arg;
5145 garray_T *instr = &cctx->ctx_instr;
5146 isn_T *isn;
5147 scope_T *scope = cctx->ctx_scope;
5148
5149 if (scope == NULL || scope->se_type != IF_SCOPE)
5150 {
5151 emsg(_(e_else_without_if));
5152 return NULL;
5153 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005154 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005155
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005156 // jump from previous block to the end, unless the else block is empty
5157 if (cctx->ctx_skip == MAYBE)
5158 {
5159 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005160 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005161 return NULL;
5162 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005163
Bram Moolenaar158906c2020-02-06 20:39:45 +01005164 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005165 {
5166 if (scope->se_u.se_if.is_if_label >= 0)
5167 {
5168 // previous "if" or "elseif" jumps here
5169 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5170 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005171 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005172 }
5173 }
5174
5175 if (cctx->ctx_skip != MAYBE)
5176 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005177
5178 return p;
5179}
5180
5181 static char_u *
5182compile_endif(char_u *arg, cctx_T *cctx)
5183{
5184 scope_T *scope = cctx->ctx_scope;
5185 ifscope_T *ifscope;
5186 garray_T *instr = &cctx->ctx_instr;
5187 isn_T *isn;
5188
5189 if (scope == NULL || scope->se_type != IF_SCOPE)
5190 {
5191 emsg(_(e_endif_without_if));
5192 return NULL;
5193 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005194 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005195 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005196
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005197 if (scope->se_u.se_if.is_if_label >= 0)
5198 {
5199 // previous "if" or "elseif" jumps here
5200 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5201 isn->isn_arg.jump.jump_where = instr->ga_len;
5202 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005203 // Fill in the "end" label in jumps at the end of the blocks.
5204 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005205 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005206
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005207 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005208 return arg;
5209}
5210
5211/*
5212 * compile "for var in expr"
5213 *
5214 * Produces instructions:
5215 * PUSHNR -1
5216 * STORE loop-idx Set index to -1
5217 * EVAL expr Push result of "expr"
5218 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5219 * - if beyond end, jump to "end"
5220 * - otherwise get item from list and push it
5221 * STORE var Store item in "var"
5222 * ... body ...
5223 * JUMP top Jump back to repeat
5224 * end: DROP Drop the result of "expr"
5225 *
5226 */
5227 static char_u *
5228compile_for(char_u *arg, cctx_T *cctx)
5229{
5230 char_u *p;
5231 size_t varlen;
5232 garray_T *instr = &cctx->ctx_instr;
5233 garray_T *stack = &cctx->ctx_type_stack;
5234 scope_T *scope;
5235 int loop_idx; // index of loop iteration variable
5236 int var_idx; // index of "var"
5237 type_T *vartype;
5238
5239 // TODO: list of variables: "for [key, value] in dict"
5240 // parse "var"
5241 for (p = arg; eval_isnamec1(*p); ++p)
5242 ;
5243 varlen = p - arg;
5244 var_idx = lookup_local(arg, varlen, cctx);
5245 if (var_idx >= 0)
5246 {
5247 semsg(_("E1023: variable already defined: %s"), arg);
5248 return NULL;
5249 }
5250
5251 // consume "in"
5252 p = skipwhite(p);
5253 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5254 {
5255 emsg(_(e_missing_in));
5256 return NULL;
5257 }
5258 p = skipwhite(p + 2);
5259
5260
5261 scope = new_scope(cctx, FOR_SCOPE);
5262 if (scope == NULL)
5263 return NULL;
5264
5265 // Reserve a variable to store the loop iteration counter.
5266 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5267 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005268 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005269 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005270 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005271 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005272 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005273
5274 // Reserve a variable to store "var"
5275 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5276 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005277 {
5278 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005279 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005280 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005281
5282 generate_STORENR(cctx, loop_idx, -1);
5283
5284 // compile "expr", it remains on the stack until "endfor"
5285 arg = p;
5286 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005287 {
5288 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005289 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005290 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005291
5292 // now we know the type of "var"
5293 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5294 if (vartype->tt_type != VAR_LIST)
5295 {
5296 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005297 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005298 return NULL;
5299 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005300 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005301 {
5302 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
5303
5304 lvar->lv_type = vartype->tt_member;
5305 }
5306
5307 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005308 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005309
5310 generate_FOR(cctx, loop_idx);
5311 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
5312
5313 return arg;
5314}
5315
5316/*
5317 * compile "endfor"
5318 */
5319 static char_u *
5320compile_endfor(char_u *arg, cctx_T *cctx)
5321{
5322 garray_T *instr = &cctx->ctx_instr;
5323 scope_T *scope = cctx->ctx_scope;
5324 forscope_T *forscope;
5325 isn_T *isn;
5326
5327 if (scope == NULL || scope->se_type != FOR_SCOPE)
5328 {
5329 emsg(_(e_for));
5330 return NULL;
5331 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005332 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005333 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005334 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005335
5336 // At end of ":for" scope jump back to the FOR instruction.
5337 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5338
5339 // Fill in the "end" label in the FOR statement so it can jump here
5340 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5341 isn->isn_arg.forloop.for_end = instr->ga_len;
5342
5343 // Fill in the "end" label any BREAK statements
5344 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5345
5346 // Below the ":for" scope drop the "expr" list from the stack.
5347 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5348 return NULL;
5349
5350 vim_free(scope);
5351
5352 return arg;
5353}
5354
5355/*
5356 * compile "while expr"
5357 *
5358 * Produces instructions:
5359 * top: EVAL expr Push result of "expr"
5360 * JUMP_IF_FALSE end jump if false
5361 * ... body ...
5362 * JUMP top Jump back to repeat
5363 * end:
5364 *
5365 */
5366 static char_u *
5367compile_while(char_u *arg, cctx_T *cctx)
5368{
5369 char_u *p = arg;
5370 garray_T *instr = &cctx->ctx_instr;
5371 scope_T *scope;
5372
5373 scope = new_scope(cctx, WHILE_SCOPE);
5374 if (scope == NULL)
5375 return NULL;
5376
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005377 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005378
5379 // compile "expr"
5380 if (compile_expr1(&p, cctx) == FAIL)
5381 return NULL;
5382
5383 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005384 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005385 JUMP_IF_FALSE, cctx) == FAIL)
5386 return FAIL;
5387
5388 return p;
5389}
5390
5391/*
5392 * compile "endwhile"
5393 */
5394 static char_u *
5395compile_endwhile(char_u *arg, cctx_T *cctx)
5396{
5397 scope_T *scope = cctx->ctx_scope;
5398
5399 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5400 {
5401 emsg(_(e_while));
5402 return NULL;
5403 }
5404 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005405 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005406
5407 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005408 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005409
5410 // Fill in the "end" label in the WHILE statement so it can jump here.
5411 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005412 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005413
5414 vim_free(scope);
5415
5416 return arg;
5417}
5418
5419/*
5420 * compile "continue"
5421 */
5422 static char_u *
5423compile_continue(char_u *arg, cctx_T *cctx)
5424{
5425 scope_T *scope = cctx->ctx_scope;
5426
5427 for (;;)
5428 {
5429 if (scope == NULL)
5430 {
5431 emsg(_(e_continue));
5432 return NULL;
5433 }
5434 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5435 break;
5436 scope = scope->se_outer;
5437 }
5438
5439 // Jump back to the FOR or WHILE instruction.
5440 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005441 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5442 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005443 return arg;
5444}
5445
5446/*
5447 * compile "break"
5448 */
5449 static char_u *
5450compile_break(char_u *arg, cctx_T *cctx)
5451{
5452 scope_T *scope = cctx->ctx_scope;
5453 endlabel_T **el;
5454
5455 for (;;)
5456 {
5457 if (scope == NULL)
5458 {
5459 emsg(_(e_break));
5460 return NULL;
5461 }
5462 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5463 break;
5464 scope = scope->se_outer;
5465 }
5466
5467 // Jump to the end of the FOR or WHILE loop.
5468 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005469 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005470 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005471 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005472 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5473 return FAIL;
5474
5475 return arg;
5476}
5477
5478/*
5479 * compile "{" start of block
5480 */
5481 static char_u *
5482compile_block(char_u *arg, cctx_T *cctx)
5483{
5484 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5485 return NULL;
5486 return skipwhite(arg + 1);
5487}
5488
5489/*
5490 * compile end of block: drop one scope
5491 */
5492 static void
5493compile_endblock(cctx_T *cctx)
5494{
5495 scope_T *scope = cctx->ctx_scope;
5496
5497 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005498 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005499 vim_free(scope);
5500}
5501
5502/*
5503 * compile "try"
5504 * Creates a new scope for the try-endtry, pointing to the first catch and
5505 * finally.
5506 * Creates another scope for the "try" block itself.
5507 * TRY instruction sets up exception handling at runtime.
5508 *
5509 * "try"
5510 * TRY -> catch1, -> finally push trystack entry
5511 * ... try block
5512 * "throw {exception}"
5513 * EVAL {exception}
5514 * THROW create exception
5515 * ... try block
5516 * " catch {expr}"
5517 * JUMP -> finally
5518 * catch1: PUSH exeception
5519 * EVAL {expr}
5520 * MATCH
5521 * JUMP nomatch -> catch2
5522 * CATCH remove exception
5523 * ... catch block
5524 * " catch"
5525 * JUMP -> finally
5526 * catch2: CATCH remove exception
5527 * ... catch block
5528 * " finally"
5529 * finally:
5530 * ... finally block
5531 * " endtry"
5532 * ENDTRY pop trystack entry, may rethrow
5533 */
5534 static char_u *
5535compile_try(char_u *arg, cctx_T *cctx)
5536{
5537 garray_T *instr = &cctx->ctx_instr;
5538 scope_T *try_scope;
5539 scope_T *scope;
5540
5541 // scope that holds the jumps that go to catch/finally/endtry
5542 try_scope = new_scope(cctx, TRY_SCOPE);
5543 if (try_scope == NULL)
5544 return NULL;
5545
5546 // "catch" is set when the first ":catch" is found.
5547 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005548 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005549 if (generate_instr(cctx, ISN_TRY) == NULL)
5550 return NULL;
5551
5552 // scope for the try block itself
5553 scope = new_scope(cctx, BLOCK_SCOPE);
5554 if (scope == NULL)
5555 return NULL;
5556
5557 return arg;
5558}
5559
5560/*
5561 * compile "catch {expr}"
5562 */
5563 static char_u *
5564compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5565{
5566 scope_T *scope = cctx->ctx_scope;
5567 garray_T *instr = &cctx->ctx_instr;
5568 char_u *p;
5569 isn_T *isn;
5570
5571 // end block scope from :try or :catch
5572 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5573 compile_endblock(cctx);
5574 scope = cctx->ctx_scope;
5575
5576 // Error if not in a :try scope
5577 if (scope == NULL || scope->se_type != TRY_SCOPE)
5578 {
5579 emsg(_(e_catch));
5580 return NULL;
5581 }
5582
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005583 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005584 {
5585 emsg(_("E1033: catch unreachable after catch-all"));
5586 return NULL;
5587 }
5588
5589 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005590 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005591 JUMP_ALWAYS, cctx) == FAIL)
5592 return NULL;
5593
5594 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005595 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005596 if (isn->isn_arg.try.try_catch == 0)
5597 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005598 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005599 {
5600 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005601 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005602 isn->isn_arg.jump.jump_where = instr->ga_len;
5603 }
5604
5605 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005606 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005607 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005608 scope->se_u.se_try.ts_caught_all = TRUE;
5609 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005610 }
5611 else
5612 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005613 char_u *end;
5614 char_u *pat;
5615 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005616 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005617 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005618
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005619 // Push v:exception, push {expr} and MATCH
5620 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5621
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005622 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005623 if (*end != *p)
5624 {
5625 semsg(_("E1067: Separator mismatch: %s"), p);
5626 vim_free(tofree);
5627 return FAIL;
5628 }
5629 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005630 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005631 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005632 len = (int)(end - tofree);
5633 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005634 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005635 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005636 if (pat == NULL)
5637 return FAIL;
5638 if (generate_PUSHS(cctx, pat) == FAIL)
5639 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005640
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005641 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5642 return NULL;
5643
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005644 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005645 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5646 return NULL;
5647 }
5648
5649 if (generate_instr(cctx, ISN_CATCH) == NULL)
5650 return NULL;
5651
5652 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5653 return NULL;
5654 return p;
5655}
5656
5657 static char_u *
5658compile_finally(char_u *arg, cctx_T *cctx)
5659{
5660 scope_T *scope = cctx->ctx_scope;
5661 garray_T *instr = &cctx->ctx_instr;
5662 isn_T *isn;
5663
5664 // end block scope from :try or :catch
5665 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5666 compile_endblock(cctx);
5667 scope = cctx->ctx_scope;
5668
5669 // Error if not in a :try scope
5670 if (scope == NULL || scope->se_type != TRY_SCOPE)
5671 {
5672 emsg(_(e_finally));
5673 return NULL;
5674 }
5675
5676 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005677 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005678 if (isn->isn_arg.try.try_finally != 0)
5679 {
5680 emsg(_(e_finally_dup));
5681 return NULL;
5682 }
5683
5684 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005685 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005686
Bram Moolenaar585fea72020-04-02 22:33:21 +02005687 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005688 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005689 {
5690 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005691 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005692 isn->isn_arg.jump.jump_where = instr->ga_len;
5693 }
5694
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005695 // TODO: set index in ts_finally_label jumps
5696
5697 return arg;
5698}
5699
5700 static char_u *
5701compile_endtry(char_u *arg, cctx_T *cctx)
5702{
5703 scope_T *scope = cctx->ctx_scope;
5704 garray_T *instr = &cctx->ctx_instr;
5705 isn_T *isn;
5706
5707 // end block scope from :catch or :finally
5708 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5709 compile_endblock(cctx);
5710 scope = cctx->ctx_scope;
5711
5712 // Error if not in a :try scope
5713 if (scope == NULL || scope->se_type != TRY_SCOPE)
5714 {
5715 if (scope == NULL)
5716 emsg(_(e_no_endtry));
5717 else if (scope->se_type == WHILE_SCOPE)
5718 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005719 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005720 emsg(_(e_endfor));
5721 else
5722 emsg(_(e_endif));
5723 return NULL;
5724 }
5725
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005726 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005727 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5728 {
5729 emsg(_("E1032: missing :catch or :finally"));
5730 return NULL;
5731 }
5732
5733 // Fill in the "end" label in jumps at the end of the blocks, if not done
5734 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005735 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005736
5737 // End :catch or :finally scope: set value in ISN_TRY instruction
5738 if (isn->isn_arg.try.try_finally == 0)
5739 isn->isn_arg.try.try_finally = instr->ga_len;
5740 compile_endblock(cctx);
5741
5742 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5743 return NULL;
5744 return arg;
5745}
5746
5747/*
5748 * compile "throw {expr}"
5749 */
5750 static char_u *
5751compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5752{
5753 char_u *p = skipwhite(arg);
5754
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005755 if (compile_expr1(&p, cctx) == FAIL)
5756 return NULL;
5757 if (may_generate_2STRING(-1, cctx) == FAIL)
5758 return NULL;
5759 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5760 return NULL;
5761
5762 return p;
5763}
5764
5765/*
5766 * compile "echo expr"
5767 */
5768 static char_u *
5769compile_echo(char_u *arg, int with_white, cctx_T *cctx)
5770{
5771 char_u *p = arg;
5772 int count = 0;
5773
Bram Moolenaarad39c092020-02-26 18:23:43 +01005774 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005775 {
5776 if (compile_expr1(&p, cctx) == FAIL)
5777 return NULL;
5778 ++count;
Bram Moolenaarad39c092020-02-26 18:23:43 +01005779 p = skipwhite(p);
5780 if (ends_excmd(*p))
5781 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005782 }
5783
5784 generate_ECHO(cctx, with_white, count);
Bram Moolenaarad39c092020-02-26 18:23:43 +01005785 return p;
5786}
5787
5788/*
5789 * compile "execute expr"
5790 */
5791 static char_u *
5792compile_execute(char_u *arg, cctx_T *cctx)
5793{
5794 char_u *p = arg;
5795 int count = 0;
5796
5797 for (;;)
5798 {
5799 if (compile_expr1(&p, cctx) == FAIL)
5800 return NULL;
5801 ++count;
5802 p = skipwhite(p);
5803 if (ends_excmd(*p))
5804 break;
5805 }
5806
5807 generate_EXECUTE(cctx, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005808
5809 return p;
5810}
5811
5812/*
5813 * After ex_function() has collected all the function lines: parse and compile
5814 * the lines into instructions.
5815 * Adds the function to "def_functions".
5816 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5817 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005818 * This can be used recursively through compile_lambda(), which may reallocate
5819 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005820 */
5821 void
5822compile_def_function(ufunc_T *ufunc, int set_return_type)
5823{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005824 char_u *line = NULL;
5825 char_u *p;
5826 exarg_T ea;
5827 char *errormsg = NULL; // error message
5828 int had_return = FALSE;
5829 cctx_T cctx;
5830 garray_T *instr;
5831 int called_emsg_before = called_emsg;
5832 int ret = FAIL;
5833 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005834 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005835
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005836 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005837 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005838
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005839 if (ufunc->uf_dfunc_idx >= 0)
5840 {
5841 // Redefining a function that was compiled before.
5842 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5843
5844 // Free old instructions.
5845 delete_def_function_contents(dfunc);
5846 }
5847 else
5848 {
5849 // Add the function to "def_functions".
5850 if (ga_grow(&def_functions, 1) == FAIL)
5851 return;
5852 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005853 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005854 dfunc->df_idx = def_functions.ga_len;
5855 ufunc->uf_dfunc_idx = dfunc->df_idx;
5856 dfunc->df_ufunc = ufunc;
5857 ++def_functions.ga_len;
5858 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005859 }
5860
Bram Moolenaara80faa82020-04-12 19:37:17 +02005861 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005862 cctx.ctx_ufunc = ufunc;
5863 cctx.ctx_lnum = -1;
5864 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5865 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5866 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5867 cctx.ctx_type_list = &ufunc->uf_type_list;
5868 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5869 instr = &cctx.ctx_instr;
5870
5871 // Most modern script version.
5872 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5873
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005874 if (ufunc->uf_def_args.ga_len > 0)
5875 {
5876 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005877 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005878 int i;
5879 char_u *arg;
5880 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5881
5882 // Produce instructions for the default values of optional arguments.
5883 // Store the instruction index in uf_def_arg_idx[] so that we know
5884 // where to start when the function is called, depending on the number
5885 // of arguments.
5886 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5887 if (ufunc->uf_def_arg_idx == NULL)
5888 goto erret;
5889 for (i = 0; i < count; ++i)
5890 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005891 garray_T *stack = &cctx.ctx_type_stack;
5892 type_T *val_type;
5893 int arg_idx = first_def_arg + i;
5894
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005895 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5896 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005897 if (compile_expr1(&arg, &cctx) == FAIL)
5898 goto erret;
5899
5900 // If no type specified use the type of the default value.
5901 // Otherwise check that the default value type matches the
5902 // specified type.
5903 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5904 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
5905 ufunc->uf_arg_types[arg_idx] = val_type;
5906 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
5907 == FAIL)
5908 {
5909 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
5910 arg_idx + 1);
5911 goto erret;
5912 }
5913
5914 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005915 goto erret;
5916 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005917 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5918 }
5919
5920 /*
5921 * Loop over all the lines of the function and generate instructions.
5922 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005923 for (;;)
5924 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005925 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01005926
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005927 // Bail out on the first error to avoid a flood of errors and report
5928 // the right line number when inside try/catch.
5929 if (emsg_before != called_emsg)
5930 goto erret;
5931
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005932 if (line != NULL && *line == '|')
5933 // the line continues after a '|'
5934 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02005935 else if (line != NULL && *line != NUL
5936 && !(*line == '#' && (line == cctx.ctx_line_start
5937 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005938 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02005939 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005940 goto erret;
5941 }
5942 else
5943 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02005944 line = next_line_from_context(&cctx);
5945 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005946 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005947 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005948 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005949 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005950
5951 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005952 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005953 ea.cmdlinep = &line;
5954 ea.cmd = skipwhite(line);
5955
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005956 // Some things can be recognized by the first character.
5957 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005958 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005959 case '#':
5960 // "#" starts a comment, but not "#{".
5961 if (ea.cmd[1] != '{')
5962 {
5963 line = (char_u *)"";
5964 continue;
5965 }
5966 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005967
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005968 case '}':
5969 {
5970 // "}" ends a block scope
5971 scopetype_T stype = cctx.ctx_scope == NULL
5972 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005973
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02005974 if (stype == BLOCK_SCOPE)
5975 {
5976 compile_endblock(&cctx);
5977 line = ea.cmd;
5978 }
5979 else
5980 {
5981 emsg(_("E1025: using } outside of a block scope"));
5982 goto erret;
5983 }
5984 if (line != NULL)
5985 line = skipwhite(ea.cmd + 1);
5986 continue;
5987 }
5988
5989 case '{':
5990 // "{" starts a block scope
5991 // "{'a': 1}->func() is something else
5992 if (ends_excmd(*skipwhite(ea.cmd + 1)))
5993 {
5994 line = compile_block(ea.cmd, &cctx);
5995 continue;
5996 }
5997 break;
5998
5999 case ':':
6000 is_ex_command = TRUE;
6001 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006002 }
6003
6004 /*
6005 * COMMAND MODIFIERS
6006 */
6007 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6008 {
6009 if (errormsg != NULL)
6010 goto erret;
6011 // empty line or comment
6012 line = (char_u *)"";
6013 continue;
6014 }
6015
6016 // Skip ":call" to get to the function name.
6017 if (checkforcmd(&ea.cmd, "call", 3))
6018 ea.cmd = skipwhite(ea.cmd);
6019
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006020 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006021 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006022 // Assuming the command starts with a variable or function name,
6023 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6024 // val".
6025 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6026 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006027 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006028 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006029 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006030 int oplen;
6031 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006032
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006033 oplen = assignment_len(skipwhite(p), &heredoc);
6034 if (oplen > 0)
6035 {
6036 // Recognize an assignment if we recognize the variable
6037 // name:
6038 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006039 // "local = expr" where "local" is a local var.
6040 // "script = expr" where "script" is a script-local var.
6041 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006042 // "&opt = expr"
6043 // "$ENV = expr"
6044 // "@r = expr"
6045 if (*ea.cmd == '&'
6046 || *ea.cmd == '$'
6047 || *ea.cmd == '@'
6048 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
6049 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
6050 || lookup_script(ea.cmd, p - ea.cmd) == OK
6051 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6052 {
6053 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6054 if (line == NULL)
6055 goto erret;
6056 continue;
6057 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006058 }
6059 }
6060 }
6061
6062 /*
6063 * COMMAND after range
6064 */
6065 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006066 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
6067 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006068
6069 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6070 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006071 if (cctx.ctx_skip == TRUE)
6072 {
6073 line += STRLEN(line);
6074 continue;
6075 }
6076
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006077 // Expression or function call.
6078 if (ea.cmdidx == CMD_eval)
6079 {
6080 p = ea.cmd;
6081 if (compile_expr1(&p, &cctx) == FAIL)
6082 goto erret;
6083
6084 // drop the return value
6085 generate_instr_drop(&cctx, ISN_DROP, 1);
6086 line = p;
6087 continue;
6088 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006089 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006090 iemsg("Command from find_ex_command() not handled");
6091 goto erret;
6092 }
6093
6094 p = skipwhite(p);
6095
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006096 if (cctx.ctx_skip == TRUE
6097 && ea.cmdidx != CMD_elseif
6098 && ea.cmdidx != CMD_else
6099 && ea.cmdidx != CMD_endif)
6100 {
6101 line += STRLEN(line);
6102 continue;
6103 }
6104
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006105 switch (ea.cmdidx)
6106 {
6107 case CMD_def:
6108 case CMD_function:
6109 // TODO: Nested function
6110 emsg("Nested function not implemented yet");
6111 goto erret;
6112
6113 case CMD_return:
6114 line = compile_return(p, set_return_type, &cctx);
6115 had_return = TRUE;
6116 break;
6117
6118 case CMD_let:
6119 case CMD_const:
6120 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6121 break;
6122
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006123 case CMD_unlet:
6124 case CMD_unlockvar:
6125 case CMD_lockvar:
6126 line = compile_unletlock(p, &ea, &cctx);
6127 break;
6128
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006129 case CMD_import:
6130 line = compile_import(p, &cctx);
6131 break;
6132
6133 case CMD_if:
6134 line = compile_if(p, &cctx);
6135 break;
6136 case CMD_elseif:
6137 line = compile_elseif(p, &cctx);
6138 break;
6139 case CMD_else:
6140 line = compile_else(p, &cctx);
6141 break;
6142 case CMD_endif:
6143 line = compile_endif(p, &cctx);
6144 break;
6145
6146 case CMD_while:
6147 line = compile_while(p, &cctx);
6148 break;
6149 case CMD_endwhile:
6150 line = compile_endwhile(p, &cctx);
6151 break;
6152
6153 case CMD_for:
6154 line = compile_for(p, &cctx);
6155 break;
6156 case CMD_endfor:
6157 line = compile_endfor(p, &cctx);
6158 break;
6159 case CMD_continue:
6160 line = compile_continue(p, &cctx);
6161 break;
6162 case CMD_break:
6163 line = compile_break(p, &cctx);
6164 break;
6165
6166 case CMD_try:
6167 line = compile_try(p, &cctx);
6168 break;
6169 case CMD_catch:
6170 line = compile_catch(p, &cctx);
6171 break;
6172 case CMD_finally:
6173 line = compile_finally(p, &cctx);
6174 break;
6175 case CMD_endtry:
6176 line = compile_endtry(p, &cctx);
6177 break;
6178 case CMD_throw:
6179 line = compile_throw(p, &cctx);
6180 break;
6181
6182 case CMD_echo:
6183 line = compile_echo(p, TRUE, &cctx);
6184 break;
6185 case CMD_echon:
6186 line = compile_echo(p, FALSE, &cctx);
6187 break;
Bram Moolenaarad39c092020-02-26 18:23:43 +01006188 case CMD_execute:
6189 line = compile_execute(p, &cctx);
6190 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006191
6192 default:
6193 // Not recognized, execute with do_cmdline_cmd().
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01006194 // TODO:
6195 // CMD_echomsg
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01006196 // etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006197 generate_EXEC(&cctx, line);
6198 line = (char_u *)"";
6199 break;
6200 }
6201 if (line == NULL)
6202 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006203 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006204
6205 if (cctx.ctx_type_stack.ga_len < 0)
6206 {
6207 iemsg("Type stack underflow");
6208 goto erret;
6209 }
6210 }
6211
6212 if (cctx.ctx_scope != NULL)
6213 {
6214 if (cctx.ctx_scope->se_type == IF_SCOPE)
6215 emsg(_(e_endif));
6216 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6217 emsg(_(e_endwhile));
6218 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6219 emsg(_(e_endfor));
6220 else
6221 emsg(_("E1026: Missing }"));
6222 goto erret;
6223 }
6224
6225 if (!had_return)
6226 {
6227 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6228 {
6229 emsg(_("E1027: Missing return statement"));
6230 goto erret;
6231 }
6232
6233 // Return zero if there is no return at the end.
6234 generate_PUSHNR(&cctx, 0);
6235 generate_instr(&cctx, ISN_RETURN);
6236 }
6237
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006238 {
6239 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6240 + ufunc->uf_dfunc_idx;
6241 dfunc->df_deleted = FALSE;
6242 dfunc->df_instr = instr->ga_data;
6243 dfunc->df_instr_count = instr->ga_len;
6244 dfunc->df_varcount = cctx.ctx_max_local;
6245 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006246
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006247 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006248 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006249 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006250
6251 // Create a type for the function, with the return type and any
6252 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006253 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6254 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006255 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006256 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006257 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6258 argcount, &ufunc->uf_type_list);
6259 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006260 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006261 argcount + varargs,
6262 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006263 {
6264 ret = FAIL;
6265 goto erret;
6266 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006267 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6268 ufunc->uf_func_type->tt_min_argcount =
6269 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006270 if (ufunc->uf_arg_types == NULL)
6271 {
6272 int i;
6273
6274 // lambda does not have argument types.
6275 for (i = 0; i < argcount; ++i)
6276 ufunc->uf_func_type->tt_args[i] = &t_any;
6277 }
6278 else
6279 mch_memmove(ufunc->uf_func_type->tt_args,
6280 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006281 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006282 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006283 ufunc->uf_func_type->tt_args[argcount] =
6284 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006285 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6286 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006287 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006288 else
6289 // No arguments, can use a predefined type.
6290 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6291 argcount, &ufunc->uf_type_list);
6292
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006293 }
6294
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006295 ret = OK;
6296
6297erret:
6298 if (ret == FAIL)
6299 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006300 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006301 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6302 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006303
6304 for (idx = 0; idx < instr->ga_len; ++idx)
6305 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006306 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006307
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006308 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006309 if (!dfunc->df_deleted)
6310 --def_functions.ga_len;
6311
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006312 while (cctx.ctx_scope != NULL)
6313 drop_scope(&cctx);
6314
Bram Moolenaar20431c92020-03-20 18:39:46 +01006315 // Don't execute this function body.
6316 ga_clear_strings(&ufunc->uf_lines);
6317
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006318 if (errormsg != NULL)
6319 emsg(errormsg);
6320 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006321 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006322 }
6323
6324 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006325 free_imported(&cctx);
6326 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006327 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006328}
6329
6330/*
6331 * Delete an instruction, free what it contains.
6332 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006333 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006334delete_instr(isn_T *isn)
6335{
6336 switch (isn->isn_type)
6337 {
6338 case ISN_EXEC:
6339 case ISN_LOADENV:
6340 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006341 case ISN_LOADB:
6342 case ISN_LOADW:
6343 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006344 case ISN_LOADOPT:
6345 case ISN_MEMBER:
6346 case ISN_PUSHEXC:
6347 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006348 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006349 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006350 case ISN_STOREB:
6351 case ISN_STOREW:
6352 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006353 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006354 vim_free(isn->isn_arg.string);
6355 break;
6356
6357 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006358 case ISN_STORES:
6359 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006360 break;
6361
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006362 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006363 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006364 vim_free(isn->isn_arg.unlet.ul_name);
6365 break;
6366
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006367 case ISN_STOREOPT:
6368 vim_free(isn->isn_arg.storeopt.so_name);
6369 break;
6370
6371 case ISN_PUSHBLOB: // push blob isn_arg.blob
6372 blob_unref(isn->isn_arg.blob);
6373 break;
6374
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006375 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006376#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006377 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006378#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006379 break;
6380
6381 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006382#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006383 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006384#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006385 break;
6386
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006387 case ISN_UCALL:
6388 vim_free(isn->isn_arg.ufunc.cuf_name);
6389 break;
6390
6391 case ISN_2BOOL:
6392 case ISN_2STRING:
6393 case ISN_ADDBLOB:
6394 case ISN_ADDLIST:
6395 case ISN_BCALL:
6396 case ISN_CATCH:
6397 case ISN_CHECKNR:
6398 case ISN_CHECKTYPE:
6399 case ISN_COMPAREANY:
6400 case ISN_COMPAREBLOB:
6401 case ISN_COMPAREBOOL:
6402 case ISN_COMPAREDICT:
6403 case ISN_COMPAREFLOAT:
6404 case ISN_COMPAREFUNC:
6405 case ISN_COMPARELIST:
6406 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006407 case ISN_COMPARESPECIAL:
6408 case ISN_COMPARESTRING:
6409 case ISN_CONCAT:
6410 case ISN_DCALL:
6411 case ISN_DROP:
6412 case ISN_ECHO:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006413 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006414 case ISN_ENDTRY:
6415 case ISN_FOR:
6416 case ISN_FUNCREF:
6417 case ISN_INDEX:
6418 case ISN_JUMP:
6419 case ISN_LOAD:
6420 case ISN_LOADSCRIPT:
6421 case ISN_LOADREG:
6422 case ISN_LOADV:
6423 case ISN_NEGATENR:
6424 case ISN_NEWDICT:
6425 case ISN_NEWLIST:
6426 case ISN_OPNR:
6427 case ISN_OPFLOAT:
6428 case ISN_OPANY:
6429 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006430 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006431 case ISN_PUSHF:
6432 case ISN_PUSHNR:
6433 case ISN_PUSHBOOL:
6434 case ISN_PUSHSPEC:
6435 case ISN_RETURN:
6436 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006437 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006438 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006439 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006440 case ISN_STORESCRIPT:
6441 case ISN_THROW:
6442 case ISN_TRY:
6443 // nothing allocated
6444 break;
6445 }
6446}
6447
6448/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006449 * Free all instructions for "dfunc".
6450 */
6451 static void
6452delete_def_function_contents(dfunc_T *dfunc)
6453{
6454 int idx;
6455
6456 ga_clear(&dfunc->df_def_args_isn);
6457
6458 if (dfunc->df_instr != NULL)
6459 {
6460 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6461 delete_instr(dfunc->df_instr + idx);
6462 VIM_CLEAR(dfunc->df_instr);
6463 }
6464
6465 dfunc->df_deleted = TRUE;
6466}
6467
6468/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006469 * When a user function is deleted, delete any associated def function.
6470 */
6471 void
6472delete_def_function(ufunc_T *ufunc)
6473{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006474 if (ufunc->uf_dfunc_idx >= 0)
6475 {
6476 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6477 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006478
Bram Moolenaar20431c92020-03-20 18:39:46 +01006479 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006480 }
6481}
6482
6483#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006484/*
6485 * Free all functions defined with ":def".
6486 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006487 void
6488free_def_functions(void)
6489{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006490 int idx;
6491
6492 for (idx = 0; idx < def_functions.ga_len; ++idx)
6493 {
6494 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6495
6496 delete_def_function_contents(dfunc);
6497 }
6498
6499 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006500}
6501#endif
6502
6503
6504#endif // FEAT_EVAL