blob: c3f3bfdfbc883d8b58582667168b5b8f7b3cbc2d [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;
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200100 int lv_idx; // index of the variable on the stack
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100101 int lv_const; // when TRUE cannot be assigned to
102 int lv_arg; // when TRUE this is an argument
103} lvar_T;
104
105/*
106 * Context for compiling lines of Vim script.
107 * Stores info about the local variables and condition stack.
108 */
109struct cctx_S {
110 ufunc_T *ctx_ufunc; // current function
111 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200112 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100113 garray_T ctx_instr; // generated instructions
114
115 garray_T ctx_locals; // currently visible local variables
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200116 int ctx_locals_count; // total number of local variables
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100117
118 garray_T ctx_imports; // imported items
119
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100120 int ctx_skip; // when TRUE skip commands, when FALSE skip
121 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100122 scope_T *ctx_scope; // current scope, NULL at toplevel
123
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200124 cctx_T *ctx_outer; // outer scope for lambda or nested
125 // function
126
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100127 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200128 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100129};
130
131static char e_var_notfound[] = N_("E1001: variable not found: %s");
132static char e_syntax_at[] = N_("E1002: Syntax error at %s");
133
134static int compile_expr1(char_u **arg, cctx_T *cctx);
135static int compile_expr2(char_u **arg, cctx_T *cctx);
136static int compile_expr3(char_u **arg, cctx_T *cctx);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100137static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200138static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
139static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100140
141/*
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200142 * Lookup variable "name" in the local scope and return it.
143 * Return NULL if not found.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100144 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200145 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146lookup_local(char_u *name, size_t len, cctx_T *cctx)
147{
148 int idx;
149
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100150 if (len == 0)
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200151 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100152 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
153 {
154 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
155
156 if (STRNCMP(name, lvar->lv_name, len) == 0
157 && STRLEN(lvar->lv_name) == len)
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200158 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100159 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200160 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100161}
162
163/*
164 * Lookup an argument in the current function.
165 * Returns the argument index or -1 if not found.
166 */
167 static int
168lookup_arg(char_u *name, size_t len, cctx_T *cctx)
169{
170 int idx;
171
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100172 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100173 return -1;
174 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
175 {
176 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
177
178 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
179 return idx;
180 }
181 return -1;
182}
183
184/*
185 * Lookup a vararg argument in the current function.
186 * Returns TRUE if there is a match.
187 */
188 static int
189lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
190{
191 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
192
193 return len > 0 && va_name != NULL
194 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
195}
196
197/*
198 * Lookup a variable in the current script.
199 * Returns OK or FAIL.
200 */
201 static int
202lookup_script(char_u *name, size_t len)
203{
204 int cc;
205 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
206 dictitem_T *di;
207
208 cc = name[len];
209 name[len] = NUL;
210 di = find_var_in_ht(ht, 0, name, TRUE);
211 name[len] = cc;
212 return di == NULL ? FAIL: OK;
213}
214
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100215/*
216 * Check if "p[len]" is already defined, either in script "import_sid" or in
217 * compilation context "cctx".
218 * Return FAIL and give an error if it defined.
219 */
220 int
221check_defined(char_u *p, int len, cctx_T *cctx)
222{
223 if (lookup_script(p, len) == OK
224 || (cctx != NULL
Bram Moolenaarb84a3812020-05-01 15:44:29 +0200225 && (lookup_local(p, len, cctx) != NULL
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100226 || find_imported(p, len, cctx) != NULL)))
227 {
228 semsg("E1073: imported name already defined: %s", p);
229 return FAIL;
230 }
231 return OK;
232}
233
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200234/*
235 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
236 * be freed later.
237 */
238 static type_T *
239alloc_type(garray_T *type_gap)
240{
241 type_T *type;
242
243 if (ga_grow(type_gap, 1) == FAIL)
244 return NULL;
245 type = ALLOC_CLEAR_ONE(type_T);
246 if (type != NULL)
247 {
248 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
249 ++type_gap->ga_len;
250 }
251 return type;
252}
253
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100254 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200255get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100256{
257 type_T *type;
258
259 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200260 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100261 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200262 if (member_type->tt_type == VAR_VOID
263 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100264 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100265 if (member_type->tt_type == VAR_BOOL)
266 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100267 if (member_type->tt_type == VAR_NUMBER)
268 return &t_list_number;
269 if (member_type->tt_type == VAR_STRING)
270 return &t_list_string;
271
272 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200273 type = alloc_type(type_gap);
274 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100275 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100276 type->tt_type = VAR_LIST;
277 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200278 type->tt_argcount = 0;
279 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100280 return type;
281}
282
283 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200284get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100285{
286 type_T *type;
287
288 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200289 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100290 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200291 if (member_type->tt_type == VAR_VOID
292 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100293 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100294 if (member_type->tt_type == VAR_BOOL)
295 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100296 if (member_type->tt_type == VAR_NUMBER)
297 return &t_dict_number;
298 if (member_type->tt_type == VAR_STRING)
299 return &t_dict_string;
300
301 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200302 type = alloc_type(type_gap);
303 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100304 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100305 type->tt_type = VAR_DICT;
306 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200307 type->tt_argcount = 0;
308 type->tt_args = NULL;
309 return type;
310}
311
312/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200313 * Allocate a new type for a function.
314 */
315 static type_T *
316alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
317{
318 type_T *type = alloc_type(type_gap);
319
320 if (type == NULL)
321 return &t_any;
322 type->tt_type = VAR_FUNC;
323 type->tt_member = ret_type;
324 type->tt_argcount = argcount;
325 type->tt_args = NULL;
326 return type;
327}
328
329/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200330 * Get a function type, based on the return type "ret_type".
331 * If "argcount" is -1 or 0 a predefined type can be used.
332 * If "argcount" > 0 always create a new type, so that arguments can be added.
333 */
334 static type_T *
335get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
336{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200337 // recognize commonly used types
338 if (argcount <= 0)
339 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200340 if (ret_type == &t_unknown)
341 {
342 // (argcount == 0) is not possible
343 return &t_func_unknown;
344 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200345 if (ret_type == &t_void)
346 {
347 if (argcount == 0)
348 return &t_func_0_void;
349 else
350 return &t_func_void;
351 }
352 if (ret_type == &t_any)
353 {
354 if (argcount == 0)
355 return &t_func_0_any;
356 else
357 return &t_func_any;
358 }
359 if (ret_type == &t_number)
360 {
361 if (argcount == 0)
362 return &t_func_0_number;
363 else
364 return &t_func_number;
365 }
366 if (ret_type == &t_string)
367 {
368 if (argcount == 0)
369 return &t_func_0_string;
370 else
371 return &t_func_string;
372 }
373 }
374
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200375 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100376}
377
Bram Moolenaara8c17702020-04-01 21:17:24 +0200378/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200379 * For a function type, reserve space for "argcount" argument types (including
380 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200381 */
382 static int
383func_type_add_arg_types(
384 type_T *functype,
385 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200386 garray_T *type_gap)
387{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200388 // To make it easy to free the space needed for the argument types, add the
389 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200390 if (ga_grow(type_gap, 1) == FAIL)
391 return FAIL;
392 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
393 if (functype->tt_args == NULL)
394 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200395 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
396 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200397 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200398 return OK;
399}
400
401/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200402 * Return the type_T for a typval. Only for primitive types.
403 */
404 static type_T *
405typval2type(typval_T *tv)
406{
407 if (tv->v_type == VAR_NUMBER)
408 return &t_number;
409 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200410 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200411 if (tv->v_type == VAR_STRING)
412 return &t_string;
413 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
414 return &t_list_string;
415 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
416 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200417 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200418}
419
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100420/////////////////////////////////////////////////////////////////////
421// Following generate_ functions expect the caller to call ga_grow().
422
Bram Moolenaar080457c2020-03-03 21:53:32 +0100423#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
424#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
425
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100426/*
427 * Generate an instruction without arguments.
428 * Returns a pointer to the new instruction, NULL if failed.
429 */
430 static isn_T *
431generate_instr(cctx_T *cctx, isntype_T isn_type)
432{
433 garray_T *instr = &cctx->ctx_instr;
434 isn_T *isn;
435
Bram Moolenaar080457c2020-03-03 21:53:32 +0100436 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100437 if (ga_grow(instr, 1) == FAIL)
438 return NULL;
439 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
440 isn->isn_type = isn_type;
441 isn->isn_lnum = cctx->ctx_lnum + 1;
442 ++instr->ga_len;
443
444 return isn;
445}
446
447/*
448 * Generate an instruction without arguments.
449 * "drop" will be removed from the stack.
450 * Returns a pointer to the new instruction, NULL if failed.
451 */
452 static isn_T *
453generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
454{
455 garray_T *stack = &cctx->ctx_type_stack;
456
Bram Moolenaar080457c2020-03-03 21:53:32 +0100457 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100458 stack->ga_len -= drop;
459 return generate_instr(cctx, isn_type);
460}
461
462/*
463 * Generate instruction "isn_type" and put "type" on the type stack.
464 */
465 static isn_T *
466generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
467{
468 isn_T *isn;
469 garray_T *stack = &cctx->ctx_type_stack;
470
471 if ((isn = generate_instr(cctx, isn_type)) == NULL)
472 return NULL;
473
474 if (ga_grow(stack, 1) == FAIL)
475 return NULL;
476 ((type_T **)stack->ga_data)[stack->ga_len] = type;
477 ++stack->ga_len;
478
479 return isn;
480}
481
482/*
483 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
484 */
485 static int
486may_generate_2STRING(int offset, cctx_T *cctx)
487{
488 isn_T *isn;
489 garray_T *stack = &cctx->ctx_type_stack;
490 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
491
492 if ((*type)->tt_type == VAR_STRING)
493 return OK;
494 *type = &t_string;
495
496 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
497 return FAIL;
498 isn->isn_arg.number = offset;
499
500 return OK;
501}
502
503 static int
504check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
505{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200506 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100507 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200508 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100509 {
510 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100511 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100512 else
513 semsg(_("E1036: %c requires number or float arguments"), *op);
514 return FAIL;
515 }
516 return OK;
517}
518
519/*
520 * Generate an instruction with two arguments. The instruction depends on the
521 * type of the arguments.
522 */
523 static int
524generate_two_op(cctx_T *cctx, char_u *op)
525{
526 garray_T *stack = &cctx->ctx_type_stack;
527 type_T *type1;
528 type_T *type2;
529 vartype_T vartype;
530 isn_T *isn;
531
Bram Moolenaar080457c2020-03-03 21:53:32 +0100532 RETURN_OK_IF_SKIP(cctx);
533
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100534 // Get the known type of the two items on the stack. If they are matching
535 // use a type-specific instruction. Otherwise fall back to runtime type
536 // checking.
537 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
538 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200539 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100540 if (type1->tt_type == type2->tt_type
541 && (type1->tt_type == VAR_NUMBER
542 || type1->tt_type == VAR_LIST
543#ifdef FEAT_FLOAT
544 || type1->tt_type == VAR_FLOAT
545#endif
546 || type1->tt_type == VAR_BLOB))
547 vartype = type1->tt_type;
548
549 switch (*op)
550 {
551 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200552 && type1->tt_type != VAR_ANY
553 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100554 && check_number_or_float(
555 type1->tt_type, type2->tt_type, op) == FAIL)
556 return FAIL;
557 isn = generate_instr_drop(cctx,
558 vartype == VAR_NUMBER ? ISN_OPNR
559 : vartype == VAR_LIST ? ISN_ADDLIST
560 : vartype == VAR_BLOB ? ISN_ADDBLOB
561#ifdef FEAT_FLOAT
562 : vartype == VAR_FLOAT ? ISN_OPFLOAT
563#endif
564 : ISN_OPANY, 1);
565 if (isn != NULL)
566 isn->isn_arg.op.op_type = EXPR_ADD;
567 break;
568
569 case '-':
570 case '*':
571 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
572 op) == FAIL)
573 return FAIL;
574 if (vartype == VAR_NUMBER)
575 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
576#ifdef FEAT_FLOAT
577 else if (vartype == VAR_FLOAT)
578 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
579#endif
580 else
581 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
582 if (isn != NULL)
583 isn->isn_arg.op.op_type = *op == '*'
584 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
585 break;
586
Bram Moolenaar4c683752020-04-05 21:38:23 +0200587 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100588 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200589 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100590 && type2->tt_type != VAR_NUMBER))
591 {
592 emsg(_("E1035: % requires number arguments"));
593 return FAIL;
594 }
595 isn = generate_instr_drop(cctx,
596 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
597 if (isn != NULL)
598 isn->isn_arg.op.op_type = EXPR_REM;
599 break;
600 }
601
602 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200603 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100604 {
605 type_T *type = &t_any;
606
607#ifdef FEAT_FLOAT
608 // float+number and number+float results in float
609 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
610 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
611 type = &t_float;
612#endif
613 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
614 }
615
616 return OK;
617}
618
619/*
620 * Generate an ISN_COMPARE* instruction with a boolean result.
621 */
622 static int
623generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
624{
625 isntype_T isntype = ISN_DROP;
626 isn_T *isn;
627 garray_T *stack = &cctx->ctx_type_stack;
628 vartype_T type1;
629 vartype_T type2;
630
Bram Moolenaar080457c2020-03-03 21:53:32 +0100631 RETURN_OK_IF_SKIP(cctx);
632
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100633 // Get the known type of the two items on the stack. If they are matching
634 // use a type-specific instruction. Otherwise fall back to runtime type
635 // checking.
636 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
637 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200638 if (type1 == VAR_UNKNOWN)
639 type1 = VAR_ANY;
640 if (type2 == VAR_UNKNOWN)
641 type2 = VAR_ANY;
642
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100643 if (type1 == type2)
644 {
645 switch (type1)
646 {
647 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
648 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
649 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
650 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
651 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
652 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
653 case VAR_LIST: isntype = ISN_COMPARELIST; break;
654 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
655 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100656 default: isntype = ISN_COMPAREANY; break;
657 }
658 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200659 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100660 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
661 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
662 isntype = ISN_COMPAREANY;
663
664 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
665 && (isntype == ISN_COMPAREBOOL
666 || isntype == ISN_COMPARESPECIAL
667 || isntype == ISN_COMPARENR
668 || isntype == ISN_COMPAREFLOAT))
669 {
670 semsg(_("E1037: Cannot use \"%s\" with %s"),
671 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
672 return FAIL;
673 }
674 if (isntype == ISN_DROP
675 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
676 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
677 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
678 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
679 && exptype != EXPR_IS && exptype != EXPR_ISNOT
680 && (type1 == VAR_BLOB || type2 == VAR_BLOB
681 || type1 == VAR_LIST || type2 == VAR_LIST))))
682 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100683 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100684 vartype_name(type1), vartype_name(type2));
685 return FAIL;
686 }
687
688 if ((isn = generate_instr(cctx, isntype)) == NULL)
689 return FAIL;
690 isn->isn_arg.op.op_type = exptype;
691 isn->isn_arg.op.op_ic = ic;
692
693 // takes two arguments, puts one bool back
694 if (stack->ga_len >= 2)
695 {
696 --stack->ga_len;
697 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
698 }
699
700 return OK;
701}
702
703/*
704 * Generate an ISN_2BOOL instruction.
705 */
706 static int
707generate_2BOOL(cctx_T *cctx, int invert)
708{
709 isn_T *isn;
710 garray_T *stack = &cctx->ctx_type_stack;
711
Bram Moolenaar080457c2020-03-03 21:53:32 +0100712 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100713 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
714 return FAIL;
715 isn->isn_arg.number = invert;
716
717 // type becomes bool
718 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
719
720 return OK;
721}
722
723 static int
724generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
725{
726 isn_T *isn;
727 garray_T *stack = &cctx->ctx_type_stack;
728
Bram Moolenaar080457c2020-03-03 21:53:32 +0100729 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100730 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
731 return FAIL;
Bram Moolenaar939b5db2020-04-28 22:49:08 +0200732 // TODO: whole type, e.g. for a function also arg and return types
733 isn->isn_arg.type.ct_type = vartype->tt_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100734 isn->isn_arg.type.ct_off = offset;
735
736 // type becomes vartype
737 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
738
739 return OK;
740}
741
742/*
743 * Generate an ISN_PUSHNR instruction.
744 */
745 static int
746generate_PUSHNR(cctx_T *cctx, varnumber_T number)
747{
748 isn_T *isn;
749
Bram Moolenaar080457c2020-03-03 21:53:32 +0100750 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100751 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
752 return FAIL;
753 isn->isn_arg.number = number;
754
755 return OK;
756}
757
758/*
759 * Generate an ISN_PUSHBOOL instruction.
760 */
761 static int
762generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
763{
764 isn_T *isn;
765
Bram Moolenaar080457c2020-03-03 21:53:32 +0100766 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100767 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
768 return FAIL;
769 isn->isn_arg.number = number;
770
771 return OK;
772}
773
774/*
775 * Generate an ISN_PUSHSPEC instruction.
776 */
777 static int
778generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
779{
780 isn_T *isn;
781
Bram Moolenaar080457c2020-03-03 21:53:32 +0100782 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100783 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
784 return FAIL;
785 isn->isn_arg.number = number;
786
787 return OK;
788}
789
790#ifdef FEAT_FLOAT
791/*
792 * Generate an ISN_PUSHF instruction.
793 */
794 static int
795generate_PUSHF(cctx_T *cctx, float_T fnumber)
796{
797 isn_T *isn;
798
Bram Moolenaar080457c2020-03-03 21:53:32 +0100799 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100800 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
801 return FAIL;
802 isn->isn_arg.fnumber = fnumber;
803
804 return OK;
805}
806#endif
807
808/*
809 * Generate an ISN_PUSHS instruction.
810 * Consumes "str".
811 */
812 static int
813generate_PUSHS(cctx_T *cctx, char_u *str)
814{
815 isn_T *isn;
816
Bram Moolenaar080457c2020-03-03 21:53:32 +0100817 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100818 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
819 return FAIL;
820 isn->isn_arg.string = str;
821
822 return OK;
823}
824
825/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100826 * Generate an ISN_PUSHCHANNEL instruction.
827 * Consumes "channel".
828 */
829 static int
830generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
831{
832 isn_T *isn;
833
Bram Moolenaar080457c2020-03-03 21:53:32 +0100834 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100835 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
836 return FAIL;
837 isn->isn_arg.channel = channel;
838
839 return OK;
840}
841
842/*
843 * Generate an ISN_PUSHJOB instruction.
844 * Consumes "job".
845 */
846 static int
847generate_PUSHJOB(cctx_T *cctx, job_T *job)
848{
849 isn_T *isn;
850
Bram Moolenaar080457c2020-03-03 21:53:32 +0100851 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100852 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100853 return FAIL;
854 isn->isn_arg.job = job;
855
856 return OK;
857}
858
859/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100860 * Generate an ISN_PUSHBLOB instruction.
861 * Consumes "blob".
862 */
863 static int
864generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
865{
866 isn_T *isn;
867
Bram Moolenaar080457c2020-03-03 21:53:32 +0100868 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100869 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
870 return FAIL;
871 isn->isn_arg.blob = blob;
872
873 return OK;
874}
875
876/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100877 * Generate an ISN_PUSHFUNC instruction with name "name".
878 * Consumes "name".
879 */
880 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200881generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100882{
883 isn_T *isn;
884
Bram Moolenaar080457c2020-03-03 21:53:32 +0100885 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200886 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100887 return FAIL;
888 isn->isn_arg.string = name;
889
890 return OK;
891}
892
893/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100894 * Generate an ISN_STORE instruction.
895 */
896 static int
897generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
898{
899 isn_T *isn;
900
Bram Moolenaar080457c2020-03-03 21:53:32 +0100901 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100902 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
903 return FAIL;
904 if (name != NULL)
905 isn->isn_arg.string = vim_strsave(name);
906 else
907 isn->isn_arg.number = idx;
908
909 return OK;
910}
911
912/*
913 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
914 */
915 static int
916generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
917{
918 isn_T *isn;
919
Bram Moolenaar080457c2020-03-03 21:53:32 +0100920 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100921 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
922 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100923 isn->isn_arg.storenr.stnr_idx = idx;
924 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100925
926 return OK;
927}
928
929/*
930 * Generate an ISN_STOREOPT instruction
931 */
932 static int
933generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
934{
935 isn_T *isn;
936
Bram Moolenaar080457c2020-03-03 21:53:32 +0100937 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100938 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
939 return FAIL;
940 isn->isn_arg.storeopt.so_name = vim_strsave(name);
941 isn->isn_arg.storeopt.so_flags = opt_flags;
942
943 return OK;
944}
945
946/*
947 * Generate an ISN_LOAD or similar instruction.
948 */
949 static int
950generate_LOAD(
951 cctx_T *cctx,
952 isntype_T isn_type,
953 int idx,
954 char_u *name,
955 type_T *type)
956{
957 isn_T *isn;
958
Bram Moolenaar080457c2020-03-03 21:53:32 +0100959 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100960 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
961 return FAIL;
962 if (name != NULL)
963 isn->isn_arg.string = vim_strsave(name);
964 else
965 isn->isn_arg.number = idx;
966
967 return OK;
968}
969
970/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200971 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100972 */
973 static int
974generate_LOADV(
975 cctx_T *cctx,
976 char_u *name,
977 int error)
978{
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200979 int di_flags;
980 int vidx = find_vim_var(name, &di_flags);
981 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100982
Bram Moolenaar080457c2020-03-03 21:53:32 +0100983 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100984 if (vidx < 0)
985 {
986 if (error)
987 semsg(_(e_var_notfound), name);
988 return FAIL;
989 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200990 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100991
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200992 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100993}
994
995/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200996 * Generate an ISN_UNLET instruction.
997 */
998 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200999generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001000{
1001 isn_T *isn;
1002
1003 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02001004 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02001005 return FAIL;
1006 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1007 isn->isn_arg.unlet.ul_forceit = forceit;
1008
1009 return OK;
1010}
1011
1012/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001013 * Generate an ISN_LOADS instruction.
1014 */
1015 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001016generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001017 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001018 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001019 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001020 int sid,
1021 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001022{
1023 isn_T *isn;
1024
Bram Moolenaar080457c2020-03-03 21:53:32 +01001025 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001026 if (isn_type == ISN_LOADS)
1027 isn = generate_instr_type(cctx, isn_type, type);
1028 else
1029 isn = generate_instr_drop(cctx, isn_type, 1);
1030 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001031 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001032 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1033 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001034
1035 return OK;
1036}
1037
1038/*
1039 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1040 */
1041 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001042generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001043 cctx_T *cctx,
1044 isntype_T isn_type,
1045 int sid,
1046 int idx,
1047 type_T *type)
1048{
1049 isn_T *isn;
1050
Bram Moolenaar080457c2020-03-03 21:53:32 +01001051 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001052 if (isn_type == ISN_LOADSCRIPT)
1053 isn = generate_instr_type(cctx, isn_type, type);
1054 else
1055 isn = generate_instr_drop(cctx, isn_type, 1);
1056 if (isn == NULL)
1057 return FAIL;
1058 isn->isn_arg.script.script_sid = sid;
1059 isn->isn_arg.script.script_idx = idx;
1060 return OK;
1061}
1062
1063/*
1064 * Generate an ISN_NEWLIST instruction.
1065 */
1066 static int
1067generate_NEWLIST(cctx_T *cctx, int count)
1068{
1069 isn_T *isn;
1070 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001071 type_T *type;
1072 type_T *member;
1073
Bram Moolenaar080457c2020-03-03 21:53:32 +01001074 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001075 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1076 return FAIL;
1077 isn->isn_arg.number = count;
1078
1079 // drop the value types
1080 stack->ga_len -= count;
1081
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001082 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001083 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001084 if (count > 0)
1085 member = ((type_T **)stack->ga_data)[stack->ga_len];
1086 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001087 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001088 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001089
1090 // add the list type to the type stack
1091 if (ga_grow(stack, 1) == FAIL)
1092 return FAIL;
1093 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1094 ++stack->ga_len;
1095
1096 return OK;
1097}
1098
1099/*
1100 * Generate an ISN_NEWDICT instruction.
1101 */
1102 static int
1103generate_NEWDICT(cctx_T *cctx, int count)
1104{
1105 isn_T *isn;
1106 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001107 type_T *type;
1108 type_T *member;
1109
Bram Moolenaar080457c2020-03-03 21:53:32 +01001110 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001111 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1112 return FAIL;
1113 isn->isn_arg.number = count;
1114
1115 // drop the key and value types
1116 stack->ga_len -= 2 * count;
1117
Bram Moolenaar436472f2020-02-20 22:54:43 +01001118 // Use the first value type for the list member type. Use "void" for an
1119 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001120 if (count > 0)
1121 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1122 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001123 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001124 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001125
1126 // add the dict type to the type stack
1127 if (ga_grow(stack, 1) == FAIL)
1128 return FAIL;
1129 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1130 ++stack->ga_len;
1131
1132 return OK;
1133}
1134
1135/*
1136 * Generate an ISN_FUNCREF instruction.
1137 */
1138 static int
1139generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1140{
1141 isn_T *isn;
1142 garray_T *stack = &cctx->ctx_type_stack;
1143
Bram Moolenaar080457c2020-03-03 21:53:32 +01001144 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001145 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1146 return FAIL;
1147 isn->isn_arg.number = dfunc_idx;
1148
1149 if (ga_grow(stack, 1) == FAIL)
1150 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001151 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001152 // TODO: argument and return types
1153 ++stack->ga_len;
1154
1155 return OK;
1156}
1157
1158/*
1159 * Generate an ISN_JUMP instruction.
1160 */
1161 static int
1162generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1163{
1164 isn_T *isn;
1165 garray_T *stack = &cctx->ctx_type_stack;
1166
Bram Moolenaar080457c2020-03-03 21:53:32 +01001167 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001168 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1169 return FAIL;
1170 isn->isn_arg.jump.jump_when = when;
1171 isn->isn_arg.jump.jump_where = where;
1172
1173 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1174 --stack->ga_len;
1175
1176 return OK;
1177}
1178
1179 static int
1180generate_FOR(cctx_T *cctx, int loop_idx)
1181{
1182 isn_T *isn;
1183 garray_T *stack = &cctx->ctx_type_stack;
1184
Bram Moolenaar080457c2020-03-03 21:53:32 +01001185 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001186 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1187 return FAIL;
1188 isn->isn_arg.forloop.for_idx = loop_idx;
1189
1190 if (ga_grow(stack, 1) == FAIL)
1191 return FAIL;
1192 // type doesn't matter, will be stored next
1193 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1194 ++stack->ga_len;
1195
1196 return OK;
1197}
1198
1199/*
1200 * Generate an ISN_BCALL instruction.
1201 * Return FAIL if the number of arguments is wrong.
1202 */
1203 static int
1204generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1205{
1206 isn_T *isn;
1207 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001208 type_T *argtypes[MAX_FUNC_ARGS];
1209 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001210
Bram Moolenaar080457c2020-03-03 21:53:32 +01001211 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001212 if (check_internal_func(func_idx, argcount) == FAIL)
1213 return FAIL;
1214
1215 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1216 return FAIL;
1217 isn->isn_arg.bfunc.cbf_idx = func_idx;
1218 isn->isn_arg.bfunc.cbf_argcount = argcount;
1219
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001220 for (i = 0; i < argcount; ++i)
1221 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1222
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001223 stack->ga_len -= argcount; // drop the arguments
1224 if (ga_grow(stack, 1) == FAIL)
1225 return FAIL;
1226 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001227 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001228 ++stack->ga_len; // add return value
1229
1230 return OK;
1231}
1232
1233/*
1234 * Generate an ISN_DCALL or ISN_UCALL instruction.
1235 * Return FAIL if the number of arguments is wrong.
1236 */
1237 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001238generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001239{
1240 isn_T *isn;
1241 garray_T *stack = &cctx->ctx_type_stack;
1242 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001243 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001244
Bram Moolenaar080457c2020-03-03 21:53:32 +01001245 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001246 if (argcount > regular_args && !has_varargs(ufunc))
1247 {
1248 semsg(_(e_toomanyarg), ufunc->uf_name);
1249 return FAIL;
1250 }
1251 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1252 {
1253 semsg(_(e_toofewarg), ufunc->uf_name);
1254 return FAIL;
1255 }
1256
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001257 if (ufunc->uf_dfunc_idx >= 0)
1258 {
1259 int i;
1260
1261 for (i = 0; i < argcount; ++i)
1262 {
1263 type_T *expected;
1264 type_T *actual;
1265
1266 if (i < regular_args)
1267 {
1268 if (ufunc->uf_arg_types == NULL)
1269 continue;
1270 expected = ufunc->uf_arg_types[i];
1271 }
1272 else
1273 expected = ufunc->uf_va_type->tt_member;
1274 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1275 if (check_type(expected, actual, FALSE) == FAIL)
1276 {
1277 arg_type_mismatch(expected, actual, i + 1);
1278 return FAIL;
1279 }
1280 }
1281 }
1282
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001283 if ((isn = generate_instr(cctx,
1284 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1285 return FAIL;
1286 if (ufunc->uf_dfunc_idx >= 0)
1287 {
1288 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1289 isn->isn_arg.dfunc.cdf_argcount = argcount;
1290 }
1291 else
1292 {
1293 // A user function may be deleted and redefined later, can't use the
1294 // ufunc pointer, need to look it up again at runtime.
1295 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1296 isn->isn_arg.ufunc.cuf_argcount = argcount;
1297 }
1298
1299 stack->ga_len -= argcount; // drop the arguments
1300 if (ga_grow(stack, 1) == FAIL)
1301 return FAIL;
1302 // add return value
1303 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1304 ++stack->ga_len;
1305
1306 return OK;
1307}
1308
1309/*
1310 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1311 */
1312 static int
1313generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1314{
1315 isn_T *isn;
1316 garray_T *stack = &cctx->ctx_type_stack;
1317
Bram Moolenaar080457c2020-03-03 21:53:32 +01001318 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001319 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1320 return FAIL;
1321 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1322 isn->isn_arg.ufunc.cuf_argcount = argcount;
1323
1324 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001325 if (ga_grow(stack, 1) == FAIL)
1326 return FAIL;
1327 // add return value
1328 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1329 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001330
1331 return OK;
1332}
1333
1334/*
1335 * Generate an ISN_PCALL instruction.
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001336 * "type" is the type of the FuncRef.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001337 */
1338 static int
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001339generate_PCALL(
1340 cctx_T *cctx,
1341 int argcount,
1342 char_u *name,
1343 type_T *type,
1344 int at_top)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001345{
1346 isn_T *isn;
1347 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001348 type_T *ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001349
Bram Moolenaar080457c2020-03-03 21:53:32 +01001350 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001351
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001352 if (type->tt_type == VAR_ANY)
1353 ret_type = &t_any;
1354 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
1355 ret_type = type->tt_member;
1356 else
1357 {
1358 semsg(_("E1085: Not a callable type: %s"), name);
1359 return FAIL;
1360 }
1361
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001362 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1363 return FAIL;
1364 isn->isn_arg.pfunc.cpf_top = at_top;
1365 isn->isn_arg.pfunc.cpf_argcount = argcount;
1366
1367 stack->ga_len -= argcount; // drop the arguments
1368
1369 // drop the funcref/partial, get back the return value
Bram Moolenaara0a9f432020-04-28 21:29:34 +02001370 ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001371
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001372 // If partial is above the arguments it must be cleared and replaced with
1373 // the return value.
1374 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1375 return FAIL;
1376
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001377 return OK;
1378}
1379
1380/*
1381 * Generate an ISN_MEMBER instruction.
1382 */
1383 static int
1384generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1385{
1386 isn_T *isn;
1387 garray_T *stack = &cctx->ctx_type_stack;
1388 type_T *type;
1389
Bram Moolenaar080457c2020-03-03 21:53:32 +01001390 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001391 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1392 return FAIL;
1393 isn->isn_arg.string = vim_strnsave(name, (int)len);
1394
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001395 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001396 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001397 if (type->tt_type != VAR_DICT && type != &t_any)
1398 {
1399 emsg(_(e_dictreq));
1400 return FAIL;
1401 }
1402 // change dict type to dict member type
1403 if (type->tt_type == VAR_DICT)
1404 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001405
1406 return OK;
1407}
1408
1409/*
1410 * Generate an ISN_ECHO instruction.
1411 */
1412 static int
1413generate_ECHO(cctx_T *cctx, int with_white, int count)
1414{
1415 isn_T *isn;
1416
Bram Moolenaar080457c2020-03-03 21:53:32 +01001417 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001418 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1419 return FAIL;
1420 isn->isn_arg.echo.echo_with_white = with_white;
1421 isn->isn_arg.echo.echo_count = count;
1422
1423 return OK;
1424}
1425
Bram Moolenaarad39c092020-02-26 18:23:43 +01001426/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001427 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001428 */
1429 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001430generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001431{
1432 isn_T *isn;
1433
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001434 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001435 return FAIL;
1436 isn->isn_arg.number = count;
1437
1438 return OK;
1439}
1440
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001441 static int
1442generate_EXEC(cctx_T *cctx, char_u *line)
1443{
1444 isn_T *isn;
1445
Bram Moolenaar080457c2020-03-03 21:53:32 +01001446 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001447 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1448 return FAIL;
1449 isn->isn_arg.string = vim_strsave(line);
1450 return OK;
1451}
1452
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001453 static int
1454generate_EXECCONCAT(cctx_T *cctx, int count)
1455{
1456 isn_T *isn;
1457
1458 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1459 return FAIL;
1460 isn->isn_arg.number = count;
1461 return OK;
1462}
1463
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001464/*
1465 * Reserve space for a local variable.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001466 * Return the variable or NULL if it failed.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001467 */
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001468 static lvar_T *
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001469reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1470{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001471 lvar_T *lvar;
1472
1473 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1474 {
1475 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001476 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001477 }
1478
1479 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001480 return NULL;
1481 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001482
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001483 // Every local variable uses the next entry on the stack. We could re-use
1484 // the last ones when leaving a scope, but then variables used in a closure
1485 // might get overwritten. To keep things simple do not re-use stack
1486 // entries. This is less efficient, but memory is cheap these days.
1487 lvar->lv_idx = cctx->ctx_locals_count++;
1488
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001489 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1490 lvar->lv_const = isConst;
1491 lvar->lv_type = type;
1492
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001493 return lvar;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001494}
1495
1496/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001497 * Remove local variables above "new_top".
1498 */
1499 static void
1500unwind_locals(cctx_T *cctx, int new_top)
1501{
1502 if (cctx->ctx_locals.ga_len > new_top)
1503 {
1504 int idx;
1505 lvar_T *lvar;
1506
1507 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1508 {
1509 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1510 vim_free(lvar->lv_name);
1511 }
1512 }
1513 cctx->ctx_locals.ga_len = new_top;
1514}
1515
1516/*
1517 * Free all local variables.
1518 */
1519 static void
Bram Moolenaarb84a3812020-05-01 15:44:29 +02001520free_locals(cctx_T *cctx)
Bram Moolenaar20431c92020-03-20 18:39:46 +01001521{
1522 unwind_locals(cctx, 0);
1523 ga_clear(&cctx->ctx_locals);
1524}
1525
1526/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001527 * Skip over a type definition and return a pointer to just after it.
1528 */
1529 char_u *
1530skip_type(char_u *start)
1531{
1532 char_u *p = start;
1533
1534 while (ASCII_ISALNUM(*p) || *p == '_')
1535 ++p;
1536
1537 // Skip over "<type>"; this is permissive about white space.
1538 if (*skipwhite(p) == '<')
1539 {
1540 p = skipwhite(p);
1541 p = skip_type(skipwhite(p + 1));
1542 p = skipwhite(p);
1543 if (*p == '>')
1544 ++p;
1545 }
1546 return p;
1547}
1548
1549/*
1550 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001551 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001552 * Returns NULL in case of failure.
1553 */
1554 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001555parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001556{
1557 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001558 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001559
1560 if (**arg != '<')
1561 {
1562 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001563 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001564 else
1565 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001566 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001567 }
1568 *arg = skipwhite(*arg + 1);
1569
Bram Moolenaard77a8522020-04-03 21:59:57 +02001570 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001571
1572 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001573 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001574 {
1575 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001576 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001577 }
1578 ++*arg;
1579
1580 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001581 return get_list_type(member_type, type_gap);
1582 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001583}
1584
1585/*
1586 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001587 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001588 */
1589 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001590parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001591{
1592 char_u *p = *arg;
1593 size_t len;
1594
1595 // skip over the first word
1596 while (ASCII_ISALNUM(*p) || *p == '_')
1597 ++p;
1598 len = p - *arg;
1599
1600 switch (**arg)
1601 {
1602 case 'a':
1603 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1604 {
1605 *arg += len;
1606 return &t_any;
1607 }
1608 break;
1609 case 'b':
1610 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1611 {
1612 *arg += len;
1613 return &t_bool;
1614 }
1615 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1616 {
1617 *arg += len;
1618 return &t_blob;
1619 }
1620 break;
1621 case 'c':
1622 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1623 {
1624 *arg += len;
1625 return &t_channel;
1626 }
1627 break;
1628 case 'd':
1629 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1630 {
1631 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001632 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001633 }
1634 break;
1635 case 'f':
1636 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1637 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001638#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001639 *arg += len;
1640 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001641#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001642 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001643 return &t_any;
1644#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001645 }
1646 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1647 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001648 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001649 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001650 int argcount = -1;
1651 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001652 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001653 type_T *arg_type[MAX_FUNC_ARGS + 1];
1654
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001655 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001656 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001657 if (**arg == '(')
1658 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001659 // "func" may or may not return a value, "func()" does
1660 // not return a value.
1661 ret_type = &t_void;
1662
Bram Moolenaard77a8522020-04-03 21:59:57 +02001663 p = ++*arg;
1664 argcount = 0;
1665 while (*p != NUL && *p != ')')
1666 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001667 if (*p == '?')
1668 {
1669 if (first_optional == -1)
1670 first_optional = argcount;
1671 ++p;
1672 }
1673 else if (first_optional != -1)
1674 {
1675 emsg(_("E1007: mandatory argument after optional argument"));
1676 return &t_any;
1677 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001678 else if (STRNCMP(p, "...", 3) == 0)
1679 {
1680 flags |= TTFLAG_VARARGS;
1681 p += 3;
1682 }
1683
1684 arg_type[argcount++] = parse_type(&p, type_gap);
1685
1686 // Nothing comes after "...{type}".
1687 if (flags & TTFLAG_VARARGS)
1688 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001689
Bram Moolenaard77a8522020-04-03 21:59:57 +02001690 if (*p != ',' && *skipwhite(p) == ',')
1691 {
1692 semsg(_(e_no_white_before), ",");
1693 return &t_any;
1694 }
1695 if (*p == ',')
1696 {
1697 ++p;
1698 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001699 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001700 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001701 return &t_any;
1702 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001703 }
1704 p = skipwhite(p);
1705 if (argcount == MAX_FUNC_ARGS)
1706 {
1707 emsg(_("E740: Too many argument types"));
1708 return &t_any;
1709 }
1710 }
1711
1712 p = skipwhite(p);
1713 if (*p != ')')
1714 {
1715 emsg(_(e_missing_close));
1716 return &t_any;
1717 }
1718 *arg = p + 1;
1719 }
1720 if (**arg == ':')
1721 {
1722 // parse return type
1723 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001724 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001725 semsg(_(e_white_after), ":");
1726 *arg = skipwhite(*arg);
1727 ret_type = parse_type(arg, type_gap);
1728 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001729 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001730 type = get_func_type(ret_type, argcount, type_gap);
1731 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001732 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001733 type = alloc_func_type(ret_type, argcount, type_gap);
1734 type->tt_flags = flags;
1735 if (argcount > 0)
1736 {
1737 type->tt_argcount = argcount;
1738 type->tt_min_argcount = first_optional == -1
1739 ? argcount : first_optional;
1740 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001741 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001742 return &t_any;
1743 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001744 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001745 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001746 }
1747 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001748 }
1749 break;
1750 case 'j':
1751 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1752 {
1753 *arg += len;
1754 return &t_job;
1755 }
1756 break;
1757 case 'l':
1758 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1759 {
1760 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001761 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001762 }
1763 break;
1764 case 'n':
1765 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1766 {
1767 *arg += len;
1768 return &t_number;
1769 }
1770 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001771 case 's':
1772 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1773 {
1774 *arg += len;
1775 return &t_string;
1776 }
1777 break;
1778 case 'v':
1779 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1780 {
1781 *arg += len;
1782 return &t_void;
1783 }
1784 break;
1785 }
1786
1787 semsg(_("E1010: Type not recognized: %s"), *arg);
1788 return &t_any;
1789}
1790
1791/*
1792 * Check if "type1" and "type2" are exactly the same.
1793 */
1794 static int
1795equal_type(type_T *type1, type_T *type2)
1796{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001797 int i;
1798
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001799 if (type1->tt_type != type2->tt_type)
1800 return FALSE;
1801 switch (type1->tt_type)
1802 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001803 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001804 case VAR_ANY:
1805 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001806 case VAR_SPECIAL:
1807 case VAR_BOOL:
1808 case VAR_NUMBER:
1809 case VAR_FLOAT:
1810 case VAR_STRING:
1811 case VAR_BLOB:
1812 case VAR_JOB:
1813 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001814 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001815 case VAR_LIST:
1816 case VAR_DICT:
1817 return equal_type(type1->tt_member, type2->tt_member);
1818 case VAR_FUNC:
1819 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001820 if (!equal_type(type1->tt_member, type2->tt_member)
1821 || type1->tt_argcount != type2->tt_argcount)
1822 return FALSE;
1823 if (type1->tt_argcount < 0
1824 || type1->tt_args == NULL || type2->tt_args == NULL)
1825 return TRUE;
1826 for (i = 0; i < type1->tt_argcount; ++i)
1827 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1828 return FALSE;
1829 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001830 }
1831 return TRUE;
1832}
1833
1834/*
1835 * Find the common type of "type1" and "type2" and put it in "dest".
1836 * "type2" and "dest" may be the same.
1837 */
1838 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001839common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001840{
1841 if (equal_type(type1, type2))
1842 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001843 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001844 return;
1845 }
1846
1847 if (type1->tt_type == type2->tt_type)
1848 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001849 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1850 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001851 type_T *common;
1852
Bram Moolenaard77a8522020-04-03 21:59:57 +02001853 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001854 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001855 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001856 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001857 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001858 return;
1859 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001860 if (type1->tt_type == VAR_FUNC)
1861 {
1862 type_T *common;
1863
1864 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1865 if (type1->tt_argcount == type2->tt_argcount
1866 && type1->tt_argcount >= 0)
1867 {
1868 int argcount = type1->tt_argcount;
1869 int i;
1870
1871 *dest = alloc_func_type(common, argcount, type_gap);
1872 if (type1->tt_args != NULL && type2->tt_args != NULL)
1873 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001874 if (func_type_add_arg_types(*dest, argcount,
1875 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001876 for (i = 0; i < argcount; ++i)
1877 common_type(type1->tt_args[i], type2->tt_args[i],
1878 &(*dest)->tt_args[i], type_gap);
1879 }
1880 }
1881 else
1882 *dest = alloc_func_type(common, -1, type_gap);
1883 return;
1884 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001885 }
1886
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001887 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001888}
1889
1890 char *
1891vartype_name(vartype_T type)
1892{
1893 switch (type)
1894 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001895 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001896 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001897 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001898 case VAR_SPECIAL: return "special";
1899 case VAR_BOOL: return "bool";
1900 case VAR_NUMBER: return "number";
1901 case VAR_FLOAT: return "float";
1902 case VAR_STRING: return "string";
1903 case VAR_BLOB: return "blob";
1904 case VAR_JOB: return "job";
1905 case VAR_CHANNEL: return "channel";
1906 case VAR_LIST: return "list";
1907 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001908
1909 case VAR_FUNC:
1910 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001911 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001912 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001913}
1914
1915/*
1916 * Return the name of a type.
1917 * The result may be in allocated memory, in which case "tofree" is set.
1918 */
1919 char *
1920type_name(type_T *type, char **tofree)
1921{
1922 char *name = vartype_name(type->tt_type);
1923
1924 *tofree = NULL;
1925 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1926 {
1927 char *member_free;
1928 char *member_name = type_name(type->tt_member, &member_free);
1929 size_t len;
1930
1931 len = STRLEN(name) + STRLEN(member_name) + 3;
1932 *tofree = alloc(len);
1933 if (*tofree != NULL)
1934 {
1935 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1936 vim_free(member_free);
1937 return *tofree;
1938 }
1939 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001940 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001941 {
1942 garray_T ga;
1943 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001944 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001945
1946 ga_init2(&ga, 1, 100);
1947 if (ga_grow(&ga, 20) == FAIL)
1948 return "[unknown]";
1949 *tofree = ga.ga_data;
1950 STRCPY(ga.ga_data, "func(");
1951 ga.ga_len += 5;
1952
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001953 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001954 {
1955 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001956 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001957 int len;
1958
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001959 if (type->tt_args == NULL)
1960 arg_type = "[unknown]";
1961 else
1962 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001963 if (i > 0)
1964 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001965 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001966 ga.ga_len += 2;
1967 }
1968 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001969 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001970 {
1971 vim_free(arg_free);
1972 return "[unknown]";
1973 }
1974 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001975 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001976 {
1977 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1978 ga.ga_len += 3;
1979 }
1980 else if (i >= type->tt_min_argcount)
1981 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001982 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001983 ga.ga_len += len;
1984 vim_free(arg_free);
1985 }
1986
1987 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001988 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001989 else
1990 {
1991 char *ret_free;
1992 char *ret_name = type_name(type->tt_member, &ret_free);
1993 int len;
1994
1995 len = (int)STRLEN(ret_name) + 4;
1996 if (ga_grow(&ga, len) == FAIL)
1997 {
1998 vim_free(ret_free);
1999 return "[unknown]";
2000 }
2001 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02002002 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
2003 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002004 vim_free(ret_free);
2005 }
2006 return ga.ga_data;
2007 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002008
2009 return name;
2010}
2011
2012/*
2013 * Find "name" in script-local items of script "sid".
2014 * Returns the index in "sn_var_vals" if found.
2015 * If found but not in "sn_var_vals" returns -1.
2016 * If not found returns -2.
2017 */
2018 int
2019get_script_item_idx(int sid, char_u *name, int check_writable)
2020{
2021 hashtab_T *ht;
2022 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002023 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002024 int idx;
2025
2026 // First look the name up in the hashtable.
2027 if (sid <= 0 || sid > script_items.ga_len)
2028 return -1;
2029 ht = &SCRIPT_VARS(sid);
2030 di = find_var_in_ht(ht, 0, name, TRUE);
2031 if (di == NULL)
2032 return -2;
2033
2034 // Now find the svar_T index in sn_var_vals.
2035 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2036 {
2037 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2038
2039 if (sv->sv_tv == &di->di_tv)
2040 {
2041 if (check_writable && sv->sv_const)
2042 semsg(_(e_readonlyvar), name);
2043 return idx;
2044 }
2045 }
2046 return -1;
2047}
2048
2049/*
2050 * Find "name" in imported items of the current script/
2051 */
2052 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002053find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002054{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002055 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002056 int idx;
2057
2058 if (cctx != NULL)
2059 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2060 {
2061 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2062 + idx;
2063
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002064 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2065 : STRLEN(import->imp_name) == len
2066 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002067 return import;
2068 }
2069
2070 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2071 {
2072 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2073
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002074 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2075 : STRLEN(import->imp_name) == len
2076 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002077 return import;
2078 }
2079 return NULL;
2080}
2081
2082/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002083 * Free all imported variables.
2084 */
2085 static void
2086free_imported(cctx_T *cctx)
2087{
2088 int idx;
2089
2090 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2091 {
2092 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2093
2094 vim_free(import->imp_name);
2095 }
2096 ga_clear(&cctx->ctx_imports);
2097}
2098
2099/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002100 * Get the next line of the function from "cctx".
2101 * Returns NULL when at the end.
2102 */
2103 static char_u *
2104next_line_from_context(cctx_T *cctx)
2105{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002106 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002107
2108 do
2109 {
2110 ++cctx->ctx_lnum;
2111 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002112 {
2113 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002114 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002115 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002116 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002117 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002118 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2119 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002120 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002121 return line;
2122}
2123
2124/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002125 * Return TRUE if "p" points at a "#" but not at "#{".
2126 */
2127 static int
2128comment_start(char_u *p)
2129{
2130 return p[0] == '#' && p[1] != '{';
2131}
2132
2133/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002134 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002135 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002136 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2137 */
2138 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002139may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002140{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002141 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002142 {
2143 char_u *next = next_line_from_context(cctx);
2144
2145 if (next == NULL)
2146 return FAIL;
2147 *arg = skipwhite(next);
2148 }
2149 return OK;
2150}
2151
2152/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002153 * Generate an instruction to load script-local variable "name", without the
2154 * leading "s:".
2155 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002156 */
2157 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002158compile_load_scriptvar(
2159 cctx_T *cctx,
2160 char_u *name, // variable NUL terminated
2161 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002162 char_u **end, // end of variable
2163 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002164{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002165 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002166 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2167 imported_T *import;
2168
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002169 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002170 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002171 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002172 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2173 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002174 }
2175 if (idx >= 0)
2176 {
2177 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2178
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002179 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002180 current_sctx.sc_sid, idx, sv->sv_type);
2181 return OK;
2182 }
2183
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002184 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002185 if (import != NULL)
2186 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002187 if (import->imp_all)
2188 {
2189 char_u *p = skipwhite(*end);
2190 int name_len;
2191 ufunc_T *ufunc;
2192 type_T *type;
2193
2194 // Used "import * as Name", need to lookup the member.
2195 if (*p != '.')
2196 {
2197 semsg(_("E1060: expected dot after name: %s"), start);
2198 return FAIL;
2199 }
2200 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002201 if (VIM_ISWHITE(*p))
2202 {
2203 emsg(_("E1074: no white space allowed after dot"));
2204 return FAIL;
2205 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002206
2207 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2208 // TODO: what if it is a function?
2209 if (idx < 0)
2210 return FAIL;
2211 *end = p;
2212
2213 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2214 import->imp_sid,
2215 idx,
2216 type);
2217 }
2218 else
2219 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002220 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002221 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2222 import->imp_sid,
2223 import->imp_var_vals_idx,
2224 import->imp_type);
2225 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002226 return OK;
2227 }
2228
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002229 if (error)
2230 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002231 return FAIL;
2232}
2233
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002234 static int
2235generate_funcref(cctx_T *cctx, char_u *name)
2236{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002237 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002238
2239 if (ufunc == NULL)
2240 return FAIL;
2241
2242 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2243}
2244
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002245/*
2246 * Compile a variable name into a load instruction.
2247 * "end" points to just after the name.
2248 * When "error" is FALSE do not give an error when not found.
2249 */
2250 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002251compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002252{
2253 type_T *type;
2254 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002255 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002256 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002257 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002258
2259 if (*(*arg + 1) == ':')
2260 {
2261 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002262 if (end <= *arg + 2)
2263 name = vim_strsave((char_u *)"[empty]");
2264 else
2265 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002266 if (name == NULL)
2267 return FAIL;
2268
2269 if (**arg == 'v')
2270 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002271 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002272 }
2273 else if (**arg == 'g')
2274 {
2275 // Global variables can be defined later, thus we don't check if it
2276 // exists, give error at runtime.
2277 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2278 }
2279 else if (**arg == 's')
2280 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002281 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002282 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002283 else if (**arg == 'b')
2284 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002285 // Buffer-local variables can be defined later, thus we don't check
2286 // if it exists, give error at runtime.
2287 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002288 }
2289 else if (**arg == 'w')
2290 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002291 // Window-local variables can be defined later, thus we don't check
2292 // if it exists, give error at runtime.
2293 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002294 }
2295 else if (**arg == 't')
2296 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002297 // Tabpage-local variables can be defined later, thus we don't
2298 // check if it exists, give error at runtime.
2299 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002300 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002301 else
2302 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002303 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002304 goto theend;
2305 }
2306 }
2307 else
2308 {
2309 size_t len = end - *arg;
2310 int idx;
2311 int gen_load = FALSE;
2312
2313 name = vim_strnsave(*arg, end - *arg);
2314 if (name == NULL)
2315 return FAIL;
2316
2317 idx = lookup_arg(*arg, len, cctx);
2318 if (idx >= 0)
2319 {
2320 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2321 type = cctx->ctx_ufunc->uf_arg_types[idx];
2322 else
2323 type = &t_any;
2324
2325 // Arguments are located above the frame pointer.
2326 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2327 if (cctx->ctx_ufunc->uf_va_name != NULL)
2328 --idx;
2329 gen_load = TRUE;
2330 }
2331 else if (lookup_vararg(*arg, len, cctx))
2332 {
2333 // varargs is always the last argument
2334 idx = -STACK_FRAME_SIZE - 1;
2335 type = cctx->ctx_ufunc->uf_va_type;
2336 gen_load = TRUE;
2337 }
2338 else
2339 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002340 lvar_T *lvar = lookup_local(*arg, len, cctx);
2341
2342 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002343 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02002344 type = lvar->lv_type;
2345 idx = lvar->lv_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002346 gen_load = TRUE;
2347 }
2348 else
2349 {
2350 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2351 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2352 res = generate_PUSHBOOL(cctx, **arg == 't'
2353 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002354 else
2355 {
2356 // "var" can be script-local even without using "s:" if it
2357 // already exists.
2358 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2359 == SCRIPT_VERSION_VIM9
2360 || lookup_script(*arg, len) == OK)
2361 res = compile_load_scriptvar(cctx, name, *arg, &end,
2362 FALSE);
2363
2364 // When the name starts with an uppercase letter or "x:" it
2365 // can be a user defined function.
2366 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2367 res = generate_funcref(cctx, name);
2368 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002369 }
2370 }
2371 if (gen_load)
2372 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2373 }
2374
2375 *arg = end;
2376
2377theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002378 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002379 semsg(_(e_var_notfound), name);
2380 vim_free(name);
2381 return res;
2382}
2383
2384/*
2385 * Compile the argument expressions.
2386 * "arg" points to just after the "(" and is advanced to after the ")"
2387 */
2388 static int
2389compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2390{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002391 char_u *p = *arg;
2392 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002393
Bram Moolenaare6085c52020-04-12 20:19:16 +02002394 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002395 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002396 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002397 {
2398 p = next_line_from_context(cctx);
2399 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002400 goto failret;
2401 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002402 p = skipwhite(p);
2403 }
2404 if (*p == ')')
2405 {
2406 *arg = p + 1;
2407 return OK;
2408 }
2409
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002410 if (compile_expr1(&p, cctx) == FAIL)
2411 return FAIL;
2412 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002413
2414 if (*p != ',' && *skipwhite(p) == ',')
2415 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002416 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002417 p = skipwhite(p);
2418 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002419 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002420 {
2421 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002422 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002423 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002424 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002425 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002426 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002427 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002428failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002429 emsg(_(e_missing_close));
2430 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002431}
2432
2433/*
2434 * Compile a function call: name(arg1, arg2)
2435 * "arg" points to "name", "arg + varlen" to the "(".
2436 * "argcount_init" is 1 for "value->method()"
2437 * Instructions:
2438 * EVAL arg1
2439 * EVAL arg2
2440 * BCALL / DCALL / UCALL
2441 */
2442 static int
2443compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2444{
2445 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002446 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002447 int argcount = argcount_init;
2448 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002449 char_u fname_buf[FLEN_FIXED + 1];
2450 char_u *tofree = NULL;
2451 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002452 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002453 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002454
2455 if (varlen >= sizeof(namebuf))
2456 {
2457 semsg(_("E1011: name too long: %s"), name);
2458 return FAIL;
2459 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002460 vim_strncpy(namebuf, *arg, varlen);
2461 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002462
2463 *arg = skipwhite(*arg + varlen + 1);
2464 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002465 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002466
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002467 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002468 {
2469 int idx;
2470
2471 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002472 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002473 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002474 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002475 else
2476 semsg(_(e_unknownfunc), namebuf);
2477 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002478 }
2479
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002480 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002481 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002482 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002483 {
2484 res = generate_CALL(cctx, ufunc, argcount);
2485 goto theend;
2486 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002487
2488 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002489 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002490 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002491 if (STRNCMP(namebuf, "g:", 2) != 0
2492 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002493 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002494 garray_T *stack = &cctx->ctx_type_stack;
2495 type_T *type;
2496
2497 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
2498 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002499 goto theend;
2500 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002501
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002502 // A global function may be defined only later. Need to figure out at
Bram Moolenaara0a9f432020-04-28 21:29:34 +02002503 // runtime. Also handles a FuncRef at runtime.
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002504 if (STRNCMP(namebuf, "g:", 2) == 0)
2505 res = generate_UCALL(cctx, name, argcount);
2506 else
2507 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002508
2509theend:
2510 vim_free(tofree);
2511 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002512}
2513
2514// like NAMESPACE_CHAR but with 'a' and 'l'.
2515#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2516
2517/*
2518 * Find the end of a variable or function name. Unlike find_name_end() this
2519 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002520 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002521 * Return a pointer to just after the name. Equal to "arg" if there is no
2522 * valid name.
2523 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002524 static char_u *
2525to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002526{
2527 char_u *p;
2528
2529 // Quick check for valid starting character.
2530 if (!eval_isnamec1(*arg))
2531 return arg;
2532
2533 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2534 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2535 // and can be used in slice "[n:]".
2536 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002537 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002538 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2539 break;
2540 return p;
2541}
2542
2543/*
2544 * Like to_name_end() but also skip over a list or dict constant.
2545 */
2546 char_u *
2547to_name_const_end(char_u *arg)
2548{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002549 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002550 typval_T rettv;
2551
2552 if (p == arg && *arg == '[')
2553 {
2554
2555 // Can be "[1, 2, 3]->Func()".
2556 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2557 p = arg;
2558 }
2559 else if (p == arg && *arg == '#' && arg[1] == '{')
2560 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002561 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002562 ++p;
2563 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2564 p = arg;
2565 }
2566 else if (p == arg && *arg == '{')
2567 {
2568 int ret = get_lambda_tv(&p, &rettv, FALSE);
2569
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002570 // Can be "{x -> ret}()".
2571 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002572 if (ret == NOTDONE)
2573 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2574 if (ret != OK)
2575 p = arg;
2576 }
2577
2578 return p;
2579}
2580
2581 static void
2582type_mismatch(type_T *expected, type_T *actual)
2583{
2584 char *tofree1, *tofree2;
2585
2586 semsg(_("E1013: type mismatch, expected %s but got %s"),
2587 type_name(expected, &tofree1), type_name(actual, &tofree2));
2588 vim_free(tofree1);
2589 vim_free(tofree2);
2590}
2591
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002592 static void
2593arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2594{
2595 char *tofree1, *tofree2;
2596
2597 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2598 argidx,
2599 type_name(expected, &tofree1), type_name(actual, &tofree2));
2600 vim_free(tofree1);
2601 vim_free(tofree2);
2602}
2603
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002604/*
2605 * Check if the expected and actual types match.
Bram Moolenaar939b5db2020-04-28 22:49:08 +02002606 * Does not allow for assigning "any" to a specific type.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002607 */
2608 static int
2609check_type(type_T *expected, type_T *actual, int give_msg)
2610{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002611 int ret = OK;
2612
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002613 // When expected is "unknown" we accept any actual type.
2614 // When expected is "any" we accept any actual type except "void".
2615 if (expected->tt_type != VAR_UNKNOWN
Bram Moolenaar939b5db2020-04-28 22:49:08 +02002616 && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID))
2617
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002618 {
2619 if (expected->tt_type != actual->tt_type)
2620 {
2621 if (give_msg)
2622 type_mismatch(expected, actual);
2623 return FAIL;
2624 }
2625 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2626 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002627 // "unknown" is used for an empty list or dict
2628 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002629 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002630 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002631 else if (expected->tt_type == VAR_FUNC)
2632 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002633 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002634 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2635 if (ret == OK && expected->tt_argcount != -1
2636 && (actual->tt_argcount < expected->tt_min_argcount
2637 || actual->tt_argcount > expected->tt_argcount))
2638 ret = FAIL;
2639 }
2640 if (ret == FAIL && give_msg)
2641 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002642 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002643 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002644}
2645
2646/*
2647 * Check that
2648 * - "actual" is "expected" type or
2649 * - "actual" is a type that can be "expected" type: add a runtime check; or
2650 * - return FAIL.
2651 */
2652 static int
2653need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2654{
Bram Moolenaar89228602020-04-05 22:14:54 +02002655 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002656 return OK;
Bram Moolenaar939b5db2020-04-28 22:49:08 +02002657 if (actual->tt_type != VAR_ANY
2658 && actual->tt_type != VAR_UNKNOWN
2659 && !(actual->tt_type == VAR_FUNC
2660 && (actual->tt_member == &t_any || actual->tt_argcount < 0)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002661 {
2662 type_mismatch(expected, actual);
2663 return FAIL;
2664 }
2665 generate_TYPECHECK(cctx, expected, offset);
2666 return OK;
2667}
2668
2669/*
2670 * parse a list: [expr, expr]
2671 * "*arg" points to the '['.
2672 */
2673 static int
2674compile_list(char_u **arg, cctx_T *cctx)
2675{
2676 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002677 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002678 int count = 0;
2679
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002680 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002681 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002682 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002683 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002684 p = next_line_from_context(cctx);
2685 if (p == NULL)
2686 {
2687 semsg(_(e_list_end), *arg);
2688 return FAIL;
2689 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002690 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002691 p = skipwhite(p);
2692 }
2693 if (*p == ']')
2694 {
2695 ++p;
2696 // Allow for following comment, after at least one space.
2697 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2698 p += STRLEN(p);
2699 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002700 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002701 if (compile_expr1(&p, cctx) == FAIL)
2702 break;
2703 ++count;
2704 if (*p == ',')
2705 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002706 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002707 p = skipwhite(p);
2708 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002709 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002710
2711 generate_NEWLIST(cctx, count);
2712 return OK;
2713}
2714
2715/*
2716 * parse a lambda: {arg, arg -> expr}
2717 * "*arg" points to the '{'.
2718 */
2719 static int
2720compile_lambda(char_u **arg, cctx_T *cctx)
2721{
2722 garray_T *instr = &cctx->ctx_instr;
2723 typval_T rettv;
2724 ufunc_T *ufunc;
2725
2726 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002727 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002728 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002729
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002730 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002731 ++ufunc->uf_refcount;
2732 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002733 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002734
2735 // The function will have one line: "return {expr}".
2736 // Compile it into instructions.
2737 compile_def_function(ufunc, TRUE);
2738
2739 if (ufunc->uf_dfunc_idx >= 0)
2740 {
2741 if (ga_grow(instr, 1) == FAIL)
2742 return FAIL;
2743 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2744 return OK;
2745 }
2746 return FAIL;
2747}
2748
2749/*
2750 * Compile a lamda call: expr->{lambda}(args)
2751 * "arg" points to the "{".
2752 */
2753 static int
2754compile_lambda_call(char_u **arg, cctx_T *cctx)
2755{
2756 ufunc_T *ufunc;
2757 typval_T rettv;
2758 int argcount = 1;
2759 int ret = FAIL;
2760
2761 // Get the funcref in "rettv".
2762 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2763 return FAIL;
2764
2765 if (**arg != '(')
2766 {
2767 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002768 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002769 else
2770 semsg(_(e_missing_paren), "lambda");
2771 clear_tv(&rettv);
2772 return FAIL;
2773 }
2774
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002775 ufunc = rettv.vval.v_partial->pt_func;
2776 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002777 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002778 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002779
2780 // The function will have one line: "return {expr}".
2781 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002782 compile_def_function(ufunc, TRUE);
2783
2784 // compile the arguments
2785 *arg = skipwhite(*arg + 1);
2786 if (compile_arguments(arg, cctx, &argcount) == OK)
2787 // call the compiled function
2788 ret = generate_CALL(cctx, ufunc, argcount);
2789
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002790 return ret;
2791}
2792
2793/*
2794 * parse a dict: {'key': val} or #{key: val}
2795 * "*arg" points to the '{'.
2796 */
2797 static int
2798compile_dict(char_u **arg, cctx_T *cctx, int literal)
2799{
2800 garray_T *instr = &cctx->ctx_instr;
2801 int count = 0;
2802 dict_T *d = dict_alloc();
2803 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002804 char_u *whitep = *arg;
2805 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002806
2807 if (d == NULL)
2808 return FAIL;
2809 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002810 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002811 {
2812 char_u *key = NULL;
2813
Bram Moolenaar2c330432020-04-13 14:41:35 +02002814 while (**arg == NUL || (literal && **arg == '"')
2815 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002816 {
2817 *arg = next_line_from_context(cctx);
2818 if (*arg == NULL)
2819 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002820 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002821 *arg = skipwhite(*arg);
2822 }
2823
2824 if (**arg == '}')
2825 break;
2826
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002827 if (literal)
2828 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002829 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002830
Bram Moolenaar2c330432020-04-13 14:41:35 +02002831 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002832 {
2833 semsg(_("E1014: Invalid key: %s"), *arg);
2834 return FAIL;
2835 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002836 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002837 if (generate_PUSHS(cctx, key) == FAIL)
2838 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002839 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002840 }
2841 else
2842 {
2843 isn_T *isn;
2844
2845 if (compile_expr1(arg, cctx) == FAIL)
2846 return FAIL;
2847 // TODO: check type is string
2848 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2849 if (isn->isn_type == ISN_PUSHS)
2850 key = isn->isn_arg.string;
2851 }
2852
2853 // Check for duplicate keys, if using string keys.
2854 if (key != NULL)
2855 {
2856 item = dict_find(d, key, -1);
2857 if (item != NULL)
2858 {
2859 semsg(_(e_duplicate_key), key);
2860 goto failret;
2861 }
2862 item = dictitem_alloc(key);
2863 if (item != NULL)
2864 {
2865 item->di_tv.v_type = VAR_UNKNOWN;
2866 item->di_tv.v_lock = 0;
2867 if (dict_add(d, item) == FAIL)
2868 dictitem_free(item);
2869 }
2870 }
2871
2872 *arg = skipwhite(*arg);
2873 if (**arg != ':')
2874 {
2875 semsg(_(e_missing_dict_colon), *arg);
2876 return FAIL;
2877 }
2878
Bram Moolenaar2c330432020-04-13 14:41:35 +02002879 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002880 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002881 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002882 {
2883 *arg = next_line_from_context(cctx);
2884 if (*arg == NULL)
2885 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002886 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002887 *arg = skipwhite(*arg);
2888 }
2889
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002890 if (compile_expr1(arg, cctx) == FAIL)
2891 return FAIL;
2892 ++count;
2893
Bram Moolenaar2c330432020-04-13 14:41:35 +02002894 whitep = *arg;
2895 p = skipwhite(*arg);
2896 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002897 {
2898 *arg = next_line_from_context(cctx);
2899 if (*arg == NULL)
2900 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002901 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002902 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002903 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002904 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002905 if (**arg == '}')
2906 break;
2907 if (**arg != ',')
2908 {
2909 semsg(_(e_missing_dict_comma), *arg);
2910 goto failret;
2911 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002912 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002913 *arg = skipwhite(*arg + 1);
2914 }
2915
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002916 *arg = *arg + 1;
2917
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002918 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002919 p = skipwhite(*arg);
2920 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002921 *arg += STRLEN(*arg);
2922
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002923 dict_unref(d);
2924 return generate_NEWDICT(cctx, count);
2925
2926failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002927 if (*arg == NULL)
2928 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002929 dict_unref(d);
2930 return FAIL;
2931}
2932
2933/*
2934 * Compile "&option".
2935 */
2936 static int
2937compile_get_option(char_u **arg, cctx_T *cctx)
2938{
2939 typval_T rettv;
2940 char_u *start = *arg;
2941 int ret;
2942
2943 // parse the option and get the current value to get the type.
2944 rettv.v_type = VAR_UNKNOWN;
2945 ret = get_option_tv(arg, &rettv, TRUE);
2946 if (ret == OK)
2947 {
2948 // include the '&' in the name, get_option_tv() expects it.
2949 char_u *name = vim_strnsave(start, *arg - start);
2950 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2951
2952 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2953 vim_free(name);
2954 }
2955 clear_tv(&rettv);
2956
2957 return ret;
2958}
2959
2960/*
2961 * Compile "$VAR".
2962 */
2963 static int
2964compile_get_env(char_u **arg, cctx_T *cctx)
2965{
2966 char_u *start = *arg;
2967 int len;
2968 int ret;
2969 char_u *name;
2970
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002971 ++*arg;
2972 len = get_env_len(arg);
2973 if (len == 0)
2974 {
2975 semsg(_(e_syntax_at), start - 1);
2976 return FAIL;
2977 }
2978
2979 // include the '$' in the name, get_env_tv() expects it.
2980 name = vim_strnsave(start, len + 1);
2981 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2982 vim_free(name);
2983 return ret;
2984}
2985
2986/*
2987 * Compile "@r".
2988 */
2989 static int
2990compile_get_register(char_u **arg, cctx_T *cctx)
2991{
2992 int ret;
2993
2994 ++*arg;
2995 if (**arg == NUL)
2996 {
2997 semsg(_(e_syntax_at), *arg - 1);
2998 return FAIL;
2999 }
3000 if (!valid_yank_reg(**arg, TRUE))
3001 {
3002 emsg_invreg(**arg);
3003 return FAIL;
3004 }
3005 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
3006 ++*arg;
3007 return ret;
3008}
3009
3010/*
3011 * Apply leading '!', '-' and '+' to constant "rettv".
3012 */
3013 static int
3014apply_leader(typval_T *rettv, char_u *start, char_u *end)
3015{
3016 char_u *p = end;
3017
3018 // this works from end to start
3019 while (p > start)
3020 {
3021 --p;
3022 if (*p == '-' || *p == '+')
3023 {
3024 // only '-' has an effect, for '+' we only check the type
3025#ifdef FEAT_FLOAT
3026 if (rettv->v_type == VAR_FLOAT)
3027 {
3028 if (*p == '-')
3029 rettv->vval.v_float = -rettv->vval.v_float;
3030 }
3031 else
3032#endif
3033 {
3034 varnumber_T val;
3035 int error = FALSE;
3036
3037 // tv_get_number_chk() accepts a string, but we don't want that
3038 // here
3039 if (check_not_string(rettv) == FAIL)
3040 return FAIL;
3041 val = tv_get_number_chk(rettv, &error);
3042 clear_tv(rettv);
3043 if (error)
3044 return FAIL;
3045 if (*p == '-')
3046 val = -val;
3047 rettv->v_type = VAR_NUMBER;
3048 rettv->vval.v_number = val;
3049 }
3050 }
3051 else
3052 {
3053 int v = tv2bool(rettv);
3054
3055 // '!' is permissive in the type.
3056 clear_tv(rettv);
3057 rettv->v_type = VAR_BOOL;
3058 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3059 }
3060 }
3061 return OK;
3062}
3063
3064/*
3065 * Recognize v: variables that are constants and set "rettv".
3066 */
3067 static void
3068get_vim_constant(char_u **arg, typval_T *rettv)
3069{
3070 if (STRNCMP(*arg, "v:true", 6) == 0)
3071 {
3072 rettv->v_type = VAR_BOOL;
3073 rettv->vval.v_number = VVAL_TRUE;
3074 *arg += 6;
3075 }
3076 else if (STRNCMP(*arg, "v:false", 7) == 0)
3077 {
3078 rettv->v_type = VAR_BOOL;
3079 rettv->vval.v_number = VVAL_FALSE;
3080 *arg += 7;
3081 }
3082 else if (STRNCMP(*arg, "v:null", 6) == 0)
3083 {
3084 rettv->v_type = VAR_SPECIAL;
3085 rettv->vval.v_number = VVAL_NULL;
3086 *arg += 6;
3087 }
3088 else if (STRNCMP(*arg, "v:none", 6) == 0)
3089 {
3090 rettv->v_type = VAR_SPECIAL;
3091 rettv->vval.v_number = VVAL_NONE;
3092 *arg += 6;
3093 }
3094}
3095
3096/*
3097 * Compile code to apply '-', '+' and '!'.
3098 */
3099 static int
3100compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3101{
3102 char_u *p = end;
3103
3104 // this works from end to start
3105 while (p > start)
3106 {
3107 --p;
3108 if (*p == '-' || *p == '+')
3109 {
3110 int negate = *p == '-';
3111 isn_T *isn;
3112
3113 // TODO: check type
3114 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3115 {
3116 --p;
3117 if (*p == '-')
3118 negate = !negate;
3119 }
3120 // only '-' has an effect, for '+' we only check the type
3121 if (negate)
3122 isn = generate_instr(cctx, ISN_NEGATENR);
3123 else
3124 isn = generate_instr(cctx, ISN_CHECKNR);
3125 if (isn == NULL)
3126 return FAIL;
3127 }
3128 else
3129 {
3130 int invert = TRUE;
3131
3132 while (p > start && p[-1] == '!')
3133 {
3134 --p;
3135 invert = !invert;
3136 }
3137 if (generate_2BOOL(cctx, invert) == FAIL)
3138 return FAIL;
3139 }
3140 }
3141 return OK;
3142}
3143
3144/*
3145 * Compile whatever comes after "name" or "name()".
3146 */
3147 static int
3148compile_subscript(
3149 char_u **arg,
3150 cctx_T *cctx,
3151 char_u **start_leader,
3152 char_u *end_leader)
3153{
3154 for (;;)
3155 {
3156 if (**arg == '(')
3157 {
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003158 garray_T *stack = &cctx->ctx_type_stack;
3159 type_T *type;
3160 int argcount = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003161
3162 // funcref(arg)
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003163 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3164
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003165 *arg = skipwhite(*arg + 1);
3166 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3167 return FAIL;
Bram Moolenaara0a9f432020-04-28 21:29:34 +02003168 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003169 return FAIL;
3170 }
3171 else if (**arg == '-' && (*arg)[1] == '>')
3172 {
3173 char_u *p;
3174
3175 // something->method()
3176 // Apply the '!', '-' and '+' first:
3177 // -1.0->func() works like (-1.0)->func()
3178 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3179 return FAIL;
3180 *start_leader = end_leader; // don't apply again later
3181
3182 *arg = skipwhite(*arg + 2);
3183 if (**arg == '{')
3184 {
3185 // lambda call: list->{lambda}
3186 if (compile_lambda_call(arg, cctx) == FAIL)
3187 return FAIL;
3188 }
3189 else
3190 {
3191 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003192 p = *arg;
3193 if (ASCII_ISALPHA(*p) && p[1] == ':')
3194 p += 2;
3195 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003196 ;
3197 if (*p != '(')
3198 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003199 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003200 return FAIL;
3201 }
3202 // TODO: base value may not be the first argument
3203 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3204 return FAIL;
3205 }
3206 }
3207 else if (**arg == '[')
3208 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003209 garray_T *stack;
3210 type_T **typep;
3211
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003212 // list index: list[123]
3213 // TODO: more arguments
3214 // TODO: dict member dict['name']
3215 *arg = skipwhite(*arg + 1);
3216 if (compile_expr1(arg, cctx) == FAIL)
3217 return FAIL;
3218
3219 if (**arg != ']')
3220 {
3221 emsg(_(e_missbrac));
3222 return FAIL;
3223 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003224 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003225
3226 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3227 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003228 stack = &cctx->ctx_type_stack;
3229 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3230 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3231 {
3232 emsg(_(e_listreq));
3233 return FAIL;
3234 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003235 if ((*typep)->tt_type == VAR_LIST)
3236 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003237 }
3238 else if (**arg == '.' && (*arg)[1] != '.')
3239 {
3240 char_u *p;
3241
3242 ++*arg;
3243 p = *arg;
3244 // dictionary member: dict.name
3245 if (eval_isnamec1(*p))
3246 while (eval_isnamec(*p))
3247 MB_PTR_ADV(p);
3248 if (p == *arg)
3249 {
3250 semsg(_(e_syntax_at), *arg);
3251 return FAIL;
3252 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003253 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3254 return FAIL;
3255 *arg = p;
3256 }
3257 else
3258 break;
3259 }
3260
3261 // TODO - see handle_subscript():
3262 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3263 // Don't do this when "Func" is already a partial that was bound
3264 // explicitly (pt_auto is FALSE).
3265
3266 return OK;
3267}
3268
3269/*
3270 * Compile an expression at "*p" and add instructions to "instr".
3271 * "p" is advanced until after the expression, skipping white space.
3272 *
3273 * This is the equivalent of eval1(), eval2(), etc.
3274 */
3275
3276/*
3277 * number number constant
3278 * 0zFFFFFFFF Blob constant
3279 * "string" string constant
3280 * 'string' literal string constant
3281 * &option-name option value
3282 * @r register contents
3283 * identifier variable value
3284 * function() function call
3285 * $VAR environment variable
3286 * (expression) nested expression
3287 * [expr, expr] List
3288 * {key: val, key: val} Dictionary
3289 * #{key: val, key: val} Dictionary with literal keys
3290 *
3291 * Also handle:
3292 * ! in front logical NOT
3293 * - in front unary minus
3294 * + in front unary plus (ignored)
3295 * trailing (arg) funcref/partial call
3296 * trailing [] subscript in String or List
3297 * trailing .name entry in Dictionary
3298 * trailing ->name() method call
3299 */
3300 static int
3301compile_expr7(char_u **arg, cctx_T *cctx)
3302{
3303 typval_T rettv;
3304 char_u *start_leader, *end_leader;
3305 int ret = OK;
3306
3307 /*
3308 * Skip '!', '-' and '+' characters. They are handled later.
3309 */
3310 start_leader = *arg;
3311 while (**arg == '!' || **arg == '-' || **arg == '+')
3312 *arg = skipwhite(*arg + 1);
3313 end_leader = *arg;
3314
3315 rettv.v_type = VAR_UNKNOWN;
3316 switch (**arg)
3317 {
3318 /*
3319 * Number constant.
3320 */
3321 case '0': // also for blob starting with 0z
3322 case '1':
3323 case '2':
3324 case '3':
3325 case '4':
3326 case '5':
3327 case '6':
3328 case '7':
3329 case '8':
3330 case '9':
3331 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3332 return FAIL;
3333 break;
3334
3335 /*
3336 * String constant: "string".
3337 */
3338 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3339 return FAIL;
3340 break;
3341
3342 /*
3343 * Literal string constant: 'str''ing'.
3344 */
3345 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3346 return FAIL;
3347 break;
3348
3349 /*
3350 * Constant Vim variable.
3351 */
3352 case 'v': get_vim_constant(arg, &rettv);
3353 ret = NOTDONE;
3354 break;
3355
3356 /*
3357 * List: [expr, expr]
3358 */
3359 case '[': ret = compile_list(arg, cctx);
3360 break;
3361
3362 /*
3363 * Dictionary: #{key: val, key: val}
3364 */
3365 case '#': if ((*arg)[1] == '{')
3366 {
3367 ++*arg;
3368 ret = compile_dict(arg, cctx, TRUE);
3369 }
3370 else
3371 ret = NOTDONE;
3372 break;
3373
3374 /*
3375 * Lambda: {arg, arg -> expr}
3376 * Dictionary: {'key': val, 'key': val}
3377 */
3378 case '{': {
3379 char_u *start = skipwhite(*arg + 1);
3380
3381 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003382 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003383 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003384 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003385 if (ret != FAIL && *start == '>')
3386 ret = compile_lambda(arg, cctx);
3387 else
3388 ret = compile_dict(arg, cctx, FALSE);
3389 }
3390 break;
3391
3392 /*
3393 * Option value: &name
3394 */
3395 case '&': ret = compile_get_option(arg, cctx);
3396 break;
3397
3398 /*
3399 * Environment variable: $VAR.
3400 */
3401 case '$': ret = compile_get_env(arg, cctx);
3402 break;
3403
3404 /*
3405 * Register contents: @r.
3406 */
3407 case '@': ret = compile_get_register(arg, cctx);
3408 break;
3409 /*
3410 * nested expression: (expression).
3411 */
3412 case '(': *arg = skipwhite(*arg + 1);
3413 ret = compile_expr1(arg, cctx); // recursive!
3414 *arg = skipwhite(*arg);
3415 if (**arg == ')')
3416 ++*arg;
3417 else if (ret == OK)
3418 {
3419 emsg(_(e_missing_close));
3420 ret = FAIL;
3421 }
3422 break;
3423
3424 default: ret = NOTDONE;
3425 break;
3426 }
3427 if (ret == FAIL)
3428 return FAIL;
3429
3430 if (rettv.v_type != VAR_UNKNOWN)
3431 {
3432 // apply the '!', '-' and '+' before the constant
3433 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3434 {
3435 clear_tv(&rettv);
3436 return FAIL;
3437 }
3438 start_leader = end_leader; // don't apply again below
3439
3440 // push constant
3441 switch (rettv.v_type)
3442 {
3443 case VAR_BOOL:
3444 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3445 break;
3446 case VAR_SPECIAL:
3447 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3448 break;
3449 case VAR_NUMBER:
3450 generate_PUSHNR(cctx, rettv.vval.v_number);
3451 break;
3452#ifdef FEAT_FLOAT
3453 case VAR_FLOAT:
3454 generate_PUSHF(cctx, rettv.vval.v_float);
3455 break;
3456#endif
3457 case VAR_BLOB:
3458 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3459 rettv.vval.v_blob = NULL;
3460 break;
3461 case VAR_STRING:
3462 generate_PUSHS(cctx, rettv.vval.v_string);
3463 rettv.vval.v_string = NULL;
3464 break;
3465 default:
3466 iemsg("constant type missing");
3467 return FAIL;
3468 }
3469 }
3470 else if (ret == NOTDONE)
3471 {
3472 char_u *p;
3473 int r;
3474
3475 if (!eval_isnamec1(**arg))
3476 {
3477 semsg(_("E1015: Name expected: %s"), *arg);
3478 return FAIL;
3479 }
3480
3481 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003482 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003483 if (*p == '(')
3484 r = compile_call(arg, p - *arg, cctx, 0);
3485 else
3486 r = compile_load(arg, p, cctx, TRUE);
3487 if (r == FAIL)
3488 return FAIL;
3489 }
3490
3491 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3492 return FAIL;
3493
3494 // Now deal with prefixed '-', '+' and '!', if not done already.
3495 return compile_leader(cctx, start_leader, end_leader);
3496}
3497
3498/*
3499 * * number multiplication
3500 * / number division
3501 * % number modulo
3502 */
3503 static int
3504compile_expr6(char_u **arg, cctx_T *cctx)
3505{
3506 char_u *op;
3507
3508 // get the first variable
3509 if (compile_expr7(arg, cctx) == FAIL)
3510 return FAIL;
3511
3512 /*
3513 * Repeat computing, until no "*", "/" or "%" is following.
3514 */
3515 for (;;)
3516 {
3517 op = skipwhite(*arg);
3518 if (*op != '*' && *op != '/' && *op != '%')
3519 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003520 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003521 {
3522 char_u buf[3];
3523
3524 vim_strncpy(buf, op, 1);
3525 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003526 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003527 }
3528 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003529 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003530 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003531
3532 // get the second variable
3533 if (compile_expr7(arg, cctx) == FAIL)
3534 return FAIL;
3535
3536 generate_two_op(cctx, op);
3537 }
3538
3539 return OK;
3540}
3541
3542/*
3543 * + number addition
3544 * - number subtraction
3545 * .. string concatenation
3546 */
3547 static int
3548compile_expr5(char_u **arg, cctx_T *cctx)
3549{
3550 char_u *op;
3551 int oplen;
3552
3553 // get the first variable
3554 if (compile_expr6(arg, cctx) == FAIL)
3555 return FAIL;
3556
3557 /*
3558 * Repeat computing, until no "+", "-" or ".." is following.
3559 */
3560 for (;;)
3561 {
3562 op = skipwhite(*arg);
3563 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3564 break;
3565 oplen = (*op == '.' ? 2 : 1);
3566
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003567 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003568 {
3569 char_u buf[3];
3570
3571 vim_strncpy(buf, op, oplen);
3572 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003573 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003574 }
3575
3576 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003577 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003578 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003579
3580 // get the second variable
3581 if (compile_expr6(arg, cctx) == FAIL)
3582 return FAIL;
3583
3584 if (*op == '.')
3585 {
3586 if (may_generate_2STRING(-2, cctx) == FAIL
3587 || may_generate_2STRING(-1, cctx) == FAIL)
3588 return FAIL;
3589 generate_instr_drop(cctx, ISN_CONCAT, 1);
3590 }
3591 else
3592 generate_two_op(cctx, op);
3593 }
3594
3595 return OK;
3596}
3597
Bram Moolenaar080457c2020-03-03 21:53:32 +01003598 static exptype_T
3599get_compare_type(char_u *p, int *len, int *type_is)
3600{
3601 exptype_T type = EXPR_UNKNOWN;
3602 int i;
3603
3604 switch (p[0])
3605 {
3606 case '=': if (p[1] == '=')
3607 type = EXPR_EQUAL;
3608 else if (p[1] == '~')
3609 type = EXPR_MATCH;
3610 break;
3611 case '!': if (p[1] == '=')
3612 type = EXPR_NEQUAL;
3613 else if (p[1] == '~')
3614 type = EXPR_NOMATCH;
3615 break;
3616 case '>': if (p[1] != '=')
3617 {
3618 type = EXPR_GREATER;
3619 *len = 1;
3620 }
3621 else
3622 type = EXPR_GEQUAL;
3623 break;
3624 case '<': if (p[1] != '=')
3625 {
3626 type = EXPR_SMALLER;
3627 *len = 1;
3628 }
3629 else
3630 type = EXPR_SEQUAL;
3631 break;
3632 case 'i': if (p[1] == 's')
3633 {
3634 // "is" and "isnot"; but not a prefix of a name
3635 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3636 *len = 5;
3637 i = p[*len];
3638 if (!isalnum(i) && i != '_')
3639 {
3640 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3641 *type_is = TRUE;
3642 }
3643 }
3644 break;
3645 }
3646 return type;
3647}
3648
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003649/*
3650 * expr5a == expr5b
3651 * expr5a =~ expr5b
3652 * expr5a != expr5b
3653 * expr5a !~ expr5b
3654 * expr5a > expr5b
3655 * expr5a >= expr5b
3656 * expr5a < expr5b
3657 * expr5a <= expr5b
3658 * expr5a is expr5b
3659 * expr5a isnot expr5b
3660 *
3661 * Produces instructions:
3662 * EVAL expr5a Push result of "expr5a"
3663 * EVAL expr5b Push result of "expr5b"
3664 * COMPARE one of the compare instructions
3665 */
3666 static int
3667compile_expr4(char_u **arg, cctx_T *cctx)
3668{
3669 exptype_T type = EXPR_UNKNOWN;
3670 char_u *p;
3671 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003672 int type_is = FALSE;
3673
3674 // get the first variable
3675 if (compile_expr5(arg, cctx) == FAIL)
3676 return FAIL;
3677
3678 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003679 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003680
3681 /*
3682 * If there is a comparative operator, use it.
3683 */
3684 if (type != EXPR_UNKNOWN)
3685 {
3686 int ic = FALSE; // Default: do not ignore case
3687
3688 if (type_is && (p[len] == '?' || p[len] == '#'))
3689 {
3690 semsg(_(e_invexpr2), *arg);
3691 return FAIL;
3692 }
3693 // extra question mark appended: ignore case
3694 if (p[len] == '?')
3695 {
3696 ic = TRUE;
3697 ++len;
3698 }
3699 // extra '#' appended: match case (ignored)
3700 else if (p[len] == '#')
3701 ++len;
3702 // nothing appended: match case
3703
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003704 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003705 {
3706 char_u buf[7];
3707
3708 vim_strncpy(buf, p, len);
3709 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003710 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003711 }
3712
3713 // get the second variable
3714 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003715 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003716 return FAIL;
3717
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003718 if (compile_expr5(arg, cctx) == FAIL)
3719 return FAIL;
3720
3721 generate_COMPARE(cctx, type, ic);
3722 }
3723
3724 return OK;
3725}
3726
3727/*
3728 * Compile || or &&.
3729 */
3730 static int
3731compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3732{
3733 char_u *p = skipwhite(*arg);
3734 int opchar = *op;
3735
3736 if (p[0] == opchar && p[1] == opchar)
3737 {
3738 garray_T *instr = &cctx->ctx_instr;
3739 garray_T end_ga;
3740
3741 /*
3742 * Repeat until there is no following "||" or "&&"
3743 */
3744 ga_init2(&end_ga, sizeof(int), 10);
3745 while (p[0] == opchar && p[1] == opchar)
3746 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003747 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3748 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003749 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003750 return FAIL;
3751 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003752
3753 if (ga_grow(&end_ga, 1) == FAIL)
3754 {
3755 ga_clear(&end_ga);
3756 return FAIL;
3757 }
3758 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3759 ++end_ga.ga_len;
3760 generate_JUMP(cctx, opchar == '|'
3761 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3762
3763 // eval the next expression
3764 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003765 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003766 return FAIL;
3767
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003768 if ((opchar == '|' ? compile_expr3(arg, cctx)
3769 : compile_expr4(arg, cctx)) == FAIL)
3770 {
3771 ga_clear(&end_ga);
3772 return FAIL;
3773 }
3774 p = skipwhite(*arg);
3775 }
3776
3777 // Fill in the end label in all jumps.
3778 while (end_ga.ga_len > 0)
3779 {
3780 isn_T *isn;
3781
3782 --end_ga.ga_len;
3783 isn = ((isn_T *)instr->ga_data)
3784 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3785 isn->isn_arg.jump.jump_where = instr->ga_len;
3786 }
3787 ga_clear(&end_ga);
3788 }
3789
3790 return OK;
3791}
3792
3793/*
3794 * expr4a && expr4a && expr4a logical AND
3795 *
3796 * Produces instructions:
3797 * EVAL expr4a Push result of "expr4a"
3798 * JUMP_AND_KEEP_IF_FALSE end
3799 * EVAL expr4b Push result of "expr4b"
3800 * JUMP_AND_KEEP_IF_FALSE end
3801 * EVAL expr4c Push result of "expr4c"
3802 * end:
3803 */
3804 static int
3805compile_expr3(char_u **arg, cctx_T *cctx)
3806{
3807 // get the first variable
3808 if (compile_expr4(arg, cctx) == FAIL)
3809 return FAIL;
3810
3811 // || and && work almost the same
3812 return compile_and_or(arg, cctx, "&&");
3813}
3814
3815/*
3816 * expr3a || expr3b || expr3c logical OR
3817 *
3818 * Produces instructions:
3819 * EVAL expr3a Push result of "expr3a"
3820 * JUMP_AND_KEEP_IF_TRUE end
3821 * EVAL expr3b Push result of "expr3b"
3822 * JUMP_AND_KEEP_IF_TRUE end
3823 * EVAL expr3c Push result of "expr3c"
3824 * end:
3825 */
3826 static int
3827compile_expr2(char_u **arg, cctx_T *cctx)
3828{
3829 // eval the first expression
3830 if (compile_expr3(arg, cctx) == FAIL)
3831 return FAIL;
3832
3833 // || and && work almost the same
3834 return compile_and_or(arg, cctx, "||");
3835}
3836
3837/*
3838 * Toplevel expression: expr2 ? expr1a : expr1b
3839 *
3840 * Produces instructions:
3841 * EVAL expr2 Push result of "expr"
3842 * JUMP_IF_FALSE alt jump if false
3843 * EVAL expr1a
3844 * JUMP_ALWAYS end
3845 * alt: EVAL expr1b
3846 * end:
3847 */
3848 static int
3849compile_expr1(char_u **arg, cctx_T *cctx)
3850{
3851 char_u *p;
3852
3853 // evaluate the first expression
3854 if (compile_expr2(arg, cctx) == FAIL)
3855 return FAIL;
3856
3857 p = skipwhite(*arg);
3858 if (*p == '?')
3859 {
3860 garray_T *instr = &cctx->ctx_instr;
3861 garray_T *stack = &cctx->ctx_type_stack;
3862 int alt_idx = instr->ga_len;
3863 int end_idx;
3864 isn_T *isn;
3865 type_T *type1;
3866 type_T *type2;
3867
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003868 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3869 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003870 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003871 return FAIL;
3872 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003873
3874 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3875
3876 // evaluate the second expression; any type is accepted
3877 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003878 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003879 return FAIL;
3880
Bram Moolenaara6d53682020-01-28 23:04:06 +01003881 if (compile_expr1(arg, cctx) == FAIL)
3882 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003883
3884 // remember the type and drop it
3885 --stack->ga_len;
3886 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3887
3888 end_idx = instr->ga_len;
3889 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3890
3891 // jump here from JUMP_IF_FALSE
3892 isn = ((isn_T *)instr->ga_data) + alt_idx;
3893 isn->isn_arg.jump.jump_where = instr->ga_len;
3894
3895 // Check for the ":".
3896 p = skipwhite(*arg);
3897 if (*p != ':')
3898 {
3899 emsg(_(e_missing_colon));
3900 return FAIL;
3901 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003902 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3903 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003904 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003905 return FAIL;
3906 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003907
3908 // evaluate the third expression
3909 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003910 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003911 return FAIL;
3912
Bram Moolenaara6d53682020-01-28 23:04:06 +01003913 if (compile_expr1(arg, cctx) == FAIL)
3914 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003915
3916 // If the types differ, the result has a more generic type.
3917 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003918 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003919
3920 // jump here from JUMP_ALWAYS
3921 isn = ((isn_T *)instr->ga_data) + end_idx;
3922 isn->isn_arg.jump.jump_where = instr->ga_len;
3923 }
3924 return OK;
3925}
3926
3927/*
3928 * compile "return [expr]"
3929 */
3930 static char_u *
3931compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3932{
3933 char_u *p = arg;
3934 garray_T *stack = &cctx->ctx_type_stack;
3935 type_T *stack_type;
3936
3937 if (*p != NUL && *p != '|' && *p != '\n')
3938 {
3939 // compile return argument into instructions
3940 if (compile_expr1(&p, cctx) == FAIL)
3941 return NULL;
3942
3943 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3944 if (set_return_type)
3945 cctx->ctx_ufunc->uf_ret_type = stack_type;
3946 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3947 == FAIL)
3948 return NULL;
3949 }
3950 else
3951 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003952 // "set_return_type" cannot be TRUE, only used for a lambda which
3953 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003954 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3955 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003956 {
3957 emsg(_("E1003: Missing return value"));
3958 return NULL;
3959 }
3960
3961 // No argument, return zero.
3962 generate_PUSHNR(cctx, 0);
3963 }
3964
3965 if (generate_instr(cctx, ISN_RETURN) == NULL)
3966 return NULL;
3967
3968 // "return val | endif" is possible
3969 return skipwhite(p);
3970}
3971
3972/*
3973 * Return the length of an assignment operator, or zero if there isn't one.
3974 */
3975 int
3976assignment_len(char_u *p, int *heredoc)
3977{
3978 if (*p == '=')
3979 {
3980 if (p[1] == '<' && p[2] == '<')
3981 {
3982 *heredoc = TRUE;
3983 return 3;
3984 }
3985 return 1;
3986 }
3987 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3988 return 2;
3989 if (STRNCMP(p, "..=", 3) == 0)
3990 return 3;
3991 return 0;
3992}
3993
3994// words that cannot be used as a variable
3995static char *reserved[] = {
3996 "true",
3997 "false",
3998 NULL
3999};
4000
4001/*
4002 * Get a line for "=<<".
4003 * Return a pointer to the line in allocated memory.
4004 * Return NULL for end-of-file or some error.
4005 */
4006 static char_u *
4007heredoc_getline(
4008 int c UNUSED,
4009 void *cookie,
4010 int indent UNUSED,
4011 int do_concat UNUSED)
4012{
4013 cctx_T *cctx = (cctx_T *)cookie;
4014
4015 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004016 {
4017 iemsg("Heredoc got to end");
4018 return NULL;
4019 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004020 ++cctx->ctx_lnum;
4021 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
4022 [cctx->ctx_lnum]);
4023}
4024
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004025typedef enum {
4026 dest_local,
4027 dest_option,
4028 dest_env,
4029 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02004030 dest_buffer,
4031 dest_window,
4032 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004033 dest_vimvar,
4034 dest_script,
4035 dest_reg,
4036} assign_dest_T;
4037
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004038/*
4039 * compile "let var [= expr]", "const var = expr" and "var = expr"
4040 * "arg" points to "var".
4041 */
4042 static char_u *
4043compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4044{
4045 char_u *p;
4046 char_u *ret = NULL;
4047 int var_count = 0;
4048 int semicolon = 0;
4049 size_t varlen;
4050 garray_T *instr = &cctx->ctx_instr;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004051 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004052 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004053 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004054 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004055 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004056 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004057 int oplen = 0;
4058 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004059 type_T *type = &t_any;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004060 lvar_T *lvar = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004061 char_u *name;
4062 char_u *sp;
4063 int has_type = FALSE;
4064 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4065 int instr_count = -1;
4066
4067 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4068 if (p == NULL)
4069 return NULL;
4070 if (var_count > 0)
4071 {
4072 // TODO: let [var, var] = list
4073 emsg("Cannot handle a list yet");
4074 return NULL;
4075 }
4076
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004077 // "a: type" is declaring variable "a" with a type, not "a:".
4078 if (is_decl && p == arg + 2 && p[-1] == ':')
4079 --p;
4080
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004081 varlen = p - arg;
4082 name = vim_strnsave(arg, (int)varlen);
4083 if (name == NULL)
4084 return NULL;
4085
Bram Moolenaar080457c2020-03-03 21:53:32 +01004086 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004087 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004088 if (*arg == '&')
4089 {
4090 int cc;
4091 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004092
Bram Moolenaar080457c2020-03-03 21:53:32 +01004093 dest = dest_option;
4094 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004095 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004096 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004097 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004098 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004099 if (is_decl)
4100 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004101 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004102 goto theend;
4103 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004104 p = arg;
4105 p = find_option_end(&p, &opt_flags);
4106 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004107 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004108 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004109 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004110 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004111 }
4112 cc = *p;
4113 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004114 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004115 *p = cc;
4116 if (opt_type == -3)
4117 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004118 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004119 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004120 }
4121 if (opt_type == -2 || opt_type == 0)
4122 type = &t_string;
4123 else
4124 type = &t_number; // both number and boolean option
4125 }
4126 else if (*arg == '$')
4127 {
4128 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004129 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004130 if (is_decl)
4131 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004132 semsg(_("E1065: Cannot declare an environment variable: %s"),
4133 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004134 goto theend;
4135 }
4136 }
4137 else if (*arg == '@')
4138 {
4139 if (!valid_yank_reg(arg[1], TRUE))
4140 {
4141 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004142 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004143 }
4144 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004145 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004146 if (is_decl)
4147 {
4148 semsg(_("E1066: Cannot declare a register: %s"), name);
4149 goto theend;
4150 }
4151 }
4152 else if (STRNCMP(arg, "g:", 2) == 0)
4153 {
4154 dest = dest_global;
4155 if (is_decl)
4156 {
4157 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4158 goto theend;
4159 }
4160 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004161 else if (STRNCMP(arg, "b:", 2) == 0)
4162 {
4163 dest = dest_buffer;
4164 if (is_decl)
4165 {
4166 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4167 goto theend;
4168 }
4169 }
4170 else if (STRNCMP(arg, "w:", 2) == 0)
4171 {
4172 dest = dest_window;
4173 if (is_decl)
4174 {
4175 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4176 goto theend;
4177 }
4178 }
4179 else if (STRNCMP(arg, "t:", 2) == 0)
4180 {
4181 dest = dest_tab;
4182 if (is_decl)
4183 {
4184 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4185 goto theend;
4186 }
4187 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004188 else if (STRNCMP(arg, "v:", 2) == 0)
4189 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004190 typval_T *vtv;
4191 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004192
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004193 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004194 if (vimvaridx < 0)
4195 {
4196 semsg(_(e_var_notfound), arg);
4197 goto theend;
4198 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004199 // We use the current value of "sandbox" here, is that OK?
4200 if (var_check_ro(di_flags, name, FALSE))
4201 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004202 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004203 vtv = get_vim_var_tv(vimvaridx);
4204 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004205 if (is_decl)
4206 {
4207 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4208 goto theend;
4209 }
4210 }
4211 else
4212 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004213 int idx;
4214
Bram Moolenaar080457c2020-03-03 21:53:32 +01004215 for (idx = 0; reserved[idx] != NULL; ++idx)
4216 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004217 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004218 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004219 goto theend;
4220 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004221
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004222 lvar = lookup_local(arg, varlen, cctx);
4223 if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004224 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004225 if (is_decl)
4226 {
4227 semsg(_("E1017: Variable already declared: %s"), name);
4228 goto theend;
4229 }
4230 else
4231 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004232 if (lvar->lv_const)
4233 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004234 semsg(_("E1018: Cannot assign to a constant: %s"),
4235 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004236 goto theend;
4237 }
4238 }
4239 }
4240 else if (STRNCMP(arg, "s:", 2) == 0
4241 || lookup_script(arg, varlen) == OK
4242 || find_imported(arg, varlen, cctx) != NULL)
4243 {
4244 dest = dest_script;
4245 if (is_decl)
4246 {
4247 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004248 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004249 goto theend;
4250 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004251 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004252 else if (name[1] == ':' && name[2] != NUL)
4253 {
4254 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4255 goto theend;
4256 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004257 }
4258 }
4259
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004260 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004261 {
4262 if (is_decl && *p == ':')
4263 {
4264 // parse optional type: "let var: type = expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004265 if (!VIM_ISWHITE(p[1]))
4266 {
4267 semsg(_(e_white_after), ":");
4268 goto theend;
4269 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004270 p = skipwhite(p + 1);
4271 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004272 has_type = TRUE;
4273 }
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004274 else if (lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004275 type = lvar->lv_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004276 }
4277
4278 sp = p;
4279 p = skipwhite(p);
4280 op = p;
4281 oplen = assignment_len(p, &heredoc);
4282 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4283 {
4284 char_u buf[4];
4285
4286 vim_strncpy(buf, op, oplen);
4287 semsg(_(e_white_both), buf);
4288 }
4289
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004290 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004291 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004292 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004293 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004294 goto theend;
4295 }
4296
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004297 if (lvar == NULL && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004298 {
4299 if (oplen > 1 && !heredoc)
4300 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004301 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004302 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4303 name);
4304 goto theend;
4305 }
4306
4307 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004308 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004309 goto theend;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004310 lvar = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4311 if (lvar == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004312 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004313 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004314 }
4315
4316 if (heredoc)
4317 {
4318 list_T *l;
4319 listitem_T *li;
4320
4321 // [let] varname =<< [trim] {end}
4322 eap->getline = heredoc_getline;
4323 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004324 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004325
4326 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004327 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004328 {
4329 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4330 li->li_tv.vval.v_string = NULL;
4331 }
4332 generate_NEWLIST(cctx, l->lv_len);
4333 type = &t_list_string;
4334 list_free(l);
4335 p += STRLEN(p);
4336 }
4337 else if (oplen > 0)
4338 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004339 int r;
4340 type_T *stacktype;
4341 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004342
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004343 // for "+=", "*=", "..=" etc. first load the current value
4344 if (*op != '=')
4345 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004346 switch (dest)
4347 {
4348 case dest_option:
4349 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004350 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004351 break;
4352 case dest_global:
4353 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4354 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004355 case dest_buffer:
4356 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4357 break;
4358 case dest_window:
4359 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4360 break;
4361 case dest_tab:
4362 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4363 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004364 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004365 compile_load_scriptvar(cctx,
4366 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004367 break;
4368 case dest_env:
4369 // Include $ in the name here
4370 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4371 break;
4372 case dest_reg:
4373 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4374 break;
4375 case dest_vimvar:
4376 generate_LOADV(cctx, name + 2, TRUE);
4377 break;
4378 case dest_local:
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004379 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004380 break;
4381 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004382 }
4383
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004384 // Compile the expression. Temporarily hide the new local variable
4385 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004386 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004387 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004388 instr_count = instr->ga_len;
4389 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004390 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004391 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004392 ++cctx->ctx_locals.ga_len;
4393 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004394 goto theend;
4395
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004396 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004397 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004398 stack = &cctx->ctx_type_stack;
4399 stacktype = stack->ga_len == 0 ? &t_void
4400 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004401 if (lvar != NULL && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004402 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004403 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004404 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004405 if (stacktype->tt_type == VAR_VOID)
4406 {
4407 emsg(_("E1031: Cannot use void value"));
4408 goto theend;
4409 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004410 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004411 {
4412 // An empty list or dict has a &t_void member, for a
4413 // variable that implies &t_any.
4414 if (stacktype == &t_list_empty)
4415 lvar->lv_type = &t_list_any;
4416 else if (stacktype == &t_dict_empty)
4417 lvar->lv_type = &t_dict_any;
4418 else
4419 lvar->lv_type = stacktype;
4420 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004421 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004422 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4423 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004424 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004425 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004426 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004427 }
4428 }
4429 else if (cmdidx == CMD_const)
4430 {
4431 emsg(_("E1021: const requires a value"));
4432 goto theend;
4433 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004434 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004435 {
4436 emsg(_("E1022: type or initialization required"));
4437 goto theend;
4438 }
4439 else
4440 {
4441 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004442 if (ga_grow(instr, 1) == FAIL)
4443 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004444 switch (type->tt_type)
4445 {
4446 case VAR_BOOL:
4447 generate_PUSHBOOL(cctx, VVAL_FALSE);
4448 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004449 case VAR_FLOAT:
4450#ifdef FEAT_FLOAT
4451 generate_PUSHF(cctx, 0.0);
4452#endif
4453 break;
4454 case VAR_STRING:
4455 generate_PUSHS(cctx, NULL);
4456 break;
4457 case VAR_BLOB:
4458 generate_PUSHBLOB(cctx, NULL);
4459 break;
4460 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004461 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004462 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004463 case VAR_LIST:
4464 generate_NEWLIST(cctx, 0);
4465 break;
4466 case VAR_DICT:
4467 generate_NEWDICT(cctx, 0);
4468 break;
4469 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004470 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004471 break;
4472 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004473 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004474 break;
4475 case VAR_NUMBER:
4476 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004477 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004478 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004479 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004480 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004481 generate_PUSHNR(cctx, 0);
4482 break;
4483 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004484 }
4485
4486 if (oplen > 0 && *op != '=')
4487 {
4488 type_T *expected = &t_number;
4489 garray_T *stack = &cctx->ctx_type_stack;
4490 type_T *stacktype;
4491
4492 // TODO: if type is known use float or any operation
4493
4494 if (*op == '.')
4495 expected = &t_string;
4496 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4497 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4498 goto theend;
4499
4500 if (*op == '.')
4501 generate_instr_drop(cctx, ISN_CONCAT, 1);
4502 else
4503 {
4504 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4505
4506 if (isn == NULL)
4507 goto theend;
4508 switch (*op)
4509 {
4510 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4511 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4512 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4513 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4514 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4515 }
4516 }
4517 }
4518
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004519 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004520 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004521 case dest_option:
4522 generate_STOREOPT(cctx, name + 1, opt_flags);
4523 break;
4524 case dest_global:
4525 // include g: with the name, easier to execute that way
4526 generate_STORE(cctx, ISN_STOREG, 0, name);
4527 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004528 case dest_buffer:
4529 // include b: with the name, easier to execute that way
4530 generate_STORE(cctx, ISN_STOREB, 0, name);
4531 break;
4532 case dest_window:
4533 // include w: with the name, easier to execute that way
4534 generate_STORE(cctx, ISN_STOREW, 0, name);
4535 break;
4536 case dest_tab:
4537 // include t: with the name, easier to execute that way
4538 generate_STORE(cctx, ISN_STORET, 0, name);
4539 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004540 case dest_env:
4541 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4542 break;
4543 case dest_reg:
4544 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4545 break;
4546 case dest_vimvar:
4547 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4548 break;
4549 case dest_script:
4550 {
4551 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4552 imported_T *import = NULL;
4553 int sid = current_sctx.sc_sid;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004554 int idx;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004555
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004556 if (name[1] != ':')
4557 {
4558 import = find_imported(name, 0, cctx);
4559 if (import != NULL)
4560 sid = import->imp_sid;
4561 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004562
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004563 idx = get_script_item_idx(sid, rawname, TRUE);
4564 // TODO: specific type
4565 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004566 {
4567 char_u *name_s = name;
4568
4569 // Include s: in the name for store_var()
4570 if (name[1] != ':')
4571 {
4572 int len = (int)STRLEN(name) + 3;
4573
4574 name_s = alloc(len);
4575 if (name_s == NULL)
4576 name_s = name;
4577 else
4578 vim_snprintf((char *)name_s, len, "s:%s", name);
4579 }
4580 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4581 if (name_s != name)
4582 vim_free(name_s);
4583 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004584 else
4585 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4586 sid, idx, &t_any);
4587 }
4588 break;
4589 case dest_local:
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004590 if (lvar != NULL)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004591 {
4592 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004593
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004594 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4595 // into ISN_STORENR
4596 if (instr->ga_len == instr_count + 1
4597 && isn->isn_type == ISN_PUSHNR)
4598 {
4599 varnumber_T val = isn->isn_arg.number;
4600 garray_T *stack = &cctx->ctx_type_stack;
4601
4602 isn->isn_type = ISN_STORENR;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004603 isn->isn_arg.storenr.stnr_idx = lvar->lv_idx;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004604 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004605 if (stack->ga_len > 0)
4606 --stack->ga_len;
4607 }
4608 else
Bram Moolenaarb84a3812020-05-01 15:44:29 +02004609 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004610 }
4611 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004612 }
4613 ret = p;
4614
4615theend:
4616 vim_free(name);
4617 return ret;
4618}
4619
4620/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004621 * Check if "name" can be "unlet".
4622 */
4623 int
4624check_vim9_unlet(char_u *name)
4625{
4626 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
4627 {
4628 semsg(_("E1081: Cannot unlet %s"), name);
4629 return FAIL;
4630 }
4631 return OK;
4632}
4633
4634/*
4635 * Callback passed to ex_unletlock().
4636 */
4637 static int
4638compile_unlet(
4639 lval_T *lvp,
4640 char_u *name_end,
4641 exarg_T *eap,
4642 int deep UNUSED,
4643 void *coookie)
4644{
4645 cctx_T *cctx = coookie;
4646
4647 if (lvp->ll_tv == NULL)
4648 {
4649 char_u *p = lvp->ll_name;
4650 int cc = *name_end;
4651 int ret = OK;
4652
4653 // Normal name. Only supports g:, w:, t: and b: namespaces.
4654 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004655 if (*p == '$')
4656 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
4657 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004658 ret = FAIL;
4659 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004660 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004661
4662 *name_end = cc;
4663 return ret;
4664 }
4665
4666 // TODO: unlet {list}[idx]
4667 // TODO: unlet {dict}[key]
4668 emsg("Sorry, :unlet not fully implemented yet");
4669 return FAIL;
4670}
4671
4672/*
4673 * compile "unlet var", "lock var" and "unlock var"
4674 * "arg" points to "var".
4675 */
4676 static char_u *
4677compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
4678{
4679 char_u *p = arg;
4680
4681 if (eap->cmdidx != CMD_unlet)
4682 {
4683 emsg("Sorry, :lock and unlock not implemented yet");
4684 return NULL;
4685 }
4686
4687 if (*p == '!')
4688 {
4689 p = skipwhite(p + 1);
4690 eap->forceit = TRUE;
4691 }
4692
4693 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
4694 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
4695}
4696
4697/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004698 * Compile an :import command.
4699 */
4700 static char_u *
4701compile_import(char_u *arg, cctx_T *cctx)
4702{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004703 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004704}
4705
4706/*
4707 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4708 */
4709 static int
4710compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4711{
4712 garray_T *instr = &cctx->ctx_instr;
4713 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4714
4715 if (endlabel == NULL)
4716 return FAIL;
4717 endlabel->el_next = *el;
4718 *el = endlabel;
4719 endlabel->el_end_label = instr->ga_len;
4720
4721 generate_JUMP(cctx, when, 0);
4722 return OK;
4723}
4724
4725 static void
4726compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4727{
4728 garray_T *instr = &cctx->ctx_instr;
4729
4730 while (*el != NULL)
4731 {
4732 endlabel_T *cur = (*el);
4733 isn_T *isn;
4734
4735 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4736 isn->isn_arg.jump.jump_where = instr->ga_len;
4737 *el = cur->el_next;
4738 vim_free(cur);
4739 }
4740}
4741
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004742 static void
4743compile_free_jump_to_end(endlabel_T **el)
4744{
4745 while (*el != NULL)
4746 {
4747 endlabel_T *cur = (*el);
4748
4749 *el = cur->el_next;
4750 vim_free(cur);
4751 }
4752}
4753
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004754/*
4755 * Create a new scope and set up the generic items.
4756 */
4757 static scope_T *
4758new_scope(cctx_T *cctx, scopetype_T type)
4759{
4760 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4761
4762 if (scope == NULL)
4763 return NULL;
4764 scope->se_outer = cctx->ctx_scope;
4765 cctx->ctx_scope = scope;
4766 scope->se_type = type;
4767 scope->se_local_count = cctx->ctx_locals.ga_len;
4768 return scope;
4769}
4770
4771/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004772 * Free the current scope and go back to the outer scope.
4773 */
4774 static void
4775drop_scope(cctx_T *cctx)
4776{
4777 scope_T *scope = cctx->ctx_scope;
4778
4779 if (scope == NULL)
4780 {
4781 iemsg("calling drop_scope() without a scope");
4782 return;
4783 }
4784 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004785 switch (scope->se_type)
4786 {
4787 case IF_SCOPE:
4788 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4789 case FOR_SCOPE:
4790 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4791 case WHILE_SCOPE:
4792 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4793 case TRY_SCOPE:
4794 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4795 case NO_SCOPE:
4796 case BLOCK_SCOPE:
4797 break;
4798 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004799 vim_free(scope);
4800}
4801
4802/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004803 * Evaluate an expression that is a constant:
4804 * has(arg)
4805 *
4806 * Also handle:
4807 * ! in front logical NOT
4808 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004809 * Return FAIL if the expression is not a constant.
4810 */
4811 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004812evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004813{
4814 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004815 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004816 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004817
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004818 /*
4819 * Skip '!' characters. They are handled later.
4820 */
4821 start_leader = *arg;
4822 while (**arg == '!')
4823 *arg = skipwhite(*arg + 1);
4824 end_leader = *arg;
4825
4826 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004827 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004828 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004829 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4830 {
4831 tv->v_type = VAR_SPECIAL;
4832 tv->vval.v_number = VVAL_TRUE;
4833 *arg += 4;
4834 return OK;
4835 }
4836 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4837 {
4838 tv->v_type = VAR_SPECIAL;
4839 tv->vval.v_number = VVAL_FALSE;
4840 *arg += 5;
4841 return OK;
4842 }
4843
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004844 if (STRNCMP("has(", *arg, 4) == 0)
4845 {
4846 has_call = TRUE;
4847 *arg = skipwhite(*arg + 4);
4848 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004849
4850 if (**arg == '"')
4851 {
4852 if (get_string_tv(arg, tv, TRUE) == FAIL)
4853 return FAIL;
4854 }
4855 else if (**arg == '\'')
4856 {
4857 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4858 return FAIL;
4859 }
4860 else
4861 return FAIL;
4862
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004863 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004864 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004865 *arg = skipwhite(*arg);
4866 if (**arg != ')')
4867 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004868 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004869
4870 argvars[0] = *tv;
4871 argvars[1].v_type = VAR_UNKNOWN;
4872 tv->v_type = VAR_NUMBER;
4873 tv->vval.v_number = 0;
4874 f_has(argvars, tv);
4875 clear_tv(&argvars[0]);
4876
4877 while (start_leader < end_leader)
4878 {
4879 if (*start_leader == '!')
4880 tv->vval.v_number = !tv->vval.v_number;
4881 ++start_leader;
4882 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004883 }
4884
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004885 return OK;
4886}
4887
Bram Moolenaar080457c2020-03-03 21:53:32 +01004888 static int
4889evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4890{
4891 exptype_T type = EXPR_UNKNOWN;
4892 char_u *p;
4893 int len = 2;
4894 int type_is = FALSE;
4895
4896 // get the first variable
4897 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4898 return FAIL;
4899
4900 p = skipwhite(*arg);
4901 type = get_compare_type(p, &len, &type_is);
4902
4903 /*
4904 * If there is a comparative operator, use it.
4905 */
4906 if (type != EXPR_UNKNOWN)
4907 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004908 typval_T tv2;
4909 char_u *s1, *s2;
4910 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4911 int n;
4912
4913 // TODO: Only string == string is supported now
4914 if (tv->v_type != VAR_STRING)
4915 return FAIL;
4916 if (type != EXPR_EQUAL)
4917 return FAIL;
4918
4919 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004920 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004921 *arg = skipwhite(p + len);
4922 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4923 || tv2.v_type != VAR_STRING)
4924 {
4925 clear_tv(&tv2);
4926 return FAIL;
4927 }
4928 s1 = tv_get_string_buf(tv, buf1);
4929 s2 = tv_get_string_buf(&tv2, buf2);
4930 n = STRCMP(s1, s2);
4931 clear_tv(tv);
4932 clear_tv(&tv2);
4933 tv->v_type = VAR_BOOL;
4934 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004935 }
4936
4937 return OK;
4938}
4939
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004940static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4941
4942/*
4943 * Compile constant || or &&.
4944 */
4945 static int
4946evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4947{
4948 char_u *p = skipwhite(*arg);
4949 int opchar = *op;
4950
4951 if (p[0] == opchar && p[1] == opchar)
4952 {
4953 int val = tv2bool(tv);
4954
4955 /*
4956 * Repeat until there is no following "||" or "&&"
4957 */
4958 while (p[0] == opchar && p[1] == opchar)
4959 {
4960 typval_T tv2;
4961
4962 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4963 return FAIL;
4964
4965 // eval the next expression
4966 *arg = skipwhite(p + 2);
4967 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004968 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004969 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004970 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004971 {
4972 clear_tv(&tv2);
4973 return FAIL;
4974 }
4975 if ((opchar == '&') == val)
4976 {
4977 // false || tv2 or true && tv2: use tv2
4978 clear_tv(tv);
4979 *tv = tv2;
4980 val = tv2bool(tv);
4981 }
4982 else
4983 clear_tv(&tv2);
4984 p = skipwhite(*arg);
4985 }
4986 }
4987
4988 return OK;
4989}
4990
4991/*
4992 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4993 * Return FAIL if the expression is not a constant.
4994 */
4995 static int
4996evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4997{
4998 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004999 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005000 return FAIL;
5001
5002 // || and && work almost the same
5003 return evaluate_const_and_or(arg, cctx, "&&", tv);
5004}
5005
5006/*
5007 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
5008 * Return FAIL if the expression is not a constant.
5009 */
5010 static int
5011evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
5012{
5013 // evaluate the first expression
5014 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
5015 return FAIL;
5016
5017 // || and && work almost the same
5018 return evaluate_const_and_or(arg, cctx, "||", tv);
5019}
5020
5021/*
5022 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
5023 * E.g. for "has('feature')".
5024 * This does not produce error messages. "tv" should be cleared afterwards.
5025 * Return FAIL if the expression is not a constant.
5026 */
5027 static int
5028evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
5029{
5030 char_u *p;
5031
5032 // evaluate the first expression
5033 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
5034 return FAIL;
5035
5036 p = skipwhite(*arg);
5037 if (*p == '?')
5038 {
5039 int val = tv2bool(tv);
5040 typval_T tv2;
5041
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005042 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005043 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5044 return FAIL;
5045
5046 // evaluate the second expression; any type is accepted
5047 clear_tv(tv);
5048 *arg = skipwhite(p + 1);
5049 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
5050 return FAIL;
5051
5052 // Check for the ":".
5053 p = skipwhite(*arg);
5054 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5055 return FAIL;
5056
5057 // evaluate the third expression
5058 *arg = skipwhite(p + 1);
5059 tv2.v_type = VAR_UNKNOWN;
5060 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
5061 {
5062 clear_tv(&tv2);
5063 return FAIL;
5064 }
5065 if (val)
5066 {
5067 // use the expr after "?"
5068 clear_tv(&tv2);
5069 }
5070 else
5071 {
5072 // use the expr after ":"
5073 clear_tv(tv);
5074 *tv = tv2;
5075 }
5076 }
5077 return OK;
5078}
5079
5080/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005081 * compile "if expr"
5082 *
5083 * "if expr" Produces instructions:
5084 * EVAL expr Push result of "expr"
5085 * JUMP_IF_FALSE end
5086 * ... body ...
5087 * end:
5088 *
5089 * "if expr | else" Produces instructions:
5090 * EVAL expr Push result of "expr"
5091 * JUMP_IF_FALSE else
5092 * ... body ...
5093 * JUMP_ALWAYS end
5094 * else:
5095 * ... body ...
5096 * end:
5097 *
5098 * "if expr1 | elseif expr2 | else" Produces instructions:
5099 * EVAL expr Push result of "expr"
5100 * JUMP_IF_FALSE elseif
5101 * ... body ...
5102 * JUMP_ALWAYS end
5103 * elseif:
5104 * EVAL expr Push result of "expr"
5105 * JUMP_IF_FALSE else
5106 * ... body ...
5107 * JUMP_ALWAYS end
5108 * else:
5109 * ... body ...
5110 * end:
5111 */
5112 static char_u *
5113compile_if(char_u *arg, cctx_T *cctx)
5114{
5115 char_u *p = arg;
5116 garray_T *instr = &cctx->ctx_instr;
5117 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005118 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005119
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005120 // compile "expr"; if we know it evaluates to FALSE skip the block
5121 tv.v_type = VAR_UNKNOWN;
5122 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5123 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5124 else
5125 cctx->ctx_skip = MAYBE;
5126 clear_tv(&tv);
5127 if (cctx->ctx_skip == MAYBE)
5128 {
5129 p = arg;
5130 if (compile_expr1(&p, cctx) == FAIL)
5131 return NULL;
5132 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005133
5134 scope = new_scope(cctx, IF_SCOPE);
5135 if (scope == NULL)
5136 return NULL;
5137
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005138 if (cctx->ctx_skip == MAYBE)
5139 {
5140 // "where" is set when ":elseif", "else" or ":endif" is found
5141 scope->se_u.se_if.is_if_label = instr->ga_len;
5142 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5143 }
5144 else
5145 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005146
5147 return p;
5148}
5149
5150 static char_u *
5151compile_elseif(char_u *arg, cctx_T *cctx)
5152{
5153 char_u *p = arg;
5154 garray_T *instr = &cctx->ctx_instr;
5155 isn_T *isn;
5156 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005157 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005158
5159 if (scope == NULL || scope->se_type != IF_SCOPE)
5160 {
5161 emsg(_(e_elseif_without_if));
5162 return NULL;
5163 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005164 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005165
Bram Moolenaar158906c2020-02-06 20:39:45 +01005166 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005167 {
5168 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005169 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005170 return NULL;
5171 // previous "if" or "elseif" jumps here
5172 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5173 isn->isn_arg.jump.jump_where = instr->ga_len;
5174 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005175
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005176 // compile "expr"; if we know it evaluates to FALSE skip the block
5177 tv.v_type = VAR_UNKNOWN;
5178 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5179 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5180 else
5181 cctx->ctx_skip = MAYBE;
5182 clear_tv(&tv);
5183 if (cctx->ctx_skip == MAYBE)
5184 {
5185 p = arg;
5186 if (compile_expr1(&p, cctx) == FAIL)
5187 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005188
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005189 // "where" is set when ":elseif", "else" or ":endif" is found
5190 scope->se_u.se_if.is_if_label = instr->ga_len;
5191 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5192 }
5193 else
5194 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005195
5196 return p;
5197}
5198
5199 static char_u *
5200compile_else(char_u *arg, cctx_T *cctx)
5201{
5202 char_u *p = arg;
5203 garray_T *instr = &cctx->ctx_instr;
5204 isn_T *isn;
5205 scope_T *scope = cctx->ctx_scope;
5206
5207 if (scope == NULL || scope->se_type != IF_SCOPE)
5208 {
5209 emsg(_(e_else_without_if));
5210 return NULL;
5211 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005212 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005213
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005214 // jump from previous block to the end, unless the else block is empty
5215 if (cctx->ctx_skip == MAYBE)
5216 {
5217 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005218 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005219 return NULL;
5220 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005221
Bram Moolenaar158906c2020-02-06 20:39:45 +01005222 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005223 {
5224 if (scope->se_u.se_if.is_if_label >= 0)
5225 {
5226 // previous "if" or "elseif" jumps here
5227 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5228 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005229 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005230 }
5231 }
5232
5233 if (cctx->ctx_skip != MAYBE)
5234 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005235
5236 return p;
5237}
5238
5239 static char_u *
5240compile_endif(char_u *arg, cctx_T *cctx)
5241{
5242 scope_T *scope = cctx->ctx_scope;
5243 ifscope_T *ifscope;
5244 garray_T *instr = &cctx->ctx_instr;
5245 isn_T *isn;
5246
5247 if (scope == NULL || scope->se_type != IF_SCOPE)
5248 {
5249 emsg(_(e_endif_without_if));
5250 return NULL;
5251 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005252 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005253 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005254
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005255 if (scope->se_u.se_if.is_if_label >= 0)
5256 {
5257 // previous "if" or "elseif" jumps here
5258 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5259 isn->isn_arg.jump.jump_where = instr->ga_len;
5260 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005261 // Fill in the "end" label in jumps at the end of the blocks.
5262 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005263 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005264
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005265 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005266 return arg;
5267}
5268
5269/*
5270 * compile "for var in expr"
5271 *
5272 * Produces instructions:
5273 * PUSHNR -1
5274 * STORE loop-idx Set index to -1
5275 * EVAL expr Push result of "expr"
5276 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5277 * - if beyond end, jump to "end"
5278 * - otherwise get item from list and push it
5279 * STORE var Store item in "var"
5280 * ... body ...
5281 * JUMP top Jump back to repeat
5282 * end: DROP Drop the result of "expr"
5283 *
5284 */
5285 static char_u *
5286compile_for(char_u *arg, cctx_T *cctx)
5287{
5288 char_u *p;
5289 size_t varlen;
5290 garray_T *instr = &cctx->ctx_instr;
5291 garray_T *stack = &cctx->ctx_type_stack;
5292 scope_T *scope;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005293 lvar_T *loop_lvar; // loop iteration variable
5294 lvar_T *var_lvar; // variable for "var"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005295 type_T *vartype;
5296
5297 // TODO: list of variables: "for [key, value] in dict"
5298 // parse "var"
5299 for (p = arg; eval_isnamec1(*p); ++p)
5300 ;
5301 varlen = p - arg;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005302 var_lvar = lookup_local(arg, varlen, cctx);
5303 if (var_lvar != NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005304 {
5305 semsg(_("E1023: variable already defined: %s"), arg);
5306 return NULL;
5307 }
5308
5309 // consume "in"
5310 p = skipwhite(p);
5311 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5312 {
5313 emsg(_(e_missing_in));
5314 return NULL;
5315 }
5316 p = skipwhite(p + 2);
5317
5318
5319 scope = new_scope(cctx, FOR_SCOPE);
5320 if (scope == NULL)
5321 return NULL;
5322
5323 // Reserve a variable to store the loop iteration counter.
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005324 loop_lvar = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5325 if (loop_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005326 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005327 // out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005328 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005329 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005330 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005331
5332 // Reserve a variable to store "var"
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005333 var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5334 if (var_lvar == NULL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005335 {
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005336 // out of memory or used as an argument
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005337 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005338 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005339 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005340
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005341 generate_STORENR(cctx, loop_lvar->lv_idx, -1);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005342
5343 // compile "expr", it remains on the stack until "endfor"
5344 arg = p;
5345 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005346 {
5347 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005348 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005349 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005350
5351 // now we know the type of "var"
5352 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5353 if (vartype->tt_type != VAR_LIST)
5354 {
5355 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005356 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005357 return NULL;
5358 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005359 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005360 var_lvar->lv_type = vartype->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005361
5362 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005363 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005364
Bram Moolenaarb84a3812020-05-01 15:44:29 +02005365 generate_FOR(cctx, loop_lvar->lv_idx);
5366 generate_STORE(cctx, ISN_STORE, var_lvar->lv_idx, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005367
5368 return arg;
5369}
5370
5371/*
5372 * compile "endfor"
5373 */
5374 static char_u *
5375compile_endfor(char_u *arg, cctx_T *cctx)
5376{
5377 garray_T *instr = &cctx->ctx_instr;
5378 scope_T *scope = cctx->ctx_scope;
5379 forscope_T *forscope;
5380 isn_T *isn;
5381
5382 if (scope == NULL || scope->se_type != FOR_SCOPE)
5383 {
5384 emsg(_(e_for));
5385 return NULL;
5386 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005387 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005388 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005389 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005390
5391 // At end of ":for" scope jump back to the FOR instruction.
5392 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5393
5394 // Fill in the "end" label in the FOR statement so it can jump here
5395 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5396 isn->isn_arg.forloop.for_end = instr->ga_len;
5397
5398 // Fill in the "end" label any BREAK statements
5399 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5400
5401 // Below the ":for" scope drop the "expr" list from the stack.
5402 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5403 return NULL;
5404
5405 vim_free(scope);
5406
5407 return arg;
5408}
5409
5410/*
5411 * compile "while expr"
5412 *
5413 * Produces instructions:
5414 * top: EVAL expr Push result of "expr"
5415 * JUMP_IF_FALSE end jump if false
5416 * ... body ...
5417 * JUMP top Jump back to repeat
5418 * end:
5419 *
5420 */
5421 static char_u *
5422compile_while(char_u *arg, cctx_T *cctx)
5423{
5424 char_u *p = arg;
5425 garray_T *instr = &cctx->ctx_instr;
5426 scope_T *scope;
5427
5428 scope = new_scope(cctx, WHILE_SCOPE);
5429 if (scope == NULL)
5430 return NULL;
5431
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005432 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005433
5434 // compile "expr"
5435 if (compile_expr1(&p, cctx) == FAIL)
5436 return NULL;
5437
5438 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005439 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005440 JUMP_IF_FALSE, cctx) == FAIL)
5441 return FAIL;
5442
5443 return p;
5444}
5445
5446/*
5447 * compile "endwhile"
5448 */
5449 static char_u *
5450compile_endwhile(char_u *arg, cctx_T *cctx)
5451{
5452 scope_T *scope = cctx->ctx_scope;
5453
5454 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5455 {
5456 emsg(_(e_while));
5457 return NULL;
5458 }
5459 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005460 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005461
5462 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005463 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005464
5465 // Fill in the "end" label in the WHILE statement so it can jump here.
5466 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005467 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005468
5469 vim_free(scope);
5470
5471 return arg;
5472}
5473
5474/*
5475 * compile "continue"
5476 */
5477 static char_u *
5478compile_continue(char_u *arg, cctx_T *cctx)
5479{
5480 scope_T *scope = cctx->ctx_scope;
5481
5482 for (;;)
5483 {
5484 if (scope == NULL)
5485 {
5486 emsg(_(e_continue));
5487 return NULL;
5488 }
5489 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5490 break;
5491 scope = scope->se_outer;
5492 }
5493
5494 // Jump back to the FOR or WHILE instruction.
5495 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005496 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5497 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005498 return arg;
5499}
5500
5501/*
5502 * compile "break"
5503 */
5504 static char_u *
5505compile_break(char_u *arg, cctx_T *cctx)
5506{
5507 scope_T *scope = cctx->ctx_scope;
5508 endlabel_T **el;
5509
5510 for (;;)
5511 {
5512 if (scope == NULL)
5513 {
5514 emsg(_(e_break));
5515 return NULL;
5516 }
5517 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5518 break;
5519 scope = scope->se_outer;
5520 }
5521
5522 // Jump to the end of the FOR or WHILE loop.
5523 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005524 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005525 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005526 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005527 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5528 return FAIL;
5529
5530 return arg;
5531}
5532
5533/*
5534 * compile "{" start of block
5535 */
5536 static char_u *
5537compile_block(char_u *arg, cctx_T *cctx)
5538{
5539 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5540 return NULL;
5541 return skipwhite(arg + 1);
5542}
5543
5544/*
5545 * compile end of block: drop one scope
5546 */
5547 static void
5548compile_endblock(cctx_T *cctx)
5549{
5550 scope_T *scope = cctx->ctx_scope;
5551
5552 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005553 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005554 vim_free(scope);
5555}
5556
5557/*
5558 * compile "try"
5559 * Creates a new scope for the try-endtry, pointing to the first catch and
5560 * finally.
5561 * Creates another scope for the "try" block itself.
5562 * TRY instruction sets up exception handling at runtime.
5563 *
5564 * "try"
5565 * TRY -> catch1, -> finally push trystack entry
5566 * ... try block
5567 * "throw {exception}"
5568 * EVAL {exception}
5569 * THROW create exception
5570 * ... try block
5571 * " catch {expr}"
5572 * JUMP -> finally
5573 * catch1: PUSH exeception
5574 * EVAL {expr}
5575 * MATCH
5576 * JUMP nomatch -> catch2
5577 * CATCH remove exception
5578 * ... catch block
5579 * " catch"
5580 * JUMP -> finally
5581 * catch2: CATCH remove exception
5582 * ... catch block
5583 * " finally"
5584 * finally:
5585 * ... finally block
5586 * " endtry"
5587 * ENDTRY pop trystack entry, may rethrow
5588 */
5589 static char_u *
5590compile_try(char_u *arg, cctx_T *cctx)
5591{
5592 garray_T *instr = &cctx->ctx_instr;
5593 scope_T *try_scope;
5594 scope_T *scope;
5595
5596 // scope that holds the jumps that go to catch/finally/endtry
5597 try_scope = new_scope(cctx, TRY_SCOPE);
5598 if (try_scope == NULL)
5599 return NULL;
5600
5601 // "catch" is set when the first ":catch" is found.
5602 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005603 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005604 if (generate_instr(cctx, ISN_TRY) == NULL)
5605 return NULL;
5606
5607 // scope for the try block itself
5608 scope = new_scope(cctx, BLOCK_SCOPE);
5609 if (scope == NULL)
5610 return NULL;
5611
5612 return arg;
5613}
5614
5615/*
5616 * compile "catch {expr}"
5617 */
5618 static char_u *
5619compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5620{
5621 scope_T *scope = cctx->ctx_scope;
5622 garray_T *instr = &cctx->ctx_instr;
5623 char_u *p;
5624 isn_T *isn;
5625
5626 // end block scope from :try or :catch
5627 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5628 compile_endblock(cctx);
5629 scope = cctx->ctx_scope;
5630
5631 // Error if not in a :try scope
5632 if (scope == NULL || scope->se_type != TRY_SCOPE)
5633 {
5634 emsg(_(e_catch));
5635 return NULL;
5636 }
5637
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005638 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005639 {
5640 emsg(_("E1033: catch unreachable after catch-all"));
5641 return NULL;
5642 }
5643
5644 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005645 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005646 JUMP_ALWAYS, cctx) == FAIL)
5647 return NULL;
5648
5649 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005650 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005651 if (isn->isn_arg.try.try_catch == 0)
5652 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005653 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005654 {
5655 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005656 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005657 isn->isn_arg.jump.jump_where = instr->ga_len;
5658 }
5659
5660 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005661 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005662 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005663 scope->se_u.se_try.ts_caught_all = TRUE;
5664 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005665 }
5666 else
5667 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005668 char_u *end;
5669 char_u *pat;
5670 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005671 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005672 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005673
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005674 // Push v:exception, push {expr} and MATCH
5675 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5676
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005677 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005678 if (*end != *p)
5679 {
5680 semsg(_("E1067: Separator mismatch: %s"), p);
5681 vim_free(tofree);
5682 return FAIL;
5683 }
5684 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005685 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005686 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005687 len = (int)(end - tofree);
5688 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005689 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005690 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005691 if (pat == NULL)
5692 return FAIL;
5693 if (generate_PUSHS(cctx, pat) == FAIL)
5694 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005695
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005696 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5697 return NULL;
5698
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005699 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005700 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5701 return NULL;
5702 }
5703
5704 if (generate_instr(cctx, ISN_CATCH) == NULL)
5705 return NULL;
5706
5707 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5708 return NULL;
5709 return p;
5710}
5711
5712 static char_u *
5713compile_finally(char_u *arg, cctx_T *cctx)
5714{
5715 scope_T *scope = cctx->ctx_scope;
5716 garray_T *instr = &cctx->ctx_instr;
5717 isn_T *isn;
5718
5719 // end block scope from :try or :catch
5720 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5721 compile_endblock(cctx);
5722 scope = cctx->ctx_scope;
5723
5724 // Error if not in a :try scope
5725 if (scope == NULL || scope->se_type != TRY_SCOPE)
5726 {
5727 emsg(_(e_finally));
5728 return NULL;
5729 }
5730
5731 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005732 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005733 if (isn->isn_arg.try.try_finally != 0)
5734 {
5735 emsg(_(e_finally_dup));
5736 return NULL;
5737 }
5738
5739 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005740 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005741
Bram Moolenaar585fea72020-04-02 22:33:21 +02005742 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005743 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005744 {
5745 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005746 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005747 isn->isn_arg.jump.jump_where = instr->ga_len;
5748 }
5749
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005750 // TODO: set index in ts_finally_label jumps
5751
5752 return arg;
5753}
5754
5755 static char_u *
5756compile_endtry(char_u *arg, cctx_T *cctx)
5757{
5758 scope_T *scope = cctx->ctx_scope;
5759 garray_T *instr = &cctx->ctx_instr;
5760 isn_T *isn;
5761
5762 // end block scope from :catch or :finally
5763 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5764 compile_endblock(cctx);
5765 scope = cctx->ctx_scope;
5766
5767 // Error if not in a :try scope
5768 if (scope == NULL || scope->se_type != TRY_SCOPE)
5769 {
5770 if (scope == NULL)
5771 emsg(_(e_no_endtry));
5772 else if (scope->se_type == WHILE_SCOPE)
5773 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005774 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005775 emsg(_(e_endfor));
5776 else
5777 emsg(_(e_endif));
5778 return NULL;
5779 }
5780
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005781 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005782 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5783 {
5784 emsg(_("E1032: missing :catch or :finally"));
5785 return NULL;
5786 }
5787
5788 // Fill in the "end" label in jumps at the end of the blocks, if not done
5789 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005790 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005791
5792 // End :catch or :finally scope: set value in ISN_TRY instruction
5793 if (isn->isn_arg.try.try_finally == 0)
5794 isn->isn_arg.try.try_finally = instr->ga_len;
5795 compile_endblock(cctx);
5796
5797 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5798 return NULL;
5799 return arg;
5800}
5801
5802/*
5803 * compile "throw {expr}"
5804 */
5805 static char_u *
5806compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5807{
5808 char_u *p = skipwhite(arg);
5809
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005810 if (compile_expr1(&p, cctx) == FAIL)
5811 return NULL;
5812 if (may_generate_2STRING(-1, cctx) == FAIL)
5813 return NULL;
5814 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5815 return NULL;
5816
5817 return p;
5818}
5819
5820/*
5821 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005822 * compile "echomsg expr"
5823 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01005824 * compile "execute expr"
5825 */
5826 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005827compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01005828{
5829 char_u *p = arg;
5830 int count = 0;
5831
5832 for (;;)
5833 {
5834 if (compile_expr1(&p, cctx) == FAIL)
5835 return NULL;
5836 ++count;
5837 p = skipwhite(p);
5838 if (ends_excmd(*p))
5839 break;
5840 }
5841
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005842 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
5843 generate_ECHO(cctx, cmdidx == CMD_echo, count);
5844 else if (cmdidx == CMD_execute)
5845 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
5846 else if (cmdidx == CMD_echomsg)
5847 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
5848 else
5849 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005850 return p;
5851}
5852
5853/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005854 * A command that is not compiled, execute with legacy code.
5855 */
5856 static char_u *
5857compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
5858{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005859 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005860 int has_expr = FALSE;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005861
5862 if (cctx->ctx_skip == TRUE)
5863 goto theend;
5864
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005865 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
5866 has_expr = (excmd_get_argt(eap->cmdidx) & (EX_XFILE | EX_EXPAND));
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005867 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
5868 {
5869 // expand filename in "syntax include [@group] filename"
5870 has_expr = TRUE;
5871 eap->arg = skipwhite(eap->arg + 7);
5872 if (*eap->arg == '@')
5873 eap->arg = skiptowhite(eap->arg);
5874 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005875
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005876 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005877 {
5878 int count = 0;
5879 char_u *start = skipwhite(line);
5880
5881 // :cmd xxx`=expr1`yyy`=expr2`zzz
5882 // PUSHS ":cmd xxx"
5883 // eval expr1
5884 // PUSHS "yyy"
5885 // eval expr2
5886 // PUSHS "zzz"
5887 // EXECCONCAT 5
5888 for (;;)
5889 {
5890 if (p > start)
5891 {
5892 generate_PUSHS(cctx, vim_strnsave(start, (int)(p - start)));
5893 ++count;
5894 }
5895 p += 2;
5896 if (compile_expr1(&p, cctx) == FAIL)
5897 return NULL;
5898 may_generate_2STRING(-1, cctx);
5899 ++count;
5900 p = skipwhite(p);
5901 if (*p != '`')
5902 {
5903 emsg(_("E1083: missing backtick"));
5904 return NULL;
5905 }
5906 start = p + 1;
5907
5908 p = (char_u *)strstr((char *)start, "`=");
5909 if (p == NULL)
5910 {
5911 if (*skipwhite(start) != NUL)
5912 {
5913 generate_PUSHS(cctx, vim_strsave(start));
5914 ++count;
5915 }
5916 break;
5917 }
5918 }
5919 generate_EXECCONCAT(cctx, count);
5920 }
5921 else
5922 generate_EXEC(cctx, line);
5923
5924theend:
5925 return (char_u *)"";
5926}
5927
5928/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005929 * After ex_function() has collected all the function lines: parse and compile
5930 * the lines into instructions.
5931 * Adds the function to "def_functions".
5932 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5933 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005934 * This can be used recursively through compile_lambda(), which may reallocate
5935 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005936 */
5937 void
5938compile_def_function(ufunc_T *ufunc, int set_return_type)
5939{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005940 char_u *line = NULL;
5941 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005942 char *errormsg = NULL; // error message
5943 int had_return = FALSE;
5944 cctx_T cctx;
5945 garray_T *instr;
5946 int called_emsg_before = called_emsg;
5947 int ret = FAIL;
5948 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005949 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005950
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005951 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005952 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005953
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005954 if (ufunc->uf_dfunc_idx >= 0)
5955 {
5956 // Redefining a function that was compiled before.
5957 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5958
5959 // Free old instructions.
5960 delete_def_function_contents(dfunc);
5961 }
5962 else
5963 {
5964 // Add the function to "def_functions".
5965 if (ga_grow(&def_functions, 1) == FAIL)
5966 return;
5967 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005968 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005969 dfunc->df_idx = def_functions.ga_len;
5970 ufunc->uf_dfunc_idx = dfunc->df_idx;
5971 dfunc->df_ufunc = ufunc;
5972 ++def_functions.ga_len;
5973 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005974 }
5975
Bram Moolenaara80faa82020-04-12 19:37:17 +02005976 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005977 cctx.ctx_ufunc = ufunc;
5978 cctx.ctx_lnum = -1;
5979 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5980 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5981 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5982 cctx.ctx_type_list = &ufunc->uf_type_list;
5983 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5984 instr = &cctx.ctx_instr;
5985
5986 // Most modern script version.
5987 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5988
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005989 if (ufunc->uf_def_args.ga_len > 0)
5990 {
5991 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005992 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005993 int i;
5994 char_u *arg;
5995 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5996
5997 // Produce instructions for the default values of optional arguments.
5998 // Store the instruction index in uf_def_arg_idx[] so that we know
5999 // where to start when the function is called, depending on the number
6000 // of arguments.
6001 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
6002 if (ufunc->uf_def_arg_idx == NULL)
6003 goto erret;
6004 for (i = 0; i < count; ++i)
6005 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006006 garray_T *stack = &cctx.ctx_type_stack;
6007 type_T *val_type;
6008 int arg_idx = first_def_arg + i;
6009
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006010 ufunc->uf_def_arg_idx[i] = instr->ga_len;
6011 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02006012 if (compile_expr1(&arg, &cctx) == FAIL)
6013 goto erret;
6014
6015 // If no type specified use the type of the default value.
6016 // Otherwise check that the default value type matches the
6017 // specified type.
6018 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
6019 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
6020 ufunc->uf_arg_types[arg_idx] = val_type;
6021 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
6022 == FAIL)
6023 {
6024 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
6025 arg_idx + 1);
6026 goto erret;
6027 }
6028
6029 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006030 goto erret;
6031 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01006032 ufunc->uf_def_arg_idx[count] = instr->ga_len;
6033 }
6034
6035 /*
6036 * Loop over all the lines of the function and generate instructions.
6037 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006038 for (;;)
6039 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006040 exarg_T ea;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006041 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006042
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006043 // Bail out on the first error to avoid a flood of errors and report
6044 // the right line number when inside try/catch.
6045 if (emsg_before != called_emsg)
6046 goto erret;
6047
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006048 if (line != NULL && *line == '|')
6049 // the line continues after a '|'
6050 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02006051 else if (line != NULL && *line != NUL
6052 && !(*line == '#' && (line == cctx.ctx_line_start
6053 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006054 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006055 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006056 goto erret;
6057 }
6058 else
6059 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006060 line = next_line_from_context(&cctx);
6061 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006062 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006063 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006064 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006065 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006066
6067 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006068 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006069 ea.cmdlinep = &line;
6070 ea.cmd = skipwhite(line);
6071
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006072 // Some things can be recognized by the first character.
6073 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006074 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006075 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006076 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006077 if (ea.cmd[1] != '{')
6078 {
6079 line = (char_u *)"";
6080 continue;
6081 }
6082 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006083
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006084 case '}':
6085 {
6086 // "}" ends a block scope
6087 scopetype_T stype = cctx.ctx_scope == NULL
6088 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006089
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006090 if (stype == BLOCK_SCOPE)
6091 {
6092 compile_endblock(&cctx);
6093 line = ea.cmd;
6094 }
6095 else
6096 {
6097 emsg(_("E1025: using } outside of a block scope"));
6098 goto erret;
6099 }
6100 if (line != NULL)
6101 line = skipwhite(ea.cmd + 1);
6102 continue;
6103 }
6104
6105 case '{':
6106 // "{" starts a block scope
6107 // "{'a': 1}->func() is something else
6108 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6109 {
6110 line = compile_block(ea.cmd, &cctx);
6111 continue;
6112 }
6113 break;
6114
6115 case ':':
6116 is_ex_command = TRUE;
6117 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006118 }
6119
6120 /*
6121 * COMMAND MODIFIERS
6122 */
6123 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6124 {
6125 if (errormsg != NULL)
6126 goto erret;
6127 // empty line or comment
6128 line = (char_u *)"";
6129 continue;
6130 }
6131
6132 // Skip ":call" to get to the function name.
6133 if (checkforcmd(&ea.cmd, "call", 3))
6134 ea.cmd = skipwhite(ea.cmd);
6135
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006136 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006137 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006138 // Assuming the command starts with a variable or function name,
6139 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6140 // val".
6141 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6142 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006143 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006144 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006145 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006146 int oplen;
6147 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006148
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006149 oplen = assignment_len(skipwhite(p), &heredoc);
6150 if (oplen > 0)
6151 {
6152 // Recognize an assignment if we recognize the variable
6153 // name:
6154 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006155 // "local = expr" where "local" is a local var.
6156 // "script = expr" where "script" is a script-local var.
6157 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006158 // "&opt = expr"
6159 // "$ENV = expr"
6160 // "@r = expr"
6161 if (*ea.cmd == '&'
6162 || *ea.cmd == '$'
6163 || *ea.cmd == '@'
6164 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006165 || lookup_local(ea.cmd, p - ea.cmd, &cctx) != NULL
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006166 || lookup_script(ea.cmd, p - ea.cmd) == OK
6167 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6168 {
6169 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6170 if (line == NULL)
6171 goto erret;
6172 continue;
6173 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006174 }
6175 }
6176 }
6177
6178 /*
6179 * COMMAND after range
6180 */
6181 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006182 p = find_ex_command(&ea, NULL, is_ex_command ? NULL
6183 : (void *(*)(char_u *, size_t, cctx_T *))lookup_local,
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006184 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006185
6186 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6187 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006188 if (cctx.ctx_skip == TRUE)
6189 {
6190 line += STRLEN(line);
6191 continue;
6192 }
6193
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006194 // Expression or function call.
6195 if (ea.cmdidx == CMD_eval)
6196 {
6197 p = ea.cmd;
6198 if (compile_expr1(&p, &cctx) == FAIL)
6199 goto erret;
6200
6201 // drop the return value
6202 generate_instr_drop(&cctx, ISN_DROP, 1);
6203 line = p;
6204 continue;
6205 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006206 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006207 iemsg("Command from find_ex_command() not handled");
6208 goto erret;
6209 }
6210
6211 p = skipwhite(p);
6212
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006213 if (cctx.ctx_skip == TRUE
6214 && ea.cmdidx != CMD_elseif
6215 && ea.cmdidx != CMD_else
6216 && ea.cmdidx != CMD_endif)
6217 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006218 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006219 continue;
6220 }
6221
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006222 switch (ea.cmdidx)
6223 {
6224 case CMD_def:
6225 case CMD_function:
6226 // TODO: Nested function
6227 emsg("Nested function not implemented yet");
6228 goto erret;
6229
6230 case CMD_return:
6231 line = compile_return(p, set_return_type, &cctx);
6232 had_return = TRUE;
6233 break;
6234
6235 case CMD_let:
6236 case CMD_const:
6237 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6238 break;
6239
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006240 case CMD_unlet:
6241 case CMD_unlockvar:
6242 case CMD_lockvar:
6243 line = compile_unletlock(p, &ea, &cctx);
6244 break;
6245
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006246 case CMD_import:
6247 line = compile_import(p, &cctx);
6248 break;
6249
6250 case CMD_if:
6251 line = compile_if(p, &cctx);
6252 break;
6253 case CMD_elseif:
6254 line = compile_elseif(p, &cctx);
6255 break;
6256 case CMD_else:
6257 line = compile_else(p, &cctx);
6258 break;
6259 case CMD_endif:
6260 line = compile_endif(p, &cctx);
6261 break;
6262
6263 case CMD_while:
6264 line = compile_while(p, &cctx);
6265 break;
6266 case CMD_endwhile:
6267 line = compile_endwhile(p, &cctx);
6268 break;
6269
6270 case CMD_for:
6271 line = compile_for(p, &cctx);
6272 break;
6273 case CMD_endfor:
6274 line = compile_endfor(p, &cctx);
6275 break;
6276 case CMD_continue:
6277 line = compile_continue(p, &cctx);
6278 break;
6279 case CMD_break:
6280 line = compile_break(p, &cctx);
6281 break;
6282
6283 case CMD_try:
6284 line = compile_try(p, &cctx);
6285 break;
6286 case CMD_catch:
6287 line = compile_catch(p, &cctx);
6288 break;
6289 case CMD_finally:
6290 line = compile_finally(p, &cctx);
6291 break;
6292 case CMD_endtry:
6293 line = compile_endtry(p, &cctx);
6294 break;
6295 case CMD_throw:
6296 line = compile_throw(p, &cctx);
6297 break;
6298
6299 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006300 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006301 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006302 case CMD_echomsg:
6303 case CMD_echoerr:
6304 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006305 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006306
6307 default:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006308 // TODO: other commands with an expression argument
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006309 // Not recognized, execute with do_cmdline_cmd().
6310 ea.arg = p;
6311 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006312 break;
6313 }
6314 if (line == NULL)
6315 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006316 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006317
6318 if (cctx.ctx_type_stack.ga_len < 0)
6319 {
6320 iemsg("Type stack underflow");
6321 goto erret;
6322 }
6323 }
6324
6325 if (cctx.ctx_scope != NULL)
6326 {
6327 if (cctx.ctx_scope->se_type == IF_SCOPE)
6328 emsg(_(e_endif));
6329 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6330 emsg(_(e_endwhile));
6331 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6332 emsg(_(e_endfor));
6333 else
6334 emsg(_("E1026: Missing }"));
6335 goto erret;
6336 }
6337
6338 if (!had_return)
6339 {
6340 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6341 {
6342 emsg(_("E1027: Missing return statement"));
6343 goto erret;
6344 }
6345
6346 // Return zero if there is no return at the end.
6347 generate_PUSHNR(&cctx, 0);
6348 generate_instr(&cctx, ISN_RETURN);
6349 }
6350
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006351 {
6352 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6353 + ufunc->uf_dfunc_idx;
6354 dfunc->df_deleted = FALSE;
6355 dfunc->df_instr = instr->ga_data;
6356 dfunc->df_instr_count = instr->ga_len;
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006357 dfunc->df_varcount = cctx.ctx_locals_count;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006358 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006359
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006360 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006361 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006362 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006363
6364 // Create a type for the function, with the return type and any
6365 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006366 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6367 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006368 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006369 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006370 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6371 argcount, &ufunc->uf_type_list);
6372 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006373 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006374 argcount + varargs,
6375 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006376 {
6377 ret = FAIL;
6378 goto erret;
6379 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006380 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6381 ufunc->uf_func_type->tt_min_argcount =
6382 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006383 if (ufunc->uf_arg_types == NULL)
6384 {
6385 int i;
6386
6387 // lambda does not have argument types.
6388 for (i = 0; i < argcount; ++i)
6389 ufunc->uf_func_type->tt_args[i] = &t_any;
6390 }
6391 else
6392 mch_memmove(ufunc->uf_func_type->tt_args,
6393 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006394 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006395 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006396 ufunc->uf_func_type->tt_args[argcount] =
6397 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006398 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6399 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006400 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006401 else
6402 // No arguments, can use a predefined type.
6403 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6404 argcount, &ufunc->uf_type_list);
6405
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006406 }
6407
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006408 ret = OK;
6409
6410erret:
6411 if (ret == FAIL)
6412 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006413 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006414 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6415 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006416
6417 for (idx = 0; idx < instr->ga_len; ++idx)
6418 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006419 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006420
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006421 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006422 if (!dfunc->df_deleted)
6423 --def_functions.ga_len;
6424
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006425 while (cctx.ctx_scope != NULL)
6426 drop_scope(&cctx);
6427
Bram Moolenaar20431c92020-03-20 18:39:46 +01006428 // Don't execute this function body.
6429 ga_clear_strings(&ufunc->uf_lines);
6430
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006431 if (errormsg != NULL)
6432 emsg(errormsg);
6433 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006434 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006435 }
6436
6437 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006438 free_imported(&cctx);
Bram Moolenaarb84a3812020-05-01 15:44:29 +02006439 free_locals(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006440 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006441}
6442
6443/*
6444 * Delete an instruction, free what it contains.
6445 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006446 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006447delete_instr(isn_T *isn)
6448{
6449 switch (isn->isn_type)
6450 {
6451 case ISN_EXEC:
6452 case ISN_LOADENV:
6453 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006454 case ISN_LOADB:
6455 case ISN_LOADW:
6456 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006457 case ISN_LOADOPT:
6458 case ISN_MEMBER:
6459 case ISN_PUSHEXC:
6460 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006461 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006462 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006463 case ISN_STOREB:
6464 case ISN_STOREW:
6465 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006466 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006467 vim_free(isn->isn_arg.string);
6468 break;
6469
6470 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006471 case ISN_STORES:
6472 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006473 break;
6474
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006475 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006476 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006477 vim_free(isn->isn_arg.unlet.ul_name);
6478 break;
6479
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006480 case ISN_STOREOPT:
6481 vim_free(isn->isn_arg.storeopt.so_name);
6482 break;
6483
6484 case ISN_PUSHBLOB: // push blob isn_arg.blob
6485 blob_unref(isn->isn_arg.blob);
6486 break;
6487
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006488 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006489#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006490 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006491#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006492 break;
6493
6494 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006495#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006496 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006497#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006498 break;
6499
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006500 case ISN_UCALL:
6501 vim_free(isn->isn_arg.ufunc.cuf_name);
6502 break;
6503
6504 case ISN_2BOOL:
6505 case ISN_2STRING:
6506 case ISN_ADDBLOB:
6507 case ISN_ADDLIST:
6508 case ISN_BCALL:
6509 case ISN_CATCH:
6510 case ISN_CHECKNR:
6511 case ISN_CHECKTYPE:
6512 case ISN_COMPAREANY:
6513 case ISN_COMPAREBLOB:
6514 case ISN_COMPAREBOOL:
6515 case ISN_COMPAREDICT:
6516 case ISN_COMPAREFLOAT:
6517 case ISN_COMPAREFUNC:
6518 case ISN_COMPARELIST:
6519 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006520 case ISN_COMPARESPECIAL:
6521 case ISN_COMPARESTRING:
6522 case ISN_CONCAT:
6523 case ISN_DCALL:
6524 case ISN_DROP:
6525 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006526 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006527 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006528 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006529 case ISN_EXECCONCAT:
6530 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006531 case ISN_FOR:
6532 case ISN_FUNCREF:
6533 case ISN_INDEX:
6534 case ISN_JUMP:
6535 case ISN_LOAD:
6536 case ISN_LOADSCRIPT:
6537 case ISN_LOADREG:
6538 case ISN_LOADV:
6539 case ISN_NEGATENR:
6540 case ISN_NEWDICT:
6541 case ISN_NEWLIST:
6542 case ISN_OPNR:
6543 case ISN_OPFLOAT:
6544 case ISN_OPANY:
6545 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006546 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006547 case ISN_PUSHF:
6548 case ISN_PUSHNR:
6549 case ISN_PUSHBOOL:
6550 case ISN_PUSHSPEC:
6551 case ISN_RETURN:
6552 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006553 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006554 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006555 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006556 case ISN_STORESCRIPT:
6557 case ISN_THROW:
6558 case ISN_TRY:
6559 // nothing allocated
6560 break;
6561 }
6562}
6563
6564/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006565 * Free all instructions for "dfunc".
6566 */
6567 static void
6568delete_def_function_contents(dfunc_T *dfunc)
6569{
6570 int idx;
6571
6572 ga_clear(&dfunc->df_def_args_isn);
6573
6574 if (dfunc->df_instr != NULL)
6575 {
6576 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6577 delete_instr(dfunc->df_instr + idx);
6578 VIM_CLEAR(dfunc->df_instr);
6579 }
6580
6581 dfunc->df_deleted = TRUE;
6582}
6583
6584/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006585 * When a user function is deleted, delete any associated def function.
6586 */
6587 void
6588delete_def_function(ufunc_T *ufunc)
6589{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006590 if (ufunc->uf_dfunc_idx >= 0)
6591 {
6592 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6593 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006594
Bram Moolenaar20431c92020-03-20 18:39:46 +01006595 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006596 }
6597}
6598
6599#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006600/*
6601 * Free all functions defined with ":def".
6602 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006603 void
6604free_def_functions(void)
6605{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006606 int idx;
6607
6608 for (idx = 0; idx < def_functions.ga_len; ++idx)
6609 {
6610 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6611
6612 delete_def_function_contents(dfunc);
6613 }
6614
6615 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006616}
6617#endif
6618
6619
6620#endif // FEAT_EVAL