blob: 89a86779a633e38e38f214de79d0a216d7a62ecb [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * vim9compile.c: :def and dealing with instructions
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19#ifdef VMS
20# include <float.h>
21#endif
22
23#define DEFINE_VIM9_GLOBALS
24#include "vim9.h"
25
26/*
27 * Chain of jump instructions where the end label needs to be set.
28 */
29typedef struct endlabel_S endlabel_T;
30struct endlabel_S {
31 endlabel_T *el_next; // chain end_label locations
32 int el_end_label; // instruction idx where to set end
33};
34
35/*
36 * info specific for the scope of :if / elseif / else
37 */
38typedef struct {
39 int is_if_label; // instruction idx at IF or ELSEIF
40 endlabel_T *is_end_label; // instructions to set end label
41} ifscope_T;
42
43/*
44 * info specific for the scope of :while
45 */
46typedef struct {
47 int ws_top_label; // instruction idx at WHILE
48 endlabel_T *ws_end_label; // instructions to set end
49} whilescope_T;
50
51/*
52 * info specific for the scope of :for
53 */
54typedef struct {
55 int fs_top_label; // instruction idx at FOR
56 endlabel_T *fs_end_label; // break instructions
57} forscope_T;
58
59/*
60 * info specific for the scope of :try
61 */
62typedef struct {
63 int ts_try_label; // instruction idx at TRY
64 endlabel_T *ts_end_label; // jump to :finally or :endtry
65 int ts_catch_label; // instruction idx of last CATCH
66 int ts_caught_all; // "catch" without argument encountered
67} tryscope_T;
68
69typedef enum {
70 NO_SCOPE,
71 IF_SCOPE,
72 WHILE_SCOPE,
73 FOR_SCOPE,
74 TRY_SCOPE,
75 BLOCK_SCOPE
76} scopetype_T;
77
78/*
79 * Info for one scope, pointed to by "ctx_scope".
80 */
81typedef struct scope_S scope_T;
82struct scope_S {
83 scope_T *se_outer; // scope containing this one
84 scopetype_T se_type;
85 int se_local_count; // ctx_locals.ga_len before scope
86 union {
87 ifscope_T se_if;
88 whilescope_T se_while;
89 forscope_T se_for;
90 tryscope_T se_try;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +010091 } se_u;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010092};
93
94/*
95 * Entry for "ctx_locals". Used for arguments and local variables.
96 */
97typedef struct {
98 char_u *lv_name;
99 type_T *lv_type;
100 int lv_const; // when TRUE cannot be assigned to
101 int lv_arg; // when TRUE this is an argument
102} lvar_T;
103
104/*
105 * Context for compiling lines of Vim script.
106 * Stores info about the local variables and condition stack.
107 */
108struct cctx_S {
109 ufunc_T *ctx_ufunc; // current function
110 int ctx_lnum; // line number in current function
Bram Moolenaar7a092242020-04-16 22:10:49 +0200111 char_u *ctx_line_start; // start of current line or NULL
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100112 garray_T ctx_instr; // generated instructions
113
114 garray_T ctx_locals; // currently visible local variables
115 int ctx_max_local; // maximum number of locals at one time
116
117 garray_T ctx_imports; // imported items
118
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100119 int ctx_skip; // when TRUE skip commands, when FALSE skip
120 // commands after "else"
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100121 scope_T *ctx_scope; // current scope, NULL at toplevel
122
123 garray_T ctx_type_stack; // type of each item on the stack
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200124 garray_T *ctx_type_list; // list of pointers to allocated types
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100125};
126
127static char e_var_notfound[] = N_("E1001: variable not found: %s");
128static char e_syntax_at[] = N_("E1002: Syntax error at %s");
129
130static int compile_expr1(char_u **arg, cctx_T *cctx);
131static int compile_expr2(char_u **arg, cctx_T *cctx);
132static int compile_expr3(char_u **arg, cctx_T *cctx);
Bram Moolenaar20431c92020-03-20 18:39:46 +0100133static void delete_def_function_contents(dfunc_T *dfunc);
Bram Moolenaar0b76b422020-04-07 22:05:08 +0200134static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
135static int check_type(type_T *expected, type_T *actual, int give_msg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100136
137/*
138 * Lookup variable "name" in the local scope and return the index.
139 */
140 static int
141lookup_local(char_u *name, size_t len, cctx_T *cctx)
142{
143 int idx;
144
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100145 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100146 return -1;
147 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
148 {
149 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
150
151 if (STRNCMP(name, lvar->lv_name, len) == 0
152 && STRLEN(lvar->lv_name) == len)
153 return idx;
154 }
155 return -1;
156}
157
158/*
159 * Lookup an argument in the current function.
160 * Returns the argument index or -1 if not found.
161 */
162 static int
163lookup_arg(char_u *name, size_t len, cctx_T *cctx)
164{
165 int idx;
166
Bram Moolenaarae8d2de2020-02-13 21:42:24 +0100167 if (len == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100168 return -1;
169 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
170 {
171 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
172
173 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
174 return idx;
175 }
176 return -1;
177}
178
179/*
180 * Lookup a vararg argument in the current function.
181 * Returns TRUE if there is a match.
182 */
183 static int
184lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
185{
186 char_u *va_name = cctx->ctx_ufunc->uf_va_name;
187
188 return len > 0 && va_name != NULL
189 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
190}
191
192/*
193 * Lookup a variable in the current script.
194 * Returns OK or FAIL.
195 */
196 static int
197lookup_script(char_u *name, size_t len)
198{
199 int cc;
200 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid);
201 dictitem_T *di;
202
203 cc = name[len];
204 name[len] = NUL;
205 di = find_var_in_ht(ht, 0, name, TRUE);
206 name[len] = cc;
207 return di == NULL ? FAIL: OK;
208}
209
Bram Moolenaar5269bd22020-03-09 19:25:27 +0100210/*
211 * Check if "p[len]" is already defined, either in script "import_sid" or in
212 * compilation context "cctx".
213 * Return FAIL and give an error if it defined.
214 */
215 int
216check_defined(char_u *p, int len, cctx_T *cctx)
217{
218 if (lookup_script(p, len) == OK
219 || (cctx != NULL
220 && (lookup_local(p, len, cctx) >= 0
221 || find_imported(p, len, cctx) != NULL)))
222 {
223 semsg("E1073: imported name already defined: %s", p);
224 return FAIL;
225 }
226 return OK;
227}
228
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200229/*
230 * Allocate memory for a type_T and add the pointer to type_gap, so that it can
231 * be freed later.
232 */
233 static type_T *
234alloc_type(garray_T *type_gap)
235{
236 type_T *type;
237
238 if (ga_grow(type_gap, 1) == FAIL)
239 return NULL;
240 type = ALLOC_CLEAR_ONE(type_T);
241 if (type != NULL)
242 {
243 ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type;
244 ++type_gap->ga_len;
245 }
246 return type;
247}
248
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100249 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200250get_list_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100251{
252 type_T *type;
253
254 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200255 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100256 return &t_list_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200257 if (member_type->tt_type == VAR_VOID
258 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100259 return &t_list_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100260 if (member_type->tt_type == VAR_BOOL)
261 return &t_list_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100262 if (member_type->tt_type == VAR_NUMBER)
263 return &t_list_number;
264 if (member_type->tt_type == VAR_STRING)
265 return &t_list_string;
266
267 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200268 type = alloc_type(type_gap);
269 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100270 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100271 type->tt_type = VAR_LIST;
272 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200273 type->tt_argcount = 0;
274 type->tt_args = NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100275 return type;
276}
277
278 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +0200279get_dict_type(type_T *member_type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100280{
281 type_T *type;
282
283 // recognize commonly used types
Bram Moolenaar4c683752020-04-05 21:38:23 +0200284 if (member_type->tt_type == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100285 return &t_dict_any;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200286 if (member_type->tt_type == VAR_VOID
287 || member_type->tt_type == VAR_UNKNOWN)
Bram Moolenaar436472f2020-02-20 22:54:43 +0100288 return &t_dict_empty;
Bram Moolenaar0c2ca582020-02-25 22:58:29 +0100289 if (member_type->tt_type == VAR_BOOL)
290 return &t_dict_bool;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100291 if (member_type->tt_type == VAR_NUMBER)
292 return &t_dict_number;
293 if (member_type->tt_type == VAR_STRING)
294 return &t_dict_string;
295
296 // Not a common type, create a new entry.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200297 type = alloc_type(type_gap);
298 if (type == NULL)
Bram Moolenaar599c89c2020-03-28 14:53:20 +0100299 return &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100300 type->tt_type = VAR_DICT;
301 type->tt_member = member_type;
Bram Moolenaard77a8522020-04-03 21:59:57 +0200302 type->tt_argcount = 0;
303 type->tt_args = NULL;
304 return type;
305}
306
307/*
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200308 * Allocate a new type for a function.
309 */
310 static type_T *
311alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
312{
313 type_T *type = alloc_type(type_gap);
314
315 if (type == NULL)
316 return &t_any;
317 type->tt_type = VAR_FUNC;
318 type->tt_member = ret_type;
319 type->tt_argcount = argcount;
320 type->tt_args = NULL;
321 return type;
322}
323
324/*
Bram Moolenaard77a8522020-04-03 21:59:57 +0200325 * Get a function type, based on the return type "ret_type".
326 * If "argcount" is -1 or 0 a predefined type can be used.
327 * If "argcount" > 0 always create a new type, so that arguments can be added.
328 */
329 static type_T *
330get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
331{
Bram Moolenaard77a8522020-04-03 21:59:57 +0200332 // recognize commonly used types
333 if (argcount <= 0)
334 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +0200335 if (ret_type == &t_unknown)
336 {
337 // (argcount == 0) is not possible
338 return &t_func_unknown;
339 }
Bram Moolenaard77a8522020-04-03 21:59:57 +0200340 if (ret_type == &t_void)
341 {
342 if (argcount == 0)
343 return &t_func_0_void;
344 else
345 return &t_func_void;
346 }
347 if (ret_type == &t_any)
348 {
349 if (argcount == 0)
350 return &t_func_0_any;
351 else
352 return &t_func_any;
353 }
354 if (ret_type == &t_number)
355 {
356 if (argcount == 0)
357 return &t_func_0_number;
358 else
359 return &t_func_number;
360 }
361 if (ret_type == &t_string)
362 {
363 if (argcount == 0)
364 return &t_func_0_string;
365 else
366 return &t_func_string;
367 }
368 }
369
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200370 return alloc_func_type(ret_type, argcount, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100371}
372
Bram Moolenaara8c17702020-04-01 21:17:24 +0200373/*
Bram Moolenaar5d905c22020-04-05 18:20:45 +0200374 * For a function type, reserve space for "argcount" argument types (including
375 * vararg).
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200376 */
377 static int
378func_type_add_arg_types(
379 type_T *functype,
380 int argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200381 garray_T *type_gap)
382{
Bram Moolenaar1378fbc2020-04-11 20:50:33 +0200383 // To make it easy to free the space needed for the argument types, add the
384 // pointer to type_gap.
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200385 if (ga_grow(type_gap, 1) == FAIL)
386 return FAIL;
387 functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount);
388 if (functype->tt_args == NULL)
389 return FAIL;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +0200390 ((type_T **)type_gap->ga_data)[type_gap->ga_len] =
391 (void *)functype->tt_args;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200392 ++type_gap->ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200393 return OK;
394}
395
396/*
Bram Moolenaara8c17702020-04-01 21:17:24 +0200397 * Return the type_T for a typval. Only for primitive types.
398 */
399 static type_T *
400typval2type(typval_T *tv)
401{
402 if (tv->v_type == VAR_NUMBER)
403 return &t_number;
404 if (tv->v_type == VAR_BOOL)
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +0200405 return &t_bool; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200406 if (tv->v_type == VAR_STRING)
407 return &t_string;
408 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
409 return &t_list_string;
410 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
411 return &t_dict_any;
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200412 return &t_any; // not used
Bram Moolenaara8c17702020-04-01 21:17:24 +0200413}
414
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100415/////////////////////////////////////////////////////////////////////
416// Following generate_ functions expect the caller to call ga_grow().
417
Bram Moolenaar080457c2020-03-03 21:53:32 +0100418#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return NULL
419#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == TRUE) return OK
420
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100421/*
422 * Generate an instruction without arguments.
423 * Returns a pointer to the new instruction, NULL if failed.
424 */
425 static isn_T *
426generate_instr(cctx_T *cctx, isntype_T isn_type)
427{
428 garray_T *instr = &cctx->ctx_instr;
429 isn_T *isn;
430
Bram Moolenaar080457c2020-03-03 21:53:32 +0100431 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100432 if (ga_grow(instr, 1) == FAIL)
433 return NULL;
434 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
435 isn->isn_type = isn_type;
436 isn->isn_lnum = cctx->ctx_lnum + 1;
437 ++instr->ga_len;
438
439 return isn;
440}
441
442/*
443 * Generate an instruction without arguments.
444 * "drop" will be removed from the stack.
445 * Returns a pointer to the new instruction, NULL if failed.
446 */
447 static isn_T *
448generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
449{
450 garray_T *stack = &cctx->ctx_type_stack;
451
Bram Moolenaar080457c2020-03-03 21:53:32 +0100452 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100453 stack->ga_len -= drop;
454 return generate_instr(cctx, isn_type);
455}
456
457/*
458 * Generate instruction "isn_type" and put "type" on the type stack.
459 */
460 static isn_T *
461generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
462{
463 isn_T *isn;
464 garray_T *stack = &cctx->ctx_type_stack;
465
466 if ((isn = generate_instr(cctx, isn_type)) == NULL)
467 return NULL;
468
469 if (ga_grow(stack, 1) == FAIL)
470 return NULL;
471 ((type_T **)stack->ga_data)[stack->ga_len] = type;
472 ++stack->ga_len;
473
474 return isn;
475}
476
477/*
478 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
479 */
480 static int
481may_generate_2STRING(int offset, cctx_T *cctx)
482{
483 isn_T *isn;
484 garray_T *stack = &cctx->ctx_type_stack;
485 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
486
487 if ((*type)->tt_type == VAR_STRING)
488 return OK;
489 *type = &t_string;
490
491 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL)
492 return FAIL;
493 isn->isn_arg.number = offset;
494
495 return OK;
496}
497
498 static int
499check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
500{
Bram Moolenaar4c683752020-04-05 21:38:23 +0200501 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100502 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar4c683752020-04-05 21:38:23 +0200503 || type2 == VAR_ANY)))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100504 {
505 if (*op == '+')
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100506 emsg(_("E1035: wrong argument type for +"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100507 else
508 semsg(_("E1036: %c requires number or float arguments"), *op);
509 return FAIL;
510 }
511 return OK;
512}
513
514/*
515 * Generate an instruction with two arguments. The instruction depends on the
516 * type of the arguments.
517 */
518 static int
519generate_two_op(cctx_T *cctx, char_u *op)
520{
521 garray_T *stack = &cctx->ctx_type_stack;
522 type_T *type1;
523 type_T *type2;
524 vartype_T vartype;
525 isn_T *isn;
526
Bram Moolenaar080457c2020-03-03 21:53:32 +0100527 RETURN_OK_IF_SKIP(cctx);
528
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100529 // Get the known type of the two items on the stack. If they are matching
530 // use a type-specific instruction. Otherwise fall back to runtime type
531 // checking.
532 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
533 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar4c683752020-04-05 21:38:23 +0200534 vartype = VAR_ANY;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100535 if (type1->tt_type == type2->tt_type
536 && (type1->tt_type == VAR_NUMBER
537 || type1->tt_type == VAR_LIST
538#ifdef FEAT_FLOAT
539 || type1->tt_type == VAR_FLOAT
540#endif
541 || type1->tt_type == VAR_BLOB))
542 vartype = type1->tt_type;
543
544 switch (*op)
545 {
546 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB
Bram Moolenaar4c683752020-04-05 21:38:23 +0200547 && type1->tt_type != VAR_ANY
548 && type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100549 && check_number_or_float(
550 type1->tt_type, type2->tt_type, op) == FAIL)
551 return FAIL;
552 isn = generate_instr_drop(cctx,
553 vartype == VAR_NUMBER ? ISN_OPNR
554 : vartype == VAR_LIST ? ISN_ADDLIST
555 : vartype == VAR_BLOB ? ISN_ADDBLOB
556#ifdef FEAT_FLOAT
557 : vartype == VAR_FLOAT ? ISN_OPFLOAT
558#endif
559 : ISN_OPANY, 1);
560 if (isn != NULL)
561 isn->isn_arg.op.op_type = EXPR_ADD;
562 break;
563
564 case '-':
565 case '*':
566 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
567 op) == FAIL)
568 return FAIL;
569 if (vartype == VAR_NUMBER)
570 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
571#ifdef FEAT_FLOAT
572 else if (vartype == VAR_FLOAT)
573 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
574#endif
575 else
576 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
577 if (isn != NULL)
578 isn->isn_arg.op.op_type = *op == '*'
579 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
580 break;
581
Bram Moolenaar4c683752020-04-05 21:38:23 +0200582 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100583 && type1->tt_type != VAR_NUMBER)
Bram Moolenaar4c683752020-04-05 21:38:23 +0200584 || (type2->tt_type != VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100585 && type2->tt_type != VAR_NUMBER))
586 {
587 emsg(_("E1035: % requires number arguments"));
588 return FAIL;
589 }
590 isn = generate_instr_drop(cctx,
591 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
592 if (isn != NULL)
593 isn->isn_arg.op.op_type = EXPR_REM;
594 break;
595 }
596
597 // correct type of result
Bram Moolenaar4c683752020-04-05 21:38:23 +0200598 if (vartype == VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100599 {
600 type_T *type = &t_any;
601
602#ifdef FEAT_FLOAT
603 // float+number and number+float results in float
604 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
605 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
606 type = &t_float;
607#endif
608 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
609 }
610
611 return OK;
612}
613
614/*
615 * Generate an ISN_COMPARE* instruction with a boolean result.
616 */
617 static int
618generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic)
619{
620 isntype_T isntype = ISN_DROP;
621 isn_T *isn;
622 garray_T *stack = &cctx->ctx_type_stack;
623 vartype_T type1;
624 vartype_T type2;
625
Bram Moolenaar080457c2020-03-03 21:53:32 +0100626 RETURN_OK_IF_SKIP(cctx);
627
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100628 // Get the known type of the two items on the stack. If they are matching
629 // use a type-specific instruction. Otherwise fall back to runtime type
630 // checking.
631 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
632 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
Bram Moolenaar4c683752020-04-05 21:38:23 +0200633 if (type1 == VAR_UNKNOWN)
634 type1 = VAR_ANY;
635 if (type2 == VAR_UNKNOWN)
636 type2 = VAR_ANY;
637
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100638 if (type1 == type2)
639 {
640 switch (type1)
641 {
642 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
643 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
644 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
645 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
646 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
647 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
648 case VAR_LIST: isntype = ISN_COMPARELIST; break;
649 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
650 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100651 default: isntype = ISN_COMPAREANY; break;
652 }
653 }
Bram Moolenaar4c683752020-04-05 21:38:23 +0200654 else if (type1 == VAR_ANY || type2 == VAR_ANY
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100655 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
656 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT)))
657 isntype = ISN_COMPAREANY;
658
659 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT)
660 && (isntype == ISN_COMPAREBOOL
661 || isntype == ISN_COMPARESPECIAL
662 || isntype == ISN_COMPARENR
663 || isntype == ISN_COMPAREFLOAT))
664 {
665 semsg(_("E1037: Cannot use \"%s\" with %s"),
666 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
667 return FAIL;
668 }
669 if (isntype == ISN_DROP
670 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
671 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
672 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
673 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL
674 && exptype != EXPR_IS && exptype != EXPR_ISNOT
675 && (type1 == VAR_BLOB || type2 == VAR_BLOB
676 || type1 == VAR_LIST || type2 == VAR_LIST))))
677 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +0100678 semsg(_("E1072: Cannot compare %s with %s"),
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100679 vartype_name(type1), vartype_name(type2));
680 return FAIL;
681 }
682
683 if ((isn = generate_instr(cctx, isntype)) == NULL)
684 return FAIL;
685 isn->isn_arg.op.op_type = exptype;
686 isn->isn_arg.op.op_ic = ic;
687
688 // takes two arguments, puts one bool back
689 if (stack->ga_len >= 2)
690 {
691 --stack->ga_len;
692 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
693 }
694
695 return OK;
696}
697
698/*
699 * Generate an ISN_2BOOL instruction.
700 */
701 static int
702generate_2BOOL(cctx_T *cctx, int invert)
703{
704 isn_T *isn;
705 garray_T *stack = &cctx->ctx_type_stack;
706
Bram Moolenaar080457c2020-03-03 21:53:32 +0100707 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100708 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
709 return FAIL;
710 isn->isn_arg.number = invert;
711
712 // type becomes bool
713 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
714
715 return OK;
716}
717
718 static int
719generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset)
720{
721 isn_T *isn;
722 garray_T *stack = &cctx->ctx_type_stack;
723
Bram Moolenaar080457c2020-03-03 21:53:32 +0100724 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100725 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
726 return FAIL;
727 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type
728 isn->isn_arg.type.ct_off = offset;
729
730 // type becomes vartype
731 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
732
733 return OK;
734}
735
736/*
737 * Generate an ISN_PUSHNR instruction.
738 */
739 static int
740generate_PUSHNR(cctx_T *cctx, varnumber_T number)
741{
742 isn_T *isn;
743
Bram Moolenaar080457c2020-03-03 21:53:32 +0100744 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100745 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
746 return FAIL;
747 isn->isn_arg.number = number;
748
749 return OK;
750}
751
752/*
753 * Generate an ISN_PUSHBOOL instruction.
754 */
755 static int
756generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
757{
758 isn_T *isn;
759
Bram Moolenaar080457c2020-03-03 21:53:32 +0100760 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100761 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
762 return FAIL;
763 isn->isn_arg.number = number;
764
765 return OK;
766}
767
768/*
769 * Generate an ISN_PUSHSPEC instruction.
770 */
771 static int
772generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
773{
774 isn_T *isn;
775
Bram Moolenaar080457c2020-03-03 21:53:32 +0100776 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100777 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
778 return FAIL;
779 isn->isn_arg.number = number;
780
781 return OK;
782}
783
784#ifdef FEAT_FLOAT
785/*
786 * Generate an ISN_PUSHF instruction.
787 */
788 static int
789generate_PUSHF(cctx_T *cctx, float_T fnumber)
790{
791 isn_T *isn;
792
Bram Moolenaar080457c2020-03-03 21:53:32 +0100793 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100794 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
795 return FAIL;
796 isn->isn_arg.fnumber = fnumber;
797
798 return OK;
799}
800#endif
801
802/*
803 * Generate an ISN_PUSHS instruction.
804 * Consumes "str".
805 */
806 static int
807generate_PUSHS(cctx_T *cctx, char_u *str)
808{
809 isn_T *isn;
810
Bram Moolenaar080457c2020-03-03 21:53:32 +0100811 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100812 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
813 return FAIL;
814 isn->isn_arg.string = str;
815
816 return OK;
817}
818
819/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100820 * Generate an ISN_PUSHCHANNEL instruction.
821 * Consumes "channel".
822 */
823 static int
824generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
825{
826 isn_T *isn;
827
Bram Moolenaar080457c2020-03-03 21:53:32 +0100828 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100829 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
830 return FAIL;
831 isn->isn_arg.channel = channel;
832
833 return OK;
834}
835
836/*
837 * Generate an ISN_PUSHJOB instruction.
838 * Consumes "job".
839 */
840 static int
841generate_PUSHJOB(cctx_T *cctx, job_T *job)
842{
843 isn_T *isn;
844
Bram Moolenaar080457c2020-03-03 21:53:32 +0100845 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100846 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100847 return FAIL;
848 isn->isn_arg.job = job;
849
850 return OK;
851}
852
853/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100854 * Generate an ISN_PUSHBLOB instruction.
855 * Consumes "blob".
856 */
857 static int
858generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
859{
860 isn_T *isn;
861
Bram Moolenaar080457c2020-03-03 21:53:32 +0100862 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100863 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
864 return FAIL;
865 isn->isn_arg.blob = blob;
866
867 return OK;
868}
869
870/*
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100871 * Generate an ISN_PUSHFUNC instruction with name "name".
872 * Consumes "name".
873 */
874 static int
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200875generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100876{
877 isn_T *isn;
878
Bram Moolenaar080457c2020-03-03 21:53:32 +0100879 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200880 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
Bram Moolenaar42a480b2020-02-29 23:23:47 +0100881 return FAIL;
882 isn->isn_arg.string = name;
883
884 return OK;
885}
886
887/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100888 * Generate an ISN_STORE instruction.
889 */
890 static int
891generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
892{
893 isn_T *isn;
894
Bram Moolenaar080457c2020-03-03 21:53:32 +0100895 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100896 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
897 return FAIL;
898 if (name != NULL)
899 isn->isn_arg.string = vim_strsave(name);
900 else
901 isn->isn_arg.number = idx;
902
903 return OK;
904}
905
906/*
907 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
908 */
909 static int
910generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
911{
912 isn_T *isn;
913
Bram Moolenaar080457c2020-03-03 21:53:32 +0100914 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100915 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
916 return FAIL;
Bram Moolenaara471eea2020-03-04 22:20:26 +0100917 isn->isn_arg.storenr.stnr_idx = idx;
918 isn->isn_arg.storenr.stnr_val = value;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100919
920 return OK;
921}
922
923/*
924 * Generate an ISN_STOREOPT instruction
925 */
926 static int
927generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags)
928{
929 isn_T *isn;
930
Bram Moolenaar080457c2020-03-03 21:53:32 +0100931 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100932 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL)
933 return FAIL;
934 isn->isn_arg.storeopt.so_name = vim_strsave(name);
935 isn->isn_arg.storeopt.so_flags = opt_flags;
936
937 return OK;
938}
939
940/*
941 * Generate an ISN_LOAD or similar instruction.
942 */
943 static int
944generate_LOAD(
945 cctx_T *cctx,
946 isntype_T isn_type,
947 int idx,
948 char_u *name,
949 type_T *type)
950{
951 isn_T *isn;
952
Bram Moolenaar080457c2020-03-03 21:53:32 +0100953 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100954 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
955 return FAIL;
956 if (name != NULL)
957 isn->isn_arg.string = vim_strsave(name);
958 else
959 isn->isn_arg.number = idx;
960
961 return OK;
962}
963
964/*
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200965 * Generate an ISN_LOADV instruction for v:var.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100966 */
967 static int
968generate_LOADV(
969 cctx_T *cctx,
970 char_u *name,
971 int error)
972{
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200973 int di_flags;
974 int vidx = find_vim_var(name, &di_flags);
975 type_T *type;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100976
Bram Moolenaar080457c2020-03-03 21:53:32 +0100977 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100978 if (vidx < 0)
979 {
980 if (error)
981 semsg(_(e_var_notfound), name);
982 return FAIL;
983 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200984 type = typval2type(get_vim_var_tv(vidx));
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100985
Bram Moolenaar5da356e2020-04-09 19:34:43 +0200986 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100987}
988
989/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200990 * Generate an ISN_UNLET instruction.
991 */
992 static int
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200993generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200994{
995 isn_T *isn;
996
997 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200998 if ((isn = generate_instr(cctx, isn_type)) == NULL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200999 return FAIL;
1000 isn->isn_arg.unlet.ul_name = vim_strsave(name);
1001 isn->isn_arg.unlet.ul_forceit = forceit;
1002
1003 return OK;
1004}
1005
1006/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001007 * Generate an ISN_LOADS instruction.
1008 */
1009 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001010generate_OLDSCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001011 cctx_T *cctx,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001012 isntype_T isn_type,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001013 char_u *name,
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001014 int sid,
1015 type_T *type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001016{
1017 isn_T *isn;
1018
Bram Moolenaar080457c2020-03-03 21:53:32 +01001019 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001020 if (isn_type == ISN_LOADS)
1021 isn = generate_instr_type(cctx, isn_type, type);
1022 else
1023 isn = generate_instr_drop(cctx, isn_type, 1);
1024 if (isn == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001025 return FAIL;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001026 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1027 isn->isn_arg.loadstore.ls_sid = sid;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001028
1029 return OK;
1030}
1031
1032/*
1033 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1034 */
1035 static int
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01001036generate_VIM9SCRIPT(
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001037 cctx_T *cctx,
1038 isntype_T isn_type,
1039 int sid,
1040 int idx,
1041 type_T *type)
1042{
1043 isn_T *isn;
1044
Bram Moolenaar080457c2020-03-03 21:53:32 +01001045 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001046 if (isn_type == ISN_LOADSCRIPT)
1047 isn = generate_instr_type(cctx, isn_type, type);
1048 else
1049 isn = generate_instr_drop(cctx, isn_type, 1);
1050 if (isn == NULL)
1051 return FAIL;
1052 isn->isn_arg.script.script_sid = sid;
1053 isn->isn_arg.script.script_idx = idx;
1054 return OK;
1055}
1056
1057/*
1058 * Generate an ISN_NEWLIST instruction.
1059 */
1060 static int
1061generate_NEWLIST(cctx_T *cctx, int count)
1062{
1063 isn_T *isn;
1064 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001065 type_T *type;
1066 type_T *member;
1067
Bram Moolenaar080457c2020-03-03 21:53:32 +01001068 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001069 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1070 return FAIL;
1071 isn->isn_arg.number = count;
1072
1073 // drop the value types
1074 stack->ga_len -= count;
1075
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001076 // Use the first value type for the list member type. Use "any" for an
Bram Moolenaar436472f2020-02-20 22:54:43 +01001077 // empty list.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001078 if (count > 0)
1079 member = ((type_T **)stack->ga_data)[stack->ga_len];
1080 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001081 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001082 type = get_list_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001083
1084 // add the list type to the type stack
1085 if (ga_grow(stack, 1) == FAIL)
1086 return FAIL;
1087 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1088 ++stack->ga_len;
1089
1090 return OK;
1091}
1092
1093/*
1094 * Generate an ISN_NEWDICT instruction.
1095 */
1096 static int
1097generate_NEWDICT(cctx_T *cctx, int count)
1098{
1099 isn_T *isn;
1100 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001101 type_T *type;
1102 type_T *member;
1103
Bram Moolenaar080457c2020-03-03 21:53:32 +01001104 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001105 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1106 return FAIL;
1107 isn->isn_arg.number = count;
1108
1109 // drop the key and value types
1110 stack->ga_len -= 2 * count;
1111
Bram Moolenaar436472f2020-02-20 22:54:43 +01001112 // Use the first value type for the list member type. Use "void" for an
1113 // empty dict.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001114 if (count > 0)
1115 member = ((type_T **)stack->ga_data)[stack->ga_len + 1];
1116 else
Bram Moolenaar436472f2020-02-20 22:54:43 +01001117 member = &t_void;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001118 type = get_dict_type(member, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001119
1120 // add the dict type to the type stack
1121 if (ga_grow(stack, 1) == FAIL)
1122 return FAIL;
1123 ((type_T **)stack->ga_data)[stack->ga_len] = type;
1124 ++stack->ga_len;
1125
1126 return OK;
1127}
1128
1129/*
1130 * Generate an ISN_FUNCREF instruction.
1131 */
1132 static int
1133generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
1134{
1135 isn_T *isn;
1136 garray_T *stack = &cctx->ctx_type_stack;
1137
Bram Moolenaar080457c2020-03-03 21:53:32 +01001138 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001139 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1140 return FAIL;
1141 isn->isn_arg.number = dfunc_idx;
1142
1143 if (ga_grow(stack, 1) == FAIL)
1144 return FAIL;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001145 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001146 // TODO: argument and return types
1147 ++stack->ga_len;
1148
1149 return OK;
1150}
1151
1152/*
1153 * Generate an ISN_JUMP instruction.
1154 */
1155 static int
1156generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1157{
1158 isn_T *isn;
1159 garray_T *stack = &cctx->ctx_type_stack;
1160
Bram Moolenaar080457c2020-03-03 21:53:32 +01001161 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001162 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1163 return FAIL;
1164 isn->isn_arg.jump.jump_when = when;
1165 isn->isn_arg.jump.jump_where = where;
1166
1167 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1168 --stack->ga_len;
1169
1170 return OK;
1171}
1172
1173 static int
1174generate_FOR(cctx_T *cctx, int loop_idx)
1175{
1176 isn_T *isn;
1177 garray_T *stack = &cctx->ctx_type_stack;
1178
Bram Moolenaar080457c2020-03-03 21:53:32 +01001179 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001180 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1181 return FAIL;
1182 isn->isn_arg.forloop.for_idx = loop_idx;
1183
1184 if (ga_grow(stack, 1) == FAIL)
1185 return FAIL;
1186 // type doesn't matter, will be stored next
1187 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1188 ++stack->ga_len;
1189
1190 return OK;
1191}
1192
1193/*
1194 * Generate an ISN_BCALL instruction.
1195 * Return FAIL if the number of arguments is wrong.
1196 */
1197 static int
1198generate_BCALL(cctx_T *cctx, int func_idx, int argcount)
1199{
1200 isn_T *isn;
1201 garray_T *stack = &cctx->ctx_type_stack;
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001202 type_T *argtypes[MAX_FUNC_ARGS];
1203 int i;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001204
Bram Moolenaar080457c2020-03-03 21:53:32 +01001205 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001206 if (check_internal_func(func_idx, argcount) == FAIL)
1207 return FAIL;
1208
1209 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1210 return FAIL;
1211 isn->isn_arg.bfunc.cbf_idx = func_idx;
1212 isn->isn_arg.bfunc.cbf_argcount = argcount;
1213
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001214 for (i = 0; i < argcount; ++i)
1215 argtypes[i] = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1216
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001217 stack->ga_len -= argcount; // drop the arguments
1218 if (ga_grow(stack, 1) == FAIL)
1219 return FAIL;
1220 ((type_T **)stack->ga_data)[stack->ga_len] =
Bram Moolenaarfbdd08e2020-03-01 14:04:46 +01001221 internal_func_ret_type(func_idx, argcount, argtypes);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001222 ++stack->ga_len; // add return value
1223
1224 return OK;
1225}
1226
1227/*
1228 * Generate an ISN_DCALL or ISN_UCALL instruction.
1229 * Return FAIL if the number of arguments is wrong.
1230 */
1231 static int
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001232generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001233{
1234 isn_T *isn;
1235 garray_T *stack = &cctx->ctx_type_stack;
1236 int regular_args = ufunc->uf_args.ga_len;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01001237 int argcount = pushed_argcount;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001238
Bram Moolenaar080457c2020-03-03 21:53:32 +01001239 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001240 if (argcount > regular_args && !has_varargs(ufunc))
1241 {
1242 semsg(_(e_toomanyarg), ufunc->uf_name);
1243 return FAIL;
1244 }
1245 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1246 {
1247 semsg(_(e_toofewarg), ufunc->uf_name);
1248 return FAIL;
1249 }
1250
Bram Moolenaar0b76b422020-04-07 22:05:08 +02001251 if (ufunc->uf_dfunc_idx >= 0)
1252 {
1253 int i;
1254
1255 for (i = 0; i < argcount; ++i)
1256 {
1257 type_T *expected;
1258 type_T *actual;
1259
1260 if (i < regular_args)
1261 {
1262 if (ufunc->uf_arg_types == NULL)
1263 continue;
1264 expected = ufunc->uf_arg_types[i];
1265 }
1266 else
1267 expected = ufunc->uf_va_type->tt_member;
1268 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
1269 if (check_type(expected, actual, FALSE) == FAIL)
1270 {
1271 arg_type_mismatch(expected, actual, i + 1);
1272 return FAIL;
1273 }
1274 }
1275 }
1276
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001277 if ((isn = generate_instr(cctx,
1278 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL)
1279 return FAIL;
1280 if (ufunc->uf_dfunc_idx >= 0)
1281 {
1282 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1283 isn->isn_arg.dfunc.cdf_argcount = argcount;
1284 }
1285 else
1286 {
1287 // A user function may be deleted and redefined later, can't use the
1288 // ufunc pointer, need to look it up again at runtime.
1289 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1290 isn->isn_arg.ufunc.cuf_argcount = argcount;
1291 }
1292
1293 stack->ga_len -= argcount; // drop the arguments
1294 if (ga_grow(stack, 1) == FAIL)
1295 return FAIL;
1296 // add return value
1297 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
1298 ++stack->ga_len;
1299
1300 return OK;
1301}
1302
1303/*
1304 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1305 */
1306 static int
1307generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1308{
1309 isn_T *isn;
1310 garray_T *stack = &cctx->ctx_type_stack;
1311
Bram Moolenaar080457c2020-03-03 21:53:32 +01001312 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001313 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1314 return FAIL;
1315 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1316 isn->isn_arg.ufunc.cuf_argcount = argcount;
1317
1318 stack->ga_len -= argcount; // drop the arguments
Bram Moolenaar26e117e2020-02-04 21:24:15 +01001319 if (ga_grow(stack, 1) == FAIL)
1320 return FAIL;
1321 // add return value
1322 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
1323 ++stack->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001324
1325 return OK;
1326}
1327
1328/*
1329 * Generate an ISN_PCALL instruction.
1330 */
1331 static int
1332generate_PCALL(cctx_T *cctx, int argcount, int at_top)
1333{
1334 isn_T *isn;
1335 garray_T *stack = &cctx->ctx_type_stack;
1336
Bram Moolenaar080457c2020-03-03 21:53:32 +01001337 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001338
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001339 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1340 return FAIL;
1341 isn->isn_arg.pfunc.cpf_top = at_top;
1342 isn->isn_arg.pfunc.cpf_argcount = argcount;
1343
1344 stack->ga_len -= argcount; // drop the arguments
1345
1346 // drop the funcref/partial, get back the return value
1347 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
1348
Bram Moolenaarbd5da372020-03-31 23:13:10 +02001349 // If partial is above the arguments it must be cleared and replaced with
1350 // the return value.
1351 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1352 return FAIL;
1353
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001354 return OK;
1355}
1356
1357/*
1358 * Generate an ISN_MEMBER instruction.
1359 */
1360 static int
1361generate_MEMBER(cctx_T *cctx, char_u *name, size_t len)
1362{
1363 isn_T *isn;
1364 garray_T *stack = &cctx->ctx_type_stack;
1365 type_T *type;
1366
Bram Moolenaar080457c2020-03-03 21:53:32 +01001367 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001368 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL)
1369 return FAIL;
1370 isn->isn_arg.string = vim_strnsave(name, (int)len);
1371
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001372 // check for dict type
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001373 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01001374 if (type->tt_type != VAR_DICT && type != &t_any)
1375 {
1376 emsg(_(e_dictreq));
1377 return FAIL;
1378 }
1379 // change dict type to dict member type
1380 if (type->tt_type == VAR_DICT)
1381 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001382
1383 return OK;
1384}
1385
1386/*
1387 * Generate an ISN_ECHO instruction.
1388 */
1389 static int
1390generate_ECHO(cctx_T *cctx, int with_white, int count)
1391{
1392 isn_T *isn;
1393
Bram Moolenaar080457c2020-03-03 21:53:32 +01001394 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001395 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1396 return FAIL;
1397 isn->isn_arg.echo.echo_with_white = with_white;
1398 isn->isn_arg.echo.echo_count = count;
1399
1400 return OK;
1401}
1402
Bram Moolenaarad39c092020-02-26 18:23:43 +01001403/*
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001404 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
Bram Moolenaarad39c092020-02-26 18:23:43 +01001405 */
1406 static int
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001407generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001408{
1409 isn_T *isn;
1410
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001411 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001412 return FAIL;
1413 isn->isn_arg.number = count;
1414
1415 return OK;
1416}
1417
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001418 static int
1419generate_EXEC(cctx_T *cctx, char_u *line)
1420{
1421 isn_T *isn;
1422
Bram Moolenaar080457c2020-03-03 21:53:32 +01001423 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001424 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
1425 return FAIL;
1426 isn->isn_arg.string = vim_strsave(line);
1427 return OK;
1428}
1429
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02001430 static int
1431generate_EXECCONCAT(cctx_T *cctx, int count)
1432{
1433 isn_T *isn;
1434
1435 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1436 return FAIL;
1437 isn->isn_arg.number = count;
1438 return OK;
1439}
1440
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001441/*
1442 * Reserve space for a local variable.
1443 * Return the index or -1 if it failed.
1444 */
1445 static int
1446reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
1447{
1448 int idx;
1449 lvar_T *lvar;
1450
1451 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
1452 {
1453 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
1454 return -1;
1455 }
1456
1457 if (ga_grow(&cctx->ctx_locals, 1) == FAIL)
1458 return -1;
1459 idx = cctx->ctx_locals.ga_len;
1460 if (cctx->ctx_max_local < idx + 1)
1461 cctx->ctx_max_local = idx + 1;
1462 ++cctx->ctx_locals.ga_len;
1463
1464 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1465 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len));
1466 lvar->lv_const = isConst;
1467 lvar->lv_type = type;
1468
1469 return idx;
1470}
1471
1472/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01001473 * Remove local variables above "new_top".
1474 */
1475 static void
1476unwind_locals(cctx_T *cctx, int new_top)
1477{
1478 if (cctx->ctx_locals.ga_len > new_top)
1479 {
1480 int idx;
1481 lvar_T *lvar;
1482
1483 for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
1484 {
1485 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
1486 vim_free(lvar->lv_name);
1487 }
1488 }
1489 cctx->ctx_locals.ga_len = new_top;
1490}
1491
1492/*
1493 * Free all local variables.
1494 */
1495 static void
1496free_local(cctx_T *cctx)
1497{
1498 unwind_locals(cctx, 0);
1499 ga_clear(&cctx->ctx_locals);
1500}
1501
1502/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001503 * Skip over a type definition and return a pointer to just after it.
1504 */
1505 char_u *
1506skip_type(char_u *start)
1507{
1508 char_u *p = start;
1509
1510 while (ASCII_ISALNUM(*p) || *p == '_')
1511 ++p;
1512
1513 // Skip over "<type>"; this is permissive about white space.
1514 if (*skipwhite(p) == '<')
1515 {
1516 p = skipwhite(p);
1517 p = skip_type(skipwhite(p + 1));
1518 p = skipwhite(p);
1519 if (*p == '>')
1520 ++p;
1521 }
1522 return p;
1523}
1524
1525/*
1526 * Parse the member type: "<type>" and return "type" with the member set.
Bram Moolenaard77a8522020-04-03 21:59:57 +02001527 * Use "type_gap" if a new type needs to be added.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001528 * Returns NULL in case of failure.
1529 */
1530 static type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001531parse_type_member(char_u **arg, type_T *type, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001532{
1533 type_T *member_type;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001534 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001535
1536 if (**arg != '<')
1537 {
1538 if (*skipwhite(*arg) == '<')
Bram Moolenaard77a8522020-04-03 21:59:57 +02001539 semsg(_(e_no_white_before), "<");
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001540 else
1541 emsg(_("E1008: Missing <type>"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001542 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001543 }
1544 *arg = skipwhite(*arg + 1);
1545
Bram Moolenaard77a8522020-04-03 21:59:57 +02001546 member_type = parse_type(arg, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001547
1548 *arg = skipwhite(*arg);
Bram Moolenaar599c89c2020-03-28 14:53:20 +01001549 if (**arg != '>' && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001550 {
1551 emsg(_("E1009: Missing > after type"));
Bram Moolenaarcf3f8bf2020-03-26 13:15:42 +01001552 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001553 }
1554 ++*arg;
1555
1556 if (type->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001557 return get_list_type(member_type, type_gap);
1558 return get_dict_type(member_type, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001559}
1560
1561/*
1562 * Parse a type at "arg" and advance over it.
Bram Moolenaara8c17702020-04-01 21:17:24 +02001563 * Return &t_any for failure.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001564 */
1565 type_T *
Bram Moolenaard77a8522020-04-03 21:59:57 +02001566parse_type(char_u **arg, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001567{
1568 char_u *p = *arg;
1569 size_t len;
1570
1571 // skip over the first word
1572 while (ASCII_ISALNUM(*p) || *p == '_')
1573 ++p;
1574 len = p - *arg;
1575
1576 switch (**arg)
1577 {
1578 case 'a':
1579 if (len == 3 && STRNCMP(*arg, "any", len) == 0)
1580 {
1581 *arg += len;
1582 return &t_any;
1583 }
1584 break;
1585 case 'b':
1586 if (len == 4 && STRNCMP(*arg, "bool", len) == 0)
1587 {
1588 *arg += len;
1589 return &t_bool;
1590 }
1591 if (len == 4 && STRNCMP(*arg, "blob", len) == 0)
1592 {
1593 *arg += len;
1594 return &t_blob;
1595 }
1596 break;
1597 case 'c':
1598 if (len == 7 && STRNCMP(*arg, "channel", len) == 0)
1599 {
1600 *arg += len;
1601 return &t_channel;
1602 }
1603 break;
1604 case 'd':
1605 if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
1606 {
1607 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001608 return parse_type_member(arg, &t_dict_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001609 }
1610 break;
1611 case 'f':
1612 if (len == 5 && STRNCMP(*arg, "float", len) == 0)
1613 {
Bram Moolenaara5d59532020-01-26 21:42:03 +01001614#ifdef FEAT_FLOAT
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001615 *arg += len;
1616 return &t_float;
Bram Moolenaara5d59532020-01-26 21:42:03 +01001617#else
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001618 emsg(_("E1076: This Vim is not compiled with float support"));
Bram Moolenaara5d59532020-01-26 21:42:03 +01001619 return &t_any;
1620#endif
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001621 }
1622 if (len == 4 && STRNCMP(*arg, "func", len) == 0)
1623 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001624 type_T *type;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001625 type_T *ret_type = &t_unknown;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001626 int argcount = -1;
1627 int flags = 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001628 int first_optional = -1;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001629 type_T *arg_type[MAX_FUNC_ARGS + 1];
1630
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001631 // func({type}, ...{type}): {type}
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001632 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001633 if (**arg == '(')
1634 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001635 // "func" may or may not return a value, "func()" does
1636 // not return a value.
1637 ret_type = &t_void;
1638
Bram Moolenaard77a8522020-04-03 21:59:57 +02001639 p = ++*arg;
1640 argcount = 0;
1641 while (*p != NUL && *p != ')')
1642 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001643 if (*p == '?')
1644 {
1645 if (first_optional == -1)
1646 first_optional = argcount;
1647 ++p;
1648 }
1649 else if (first_optional != -1)
1650 {
1651 emsg(_("E1007: mandatory argument after optional argument"));
1652 return &t_any;
1653 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001654 else if (STRNCMP(p, "...", 3) == 0)
1655 {
1656 flags |= TTFLAG_VARARGS;
1657 p += 3;
1658 }
1659
1660 arg_type[argcount++] = parse_type(&p, type_gap);
1661
1662 // Nothing comes after "...{type}".
1663 if (flags & TTFLAG_VARARGS)
1664 break;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001665
Bram Moolenaard77a8522020-04-03 21:59:57 +02001666 if (*p != ',' && *skipwhite(p) == ',')
1667 {
1668 semsg(_(e_no_white_before), ",");
1669 return &t_any;
1670 }
1671 if (*p == ',')
1672 {
1673 ++p;
1674 if (!VIM_ISWHITE(*p))
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001675 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02001676 semsg(_(e_white_after), ",");
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001677 return &t_any;
1678 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001679 }
1680 p = skipwhite(p);
1681 if (argcount == MAX_FUNC_ARGS)
1682 {
1683 emsg(_("E740: Too many argument types"));
1684 return &t_any;
1685 }
1686 }
1687
1688 p = skipwhite(p);
1689 if (*p != ')')
1690 {
1691 emsg(_(e_missing_close));
1692 return &t_any;
1693 }
1694 *arg = p + 1;
1695 }
1696 if (**arg == ':')
1697 {
1698 // parse return type
1699 ++*arg;
Bram Moolenaarec5929d2020-04-07 20:53:39 +02001700 if (!VIM_ISWHITE(**arg))
Bram Moolenaard77a8522020-04-03 21:59:57 +02001701 semsg(_(e_white_after), ":");
1702 *arg = skipwhite(*arg);
1703 ret_type = parse_type(arg, type_gap);
1704 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001705 if (flags == 0 && first_optional == -1 && argcount <= 0)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001706 type = get_func_type(ret_type, argcount, type_gap);
1707 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001708 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001709 type = alloc_func_type(ret_type, argcount, type_gap);
1710 type->tt_flags = flags;
1711 if (argcount > 0)
1712 {
1713 type->tt_argcount = argcount;
1714 type->tt_min_argcount = first_optional == -1
1715 ? argcount : first_optional;
1716 if (func_type_add_arg_types(type, argcount,
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001717 type_gap) == FAIL)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001718 return &t_any;
1719 mch_memmove(type->tt_args, arg_type,
Bram Moolenaard77a8522020-04-03 21:59:57 +02001720 sizeof(type_T *) * argcount);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001721 }
Bram Moolenaard77a8522020-04-03 21:59:57 +02001722 }
1723 return type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001724 }
1725 break;
1726 case 'j':
1727 if (len == 3 && STRNCMP(*arg, "job", len) == 0)
1728 {
1729 *arg += len;
1730 return &t_job;
1731 }
1732 break;
1733 case 'l':
1734 if (len == 4 && STRNCMP(*arg, "list", len) == 0)
1735 {
1736 *arg += len;
Bram Moolenaard77a8522020-04-03 21:59:57 +02001737 return parse_type_member(arg, &t_list_any, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001738 }
1739 break;
1740 case 'n':
1741 if (len == 6 && STRNCMP(*arg, "number", len) == 0)
1742 {
1743 *arg += len;
1744 return &t_number;
1745 }
1746 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001747 case 's':
1748 if (len == 6 && STRNCMP(*arg, "string", len) == 0)
1749 {
1750 *arg += len;
1751 return &t_string;
1752 }
1753 break;
1754 case 'v':
1755 if (len == 4 && STRNCMP(*arg, "void", len) == 0)
1756 {
1757 *arg += len;
1758 return &t_void;
1759 }
1760 break;
1761 }
1762
1763 semsg(_("E1010: Type not recognized: %s"), *arg);
1764 return &t_any;
1765}
1766
1767/*
1768 * Check if "type1" and "type2" are exactly the same.
1769 */
1770 static int
1771equal_type(type_T *type1, type_T *type2)
1772{
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001773 int i;
1774
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001775 if (type1->tt_type != type2->tt_type)
1776 return FALSE;
1777 switch (type1->tt_type)
1778 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001779 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02001780 case VAR_ANY:
1781 case VAR_VOID:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001782 case VAR_SPECIAL:
1783 case VAR_BOOL:
1784 case VAR_NUMBER:
1785 case VAR_FLOAT:
1786 case VAR_STRING:
1787 case VAR_BLOB:
1788 case VAR_JOB:
1789 case VAR_CHANNEL:
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001790 break; // not composite is always OK
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001791 case VAR_LIST:
1792 case VAR_DICT:
1793 return equal_type(type1->tt_member, type2->tt_member);
1794 case VAR_FUNC:
1795 case VAR_PARTIAL:
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001796 if (!equal_type(type1->tt_member, type2->tt_member)
1797 || type1->tt_argcount != type2->tt_argcount)
1798 return FALSE;
1799 if (type1->tt_argcount < 0
1800 || type1->tt_args == NULL || type2->tt_args == NULL)
1801 return TRUE;
1802 for (i = 0; i < type1->tt_argcount; ++i)
1803 if (!equal_type(type1->tt_args[i], type2->tt_args[i]))
1804 return FALSE;
1805 return TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001806 }
1807 return TRUE;
1808}
1809
1810/*
1811 * Find the common type of "type1" and "type2" and put it in "dest".
1812 * "type2" and "dest" may be the same.
1813 */
1814 static void
Bram Moolenaard77a8522020-04-03 21:59:57 +02001815common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001816{
1817 if (equal_type(type1, type2))
1818 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001819 *dest = type1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001820 return;
1821 }
1822
1823 if (type1->tt_type == type2->tt_type)
1824 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001825 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT)
1826 {
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001827 type_T *common;
1828
Bram Moolenaard77a8522020-04-03 21:59:57 +02001829 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001830 if (type1->tt_type == VAR_LIST)
Bram Moolenaard77a8522020-04-03 21:59:57 +02001831 *dest = get_list_type(common, type_gap);
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001832 else
Bram Moolenaard77a8522020-04-03 21:59:57 +02001833 *dest = get_dict_type(common, type_gap);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001834 return;
1835 }
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001836 if (type1->tt_type == VAR_FUNC)
1837 {
1838 type_T *common;
1839
1840 common_type(type1->tt_member, type2->tt_member, &common, type_gap);
1841 if (type1->tt_argcount == type2->tt_argcount
1842 && type1->tt_argcount >= 0)
1843 {
1844 int argcount = type1->tt_argcount;
1845 int i;
1846
1847 *dest = alloc_func_type(common, argcount, type_gap);
1848 if (type1->tt_args != NULL && type2->tt_args != NULL)
1849 {
Bram Moolenaarc5f1ef52020-04-12 17:11:27 +02001850 if (func_type_add_arg_types(*dest, argcount,
1851 type_gap) == OK)
Bram Moolenaar99aaf0c2020-04-12 14:39:53 +02001852 for (i = 0; i < argcount; ++i)
1853 common_type(type1->tt_args[i], type2->tt_args[i],
1854 &(*dest)->tt_args[i], type_gap);
1855 }
1856 }
1857 else
1858 *dest = alloc_func_type(common, -1, type_gap);
1859 return;
1860 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001861 }
1862
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001863 *dest = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001864}
1865
1866 char *
1867vartype_name(vartype_T type)
1868{
1869 switch (type)
1870 {
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01001871 case VAR_UNKNOWN: break;
Bram Moolenaar4c683752020-04-05 21:38:23 +02001872 case VAR_ANY: return "any";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001873 case VAR_VOID: return "void";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001874 case VAR_SPECIAL: return "special";
1875 case VAR_BOOL: return "bool";
1876 case VAR_NUMBER: return "number";
1877 case VAR_FLOAT: return "float";
1878 case VAR_STRING: return "string";
1879 case VAR_BLOB: return "blob";
1880 case VAR_JOB: return "job";
1881 case VAR_CHANNEL: return "channel";
1882 case VAR_LIST: return "list";
1883 case VAR_DICT: return "dict";
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001884
1885 case VAR_FUNC:
1886 case VAR_PARTIAL: return "func";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001887 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02001888 return "unknown";
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001889}
1890
1891/*
1892 * Return the name of a type.
1893 * The result may be in allocated memory, in which case "tofree" is set.
1894 */
1895 char *
1896type_name(type_T *type, char **tofree)
1897{
1898 char *name = vartype_name(type->tt_type);
1899
1900 *tofree = NULL;
1901 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT)
1902 {
1903 char *member_free;
1904 char *member_name = type_name(type->tt_member, &member_free);
1905 size_t len;
1906
1907 len = STRLEN(name) + STRLEN(member_name) + 3;
1908 *tofree = alloc(len);
1909 if (*tofree != NULL)
1910 {
1911 vim_snprintf(*tofree, len, "%s<%s>", name, member_name);
1912 vim_free(member_free);
1913 return *tofree;
1914 }
1915 }
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001916 if (type->tt_type == VAR_FUNC)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001917 {
1918 garray_T ga;
1919 int i;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001920 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001921
1922 ga_init2(&ga, 1, 100);
1923 if (ga_grow(&ga, 20) == FAIL)
1924 return "[unknown]";
1925 *tofree = ga.ga_data;
1926 STRCPY(ga.ga_data, "func(");
1927 ga.ga_len += 5;
1928
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001929 for (i = 0; i < type->tt_argcount; ++i)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001930 {
1931 char *arg_free;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001932 char *arg_type;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001933 int len;
1934
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001935 if (type->tt_args == NULL)
1936 arg_type = "[unknown]";
1937 else
1938 arg_type = type_name(type->tt_args[i], &arg_free);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001939 if (i > 0)
1940 {
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001941 STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001942 ga.ga_len += 2;
1943 }
1944 len = (int)STRLEN(arg_type);
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001945 if (ga_grow(&ga, len + 8) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001946 {
1947 vim_free(arg_free);
1948 return "[unknown]";
1949 }
1950 *tofree = ga.ga_data;
Bram Moolenaar08938ee2020-04-11 23:17:17 +02001951 if (varargs && i == type->tt_argcount - 1)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02001952 {
1953 STRCPY((char *)ga.ga_data + ga.ga_len, "...");
1954 ga.ga_len += 3;
1955 }
1956 else if (i >= type->tt_min_argcount)
1957 *((char *)ga.ga_data + ga.ga_len++) = '?';
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001958 STRCPY((char *)ga.ga_data + ga.ga_len, arg_type);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001959 ga.ga_len += len;
1960 vim_free(arg_free);
1961 }
1962
1963 if (type->tt_member == &t_void)
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001964 STRCPY((char *)ga.ga_data + ga.ga_len, ")");
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001965 else
1966 {
1967 char *ret_free;
1968 char *ret_name = type_name(type->tt_member, &ret_free);
1969 int len;
1970
1971 len = (int)STRLEN(ret_name) + 4;
1972 if (ga_grow(&ga, len) == FAIL)
1973 {
1974 vim_free(ret_free);
1975 return "[unknown]";
1976 }
1977 *tofree = ga.ga_data;
Bram Moolenaarb8ed3aa2020-04-05 19:09:05 +02001978 STRCPY((char *)ga.ga_data + ga.ga_len, "): ");
1979 STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02001980 vim_free(ret_free);
1981 }
1982 return ga.ga_data;
1983 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001984
1985 return name;
1986}
1987
1988/*
1989 * Find "name" in script-local items of script "sid".
1990 * Returns the index in "sn_var_vals" if found.
1991 * If found but not in "sn_var_vals" returns -1.
1992 * If not found returns -2.
1993 */
1994 int
1995get_script_item_idx(int sid, char_u *name, int check_writable)
1996{
1997 hashtab_T *ht;
1998 dictitem_T *di;
Bram Moolenaar21b9e972020-01-26 19:26:46 +01001999 scriptitem_T *si = SCRIPT_ITEM(sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002000 int idx;
2001
2002 // First look the name up in the hashtable.
2003 if (sid <= 0 || sid > script_items.ga_len)
2004 return -1;
2005 ht = &SCRIPT_VARS(sid);
2006 di = find_var_in_ht(ht, 0, name, TRUE);
2007 if (di == NULL)
2008 return -2;
2009
2010 // Now find the svar_T index in sn_var_vals.
2011 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
2012 {
2013 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2014
2015 if (sv->sv_tv == &di->di_tv)
2016 {
2017 if (check_writable && sv->sv_const)
2018 semsg(_(e_readonlyvar), name);
2019 return idx;
2020 }
2021 }
2022 return -1;
2023}
2024
2025/*
2026 * Find "name" in imported items of the current script/
2027 */
2028 imported_T *
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002029find_imported(char_u *name, size_t len, cctx_T *cctx)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002030{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002031 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002032 int idx;
2033
2034 if (cctx != NULL)
2035 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2036 {
2037 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data)
2038 + idx;
2039
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002040 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2041 : STRLEN(import->imp_name) == len
2042 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002043 return import;
2044 }
2045
2046 for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
2047 {
2048 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx;
2049
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002050 if (len == 0 ? STRCMP(name, import->imp_name) == 0
2051 : STRLEN(import->imp_name) == len
2052 && STRNCMP(name, import->imp_name, len) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002053 return import;
2054 }
2055 return NULL;
2056}
2057
2058/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01002059 * Free all imported variables.
2060 */
2061 static void
2062free_imported(cctx_T *cctx)
2063{
2064 int idx;
2065
2066 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
2067 {
2068 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
2069
2070 vim_free(import->imp_name);
2071 }
2072 ga_clear(&cctx->ctx_imports);
2073}
2074
2075/*
Bram Moolenaare6085c52020-04-12 20:19:16 +02002076 * Get the next line of the function from "cctx".
2077 * Returns NULL when at the end.
2078 */
2079 static char_u *
2080next_line_from_context(cctx_T *cctx)
2081{
Bram Moolenaar7a092242020-04-16 22:10:49 +02002082 char_u *line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002083
2084 do
2085 {
2086 ++cctx->ctx_lnum;
2087 if (cctx->ctx_lnum >= cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar7a092242020-04-16 22:10:49 +02002088 {
2089 line = NULL;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002090 break;
Bram Moolenaar7a092242020-04-16 22:10:49 +02002091 }
Bram Moolenaare6085c52020-04-12 20:19:16 +02002092 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum];
Bram Moolenaar7a092242020-04-16 22:10:49 +02002093 cctx->ctx_line_start = line;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002094 SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum
2095 + cctx->ctx_lnum + 1;
Bram Moolenaar675f7162020-04-12 22:53:54 +02002096 } while (line == NULL || *skipwhite(line) == NUL);
Bram Moolenaare6085c52020-04-12 20:19:16 +02002097 return line;
2098}
2099
2100/*
Bram Moolenaar2c330432020-04-13 14:41:35 +02002101 * Return TRUE if "p" points at a "#" but not at "#{".
2102 */
2103 static int
2104comment_start(char_u *p)
2105{
2106 return p[0] == '#' && p[1] != '{';
2107}
2108
2109/*
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002110 * If "*arg" is at the end of the line, advance to the next line.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002111 * Also when "whitep" points to white space and "*arg" is on a "#".
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002112 * Return FAIL if beyond the last line, "*arg" is unmodified then.
2113 */
2114 static int
Bram Moolenaar2c330432020-04-13 14:41:35 +02002115may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002116{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002117 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02002118 {
2119 char_u *next = next_line_from_context(cctx);
2120
2121 if (next == NULL)
2122 return FAIL;
2123 *arg = skipwhite(next);
2124 }
2125 return OK;
2126}
2127
2128/*
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002129 * Generate an instruction to load script-local variable "name", without the
2130 * leading "s:".
2131 * Also finds imported variables.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002132 */
2133 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002134compile_load_scriptvar(
2135 cctx_T *cctx,
2136 char_u *name, // variable NUL terminated
2137 char_u *start, // start of variable
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002138 char_u **end, // end of variable
2139 int error) // when TRUE may give error
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002140{
Bram Moolenaar21b9e972020-01-26 19:26:46 +01002141 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002142 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE);
2143 imported_T *import;
2144
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002145 if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002146 {
Bram Moolenaarfd1823e2020-02-19 20:23:11 +01002147 // variable is not in sn_var_vals: old style script.
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002148 return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
2149 &t_any);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002150 }
2151 if (idx >= 0)
2152 {
2153 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
2154
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002155 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002156 current_sctx.sc_sid, idx, sv->sv_type);
2157 return OK;
2158 }
2159
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01002160 import = find_imported(name, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002161 if (import != NULL)
2162 {
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002163 if (import->imp_all)
2164 {
2165 char_u *p = skipwhite(*end);
2166 int name_len;
2167 ufunc_T *ufunc;
2168 type_T *type;
2169
2170 // Used "import * as Name", need to lookup the member.
2171 if (*p != '.')
2172 {
2173 semsg(_("E1060: expected dot after name: %s"), start);
2174 return FAIL;
2175 }
2176 ++p;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002177 if (VIM_ISWHITE(*p))
2178 {
2179 emsg(_("E1074: no white space allowed after dot"));
2180 return FAIL;
2181 }
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002182
2183 idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
2184 // TODO: what if it is a function?
2185 if (idx < 0)
2186 return FAIL;
2187 *end = p;
2188
2189 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2190 import->imp_sid,
2191 idx,
2192 type);
2193 }
2194 else
2195 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002196 // TODO: check this is a variable, not a function?
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002197 generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
2198 import->imp_sid,
2199 import->imp_var_vals_idx,
2200 import->imp_type);
2201 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002202 return OK;
2203 }
2204
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002205 if (error)
2206 semsg(_("E1050: Item not found: %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002207 return FAIL;
2208}
2209
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002210 static int
2211generate_funcref(cctx_T *cctx, char_u *name)
2212{
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002213 ufunc_T *ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002214
2215 if (ufunc == NULL)
2216 return FAIL;
2217
2218 return generate_PUSHFUNC(cctx, vim_strsave(name), ufunc->uf_func_type);
2219}
2220
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002221/*
2222 * Compile a variable name into a load instruction.
2223 * "end" points to just after the name.
2224 * When "error" is FALSE do not give an error when not found.
2225 */
2226 static int
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002227compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002228{
2229 type_T *type;
2230 char_u *name;
Bram Moolenaarf2d5c242020-02-23 21:25:54 +01002231 char_u *end = end_arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002232 int res = FAIL;
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002233 int prev_called_emsg = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002234
2235 if (*(*arg + 1) == ':')
2236 {
2237 // load namespaced variable
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002238 if (end <= *arg + 2)
2239 name = vim_strsave((char_u *)"[empty]");
2240 else
2241 name = vim_strnsave(*arg + 2, end - (*arg + 2));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002242 if (name == NULL)
2243 return FAIL;
2244
2245 if (**arg == 'v')
2246 {
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01002247 res = generate_LOADV(cctx, name, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002248 }
2249 else if (**arg == 'g')
2250 {
2251 // Global variables can be defined later, thus we don't check if it
2252 // exists, give error at runtime.
2253 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
2254 }
2255 else if (**arg == 's')
2256 {
Bram Moolenaarb35efa52020-02-26 20:15:18 +01002257 res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002258 }
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002259 else if (**arg == 'b')
2260 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002261 // Buffer-local variables can be defined later, thus we don't check
2262 // if it exists, give error at runtime.
2263 res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002264 }
2265 else if (**arg == 'w')
2266 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002267 // Window-local variables can be defined later, thus we don't check
2268 // if it exists, give error at runtime.
2269 res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002270 }
2271 else if (**arg == 't')
2272 {
Bram Moolenaard3aac292020-04-19 14:32:17 +02002273 // Tabpage-local variables can be defined later, thus we don't
2274 // check if it exists, give error at runtime.
2275 res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002276 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002277 else
2278 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002279 semsg("E1075: Namespace not supported: %s", *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002280 goto theend;
2281 }
2282 }
2283 else
2284 {
2285 size_t len = end - *arg;
2286 int idx;
2287 int gen_load = FALSE;
2288
2289 name = vim_strnsave(*arg, end - *arg);
2290 if (name == NULL)
2291 return FAIL;
2292
2293 idx = lookup_arg(*arg, len, cctx);
2294 if (idx >= 0)
2295 {
2296 if (cctx->ctx_ufunc->uf_arg_types != NULL)
2297 type = cctx->ctx_ufunc->uf_arg_types[idx];
2298 else
2299 type = &t_any;
2300
2301 // Arguments are located above the frame pointer.
2302 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
2303 if (cctx->ctx_ufunc->uf_va_name != NULL)
2304 --idx;
2305 gen_load = TRUE;
2306 }
2307 else if (lookup_vararg(*arg, len, cctx))
2308 {
2309 // varargs is always the last argument
2310 idx = -STACK_FRAME_SIZE - 1;
2311 type = cctx->ctx_ufunc->uf_va_type;
2312 gen_load = TRUE;
2313 }
2314 else
2315 {
2316 idx = lookup_local(*arg, len, cctx);
2317 if (idx >= 0)
2318 {
2319 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type;
2320 gen_load = TRUE;
2321 }
2322 else
2323 {
2324 if ((len == 4 && STRNCMP("true", *arg, 4) == 0)
2325 || (len == 5 && STRNCMP("false", *arg, 5) == 0))
2326 res = generate_PUSHBOOL(cctx, **arg == 't'
2327 ? VVAL_TRUE : VVAL_FALSE);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002328 else
2329 {
2330 // "var" can be script-local even without using "s:" if it
2331 // already exists.
2332 if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
2333 == SCRIPT_VERSION_VIM9
2334 || lookup_script(*arg, len) == OK)
2335 res = compile_load_scriptvar(cctx, name, *arg, &end,
2336 FALSE);
2337
2338 // When the name starts with an uppercase letter or "x:" it
2339 // can be a user defined function.
2340 if (res == FAIL && (ASCII_ISUPPER(*name) || name[1] == ':'))
2341 res = generate_funcref(cctx, name);
2342 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002343 }
2344 }
2345 if (gen_load)
2346 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
2347 }
2348
2349 *arg = end;
2350
2351theend:
Bram Moolenaar599c89c2020-03-28 14:53:20 +01002352 if (res == FAIL && error && called_emsg == prev_called_emsg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002353 semsg(_(e_var_notfound), name);
2354 vim_free(name);
2355 return res;
2356}
2357
2358/*
2359 * Compile the argument expressions.
2360 * "arg" points to just after the "(" and is advanced to after the ")"
2361 */
2362 static int
2363compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
2364{
Bram Moolenaar2c330432020-04-13 14:41:35 +02002365 char_u *p = *arg;
2366 char_u *whitep = *arg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002367
Bram Moolenaare6085c52020-04-12 20:19:16 +02002368 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002369 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002370 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaare6085c52020-04-12 20:19:16 +02002371 {
2372 p = next_line_from_context(cctx);
2373 if (p == NULL)
Bram Moolenaar2c330432020-04-13 14:41:35 +02002374 goto failret;
2375 whitep = (char_u *)" ";
Bram Moolenaare6085c52020-04-12 20:19:16 +02002376 p = skipwhite(p);
2377 }
2378 if (*p == ')')
2379 {
2380 *arg = p + 1;
2381 return OK;
2382 }
2383
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002384 if (compile_expr1(&p, cctx) == FAIL)
2385 return FAIL;
2386 ++*argcount;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002387
2388 if (*p != ',' && *skipwhite(p) == ',')
2389 {
Bram Moolenaard77a8522020-04-03 21:59:57 +02002390 semsg(_(e_no_white_before), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002391 p = skipwhite(p);
2392 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002393 if (*p == ',')
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002394 {
2395 ++p;
Bram Moolenaare6085c52020-04-12 20:19:16 +02002396 if (*p != NUL && !VIM_ISWHITE(*p))
Bram Moolenaard77a8522020-04-03 21:59:57 +02002397 semsg(_(e_white_after), ",");
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002398 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002399 whitep = p;
Bram Moolenaar38a5f512020-02-19 12:40:39 +01002400 p = skipwhite(p);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002401 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002402failret:
Bram Moolenaare6085c52020-04-12 20:19:16 +02002403 emsg(_(e_missing_close));
2404 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002405}
2406
2407/*
2408 * Compile a function call: name(arg1, arg2)
2409 * "arg" points to "name", "arg + varlen" to the "(".
2410 * "argcount_init" is 1 for "value->method()"
2411 * Instructions:
2412 * EVAL arg1
2413 * EVAL arg2
2414 * BCALL / DCALL / UCALL
2415 */
2416 static int
2417compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
2418{
2419 char_u *name = *arg;
Bram Moolenaar0b76ad52020-01-31 21:20:51 +01002420 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002421 int argcount = argcount_init;
2422 char_u namebuf[100];
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002423 char_u fname_buf[FLEN_FIXED + 1];
2424 char_u *tofree = NULL;
2425 int error = FCERR_NONE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002426 ufunc_T *ufunc;
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002427 int res = FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002428
2429 if (varlen >= sizeof(namebuf))
2430 {
2431 semsg(_("E1011: name too long: %s"), name);
2432 return FAIL;
2433 }
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002434 vim_strncpy(namebuf, *arg, varlen);
2435 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002436
2437 *arg = skipwhite(*arg + varlen + 1);
2438 if (compile_arguments(arg, cctx, &argcount) == FAIL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002439 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002440
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002441 if (ASCII_ISLOWER(*name) && name[1] != ':')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002442 {
2443 int idx;
2444
2445 // builtin function
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002446 idx = find_internal_func(name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002447 if (idx >= 0)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002448 res = generate_BCALL(cctx, idx, argcount);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002449 else
2450 semsg(_(e_unknownfunc), namebuf);
2451 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002452 }
2453
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002454 // If we can find the function by name generate the right call.
Bram Moolenaar4c17ad92020-04-27 22:47:51 +02002455 ufunc = find_func(name, FALSE, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002456 if (ufunc != NULL)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002457 {
2458 res = generate_CALL(cctx, ufunc, argcount);
2459 goto theend;
2460 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002461
2462 // If the name is a variable, load it and use PCALL.
Bram Moolenaara26b9702020-04-18 19:53:28 +02002463 // Not for g:Func(), we don't know if it is a variable or not.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002464 p = namebuf;
Bram Moolenaara26b9702020-04-18 19:53:28 +02002465 if (STRNCMP(namebuf, "g:", 2) != 0
2466 && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002467 {
2468 res = generate_PCALL(cctx, argcount, FALSE);
2469 goto theend;
2470 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002471
Bram Moolenaar1df8b3f2020-04-23 18:13:23 +02002472 // A global function may be defined only later. Need to figure out at
2473 // runtime.
2474 if (STRNCMP(namebuf, "g:", 2) == 0)
2475 res = generate_UCALL(cctx, name, argcount);
2476 else
2477 semsg(_(e_unknownfunc), namebuf);
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01002478
2479theend:
2480 vim_free(tofree);
2481 return res;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002482}
2483
2484// like NAMESPACE_CHAR but with 'a' and 'l'.
2485#define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw"
2486
2487/*
2488 * Find the end of a variable or function name. Unlike find_name_end() this
2489 * does not recognize magic braces.
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002490 * When "namespace" is TRUE recognize "b:", "s:", etc.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002491 * Return a pointer to just after the name. Equal to "arg" if there is no
2492 * valid name.
2493 */
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002494 static char_u *
2495to_name_end(char_u *arg, int namespace)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002496{
2497 char_u *p;
2498
2499 // Quick check for valid starting character.
2500 if (!eval_isnamec1(*arg))
2501 return arg;
2502
2503 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p))
2504 // Include a namespace such as "s:var" and "v:var". But "n:" is not
2505 // and can be used in slice "[n:]".
2506 if (*p == ':' && (p != arg + 1
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002507 || !namespace
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002508 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL))
2509 break;
2510 return p;
2511}
2512
2513/*
2514 * Like to_name_end() but also skip over a list or dict constant.
2515 */
2516 char_u *
2517to_name_const_end(char_u *arg)
2518{
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01002519 char_u *p = to_name_end(arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002520 typval_T rettv;
2521
2522 if (p == arg && *arg == '[')
2523 {
2524
2525 // Can be "[1, 2, 3]->Func()".
2526 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL)
2527 p = arg;
2528 }
2529 else if (p == arg && *arg == '#' && arg[1] == '{')
2530 {
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002531 // Can be "#{a: 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002532 ++p;
2533 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL)
2534 p = arg;
2535 }
2536 else if (p == arg && *arg == '{')
2537 {
2538 int ret = get_lambda_tv(&p, &rettv, FALSE);
2539
Bram Moolenaar33fa29c2020-03-28 19:41:33 +01002540 // Can be "{x -> ret}()".
2541 // Can be "{'a': 1}->Func()".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002542 if (ret == NOTDONE)
2543 ret = eval_dict(&p, &rettv, FALSE, FALSE);
2544 if (ret != OK)
2545 p = arg;
2546 }
2547
2548 return p;
2549}
2550
2551 static void
2552type_mismatch(type_T *expected, type_T *actual)
2553{
2554 char *tofree1, *tofree2;
2555
2556 semsg(_("E1013: type mismatch, expected %s but got %s"),
2557 type_name(expected, &tofree1), type_name(actual, &tofree2));
2558 vim_free(tofree1);
2559 vim_free(tofree2);
2560}
2561
Bram Moolenaar0b76b422020-04-07 22:05:08 +02002562 static void
2563arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
2564{
2565 char *tofree1, *tofree2;
2566
2567 semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
2568 argidx,
2569 type_name(expected, &tofree1), type_name(actual, &tofree2));
2570 vim_free(tofree1);
2571 vim_free(tofree2);
2572}
2573
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002574/*
2575 * Check if the expected and actual types match.
2576 */
2577 static int
2578check_type(type_T *expected, type_T *actual, int give_msg)
2579{
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002580 int ret = OK;
2581
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002582 // When expected is "unknown" we accept any actual type.
2583 // When expected is "any" we accept any actual type except "void".
2584 if (expected->tt_type != VAR_UNKNOWN
2585 && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002586 {
2587 if (expected->tt_type != actual->tt_type)
2588 {
2589 if (give_msg)
2590 type_mismatch(expected, actual);
2591 return FAIL;
2592 }
2593 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
2594 {
Bram Moolenaar4c683752020-04-05 21:38:23 +02002595 // "unknown" is used for an empty list or dict
2596 if (actual->tt_member != &t_unknown)
Bram Moolenaar436472f2020-02-20 22:54:43 +01002597 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002598 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002599 else if (expected->tt_type == VAR_FUNC)
2600 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02002601 if (expected->tt_member != &t_unknown)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002602 ret = check_type(expected->tt_member, actual->tt_member, FALSE);
2603 if (ret == OK && expected->tt_argcount != -1
2604 && (actual->tt_argcount < expected->tt_min_argcount
2605 || actual->tt_argcount > expected->tt_argcount))
2606 ret = FAIL;
2607 }
2608 if (ret == FAIL && give_msg)
2609 type_mismatch(expected, actual);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002610 }
Bram Moolenaar89228602020-04-05 22:14:54 +02002611 return ret;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002612}
2613
2614/*
2615 * Check that
2616 * - "actual" is "expected" type or
2617 * - "actual" is a type that can be "expected" type: add a runtime check; or
2618 * - return FAIL.
2619 */
2620 static int
2621need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx)
2622{
Bram Moolenaar89228602020-04-05 22:14:54 +02002623 if (check_type(expected, actual, FALSE) == OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002624 return OK;
Bram Moolenaar4c683752020-04-05 21:38:23 +02002625 if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002626 {
2627 type_mismatch(expected, actual);
2628 return FAIL;
2629 }
2630 generate_TYPECHECK(cctx, expected, offset);
2631 return OK;
2632}
2633
2634/*
2635 * parse a list: [expr, expr]
2636 * "*arg" points to the '['.
2637 */
2638 static int
2639compile_list(char_u **arg, cctx_T *cctx)
2640{
2641 char_u *p = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002642 char_u *whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002643 int count = 0;
2644
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002645 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002646 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002647 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaara30590d2020-03-28 22:06:23 +01002648 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002649 p = next_line_from_context(cctx);
2650 if (p == NULL)
2651 {
2652 semsg(_(e_list_end), *arg);
2653 return FAIL;
2654 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002655 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002656 p = skipwhite(p);
2657 }
2658 if (*p == ']')
2659 {
2660 ++p;
2661 // Allow for following comment, after at least one space.
2662 if (VIM_ISWHITE(*p) && *skipwhite(p) == '"')
2663 p += STRLEN(p);
2664 break;
Bram Moolenaara30590d2020-03-28 22:06:23 +01002665 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002666 if (compile_expr1(&p, cctx) == FAIL)
2667 break;
2668 ++count;
2669 if (*p == ',')
2670 ++p;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002671 whitep = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002672 p = skipwhite(p);
2673 }
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002674 *arg = p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002675
2676 generate_NEWLIST(cctx, count);
2677 return OK;
2678}
2679
2680/*
2681 * parse a lambda: {arg, arg -> expr}
2682 * "*arg" points to the '{'.
2683 */
2684 static int
2685compile_lambda(char_u **arg, cctx_T *cctx)
2686{
2687 garray_T *instr = &cctx->ctx_instr;
2688 typval_T rettv;
2689 ufunc_T *ufunc;
2690
2691 // Get the funcref in "rettv".
Bram Moolenaara30590d2020-03-28 22:06:23 +01002692 if (get_lambda_tv(arg, &rettv, TRUE) != OK)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002693 return FAIL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002694
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002695 ufunc = rettv.vval.v_partial->pt_func;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002696 ++ufunc->uf_refcount;
2697 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002698 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002699
2700 // The function will have one line: "return {expr}".
2701 // Compile it into instructions.
2702 compile_def_function(ufunc, TRUE);
2703
2704 if (ufunc->uf_dfunc_idx >= 0)
2705 {
2706 if (ga_grow(instr, 1) == FAIL)
2707 return FAIL;
2708 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
2709 return OK;
2710 }
2711 return FAIL;
2712}
2713
2714/*
2715 * Compile a lamda call: expr->{lambda}(args)
2716 * "arg" points to the "{".
2717 */
2718 static int
2719compile_lambda_call(char_u **arg, cctx_T *cctx)
2720{
2721 ufunc_T *ufunc;
2722 typval_T rettv;
2723 int argcount = 1;
2724 int ret = FAIL;
2725
2726 // Get the funcref in "rettv".
2727 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
2728 return FAIL;
2729
2730 if (**arg != '(')
2731 {
2732 if (*skipwhite(*arg) == '(')
Bram Moolenaardb99f9f2020-03-23 22:12:22 +01002733 emsg(_(e_nowhitespace));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002734 else
2735 semsg(_(e_missing_paren), "lambda");
2736 clear_tv(&rettv);
2737 return FAIL;
2738 }
2739
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002740 ufunc = rettv.vval.v_partial->pt_func;
2741 ++ufunc->uf_refcount;
Bram Moolenaar20431c92020-03-20 18:39:46 +01002742 clear_tv(&rettv);
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02002743 ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10);
Bram Moolenaar20431c92020-03-20 18:39:46 +01002744
2745 // The function will have one line: "return {expr}".
2746 // Compile it into instructions.
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002747 compile_def_function(ufunc, TRUE);
2748
2749 // compile the arguments
2750 *arg = skipwhite(*arg + 1);
2751 if (compile_arguments(arg, cctx, &argcount) == OK)
2752 // call the compiled function
2753 ret = generate_CALL(cctx, ufunc, argcount);
2754
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002755 return ret;
2756}
2757
2758/*
2759 * parse a dict: {'key': val} or #{key: val}
2760 * "*arg" points to the '{'.
2761 */
2762 static int
2763compile_dict(char_u **arg, cctx_T *cctx, int literal)
2764{
2765 garray_T *instr = &cctx->ctx_instr;
2766 int count = 0;
2767 dict_T *d = dict_alloc();
2768 dictitem_T *item;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002769 char_u *whitep = *arg;
2770 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002771
2772 if (d == NULL)
2773 return FAIL;
2774 *arg = skipwhite(*arg + 1);
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002775 for (;;)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002776 {
2777 char_u *key = NULL;
2778
Bram Moolenaar2c330432020-04-13 14:41:35 +02002779 while (**arg == NUL || (literal && **arg == '"')
2780 || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002781 {
2782 *arg = next_line_from_context(cctx);
2783 if (*arg == NULL)
2784 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002785 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002786 *arg = skipwhite(*arg);
2787 }
2788
2789 if (**arg == '}')
2790 break;
2791
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002792 if (literal)
2793 {
Bram Moolenaar2c330432020-04-13 14:41:35 +02002794 char_u *end = to_name_end(*arg, !literal);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002795
Bram Moolenaar2c330432020-04-13 14:41:35 +02002796 if (end == *arg)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002797 {
2798 semsg(_("E1014: Invalid key: %s"), *arg);
2799 return FAIL;
2800 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002801 key = vim_strnsave(*arg, end - *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002802 if (generate_PUSHS(cctx, key) == FAIL)
2803 return FAIL;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002804 *arg = end;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002805 }
2806 else
2807 {
2808 isn_T *isn;
2809
2810 if (compile_expr1(arg, cctx) == FAIL)
2811 return FAIL;
2812 // TODO: check type is string
2813 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
2814 if (isn->isn_type == ISN_PUSHS)
2815 key = isn->isn_arg.string;
2816 }
2817
2818 // Check for duplicate keys, if using string keys.
2819 if (key != NULL)
2820 {
2821 item = dict_find(d, key, -1);
2822 if (item != NULL)
2823 {
2824 semsg(_(e_duplicate_key), key);
2825 goto failret;
2826 }
2827 item = dictitem_alloc(key);
2828 if (item != NULL)
2829 {
2830 item->di_tv.v_type = VAR_UNKNOWN;
2831 item->di_tv.v_lock = 0;
2832 if (dict_add(d, item) == FAIL)
2833 dictitem_free(item);
2834 }
2835 }
2836
2837 *arg = skipwhite(*arg);
2838 if (**arg != ':')
2839 {
2840 semsg(_(e_missing_dict_colon), *arg);
2841 return FAIL;
2842 }
2843
Bram Moolenaar2c330432020-04-13 14:41:35 +02002844 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002845 *arg = skipwhite(*arg + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002846 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002847 {
2848 *arg = next_line_from_context(cctx);
2849 if (*arg == NULL)
2850 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002851 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002852 *arg = skipwhite(*arg);
2853 }
2854
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002855 if (compile_expr1(arg, cctx) == FAIL)
2856 return FAIL;
2857 ++count;
2858
Bram Moolenaar2c330432020-04-13 14:41:35 +02002859 whitep = *arg;
2860 p = skipwhite(*arg);
2861 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002862 {
2863 *arg = next_line_from_context(cctx);
2864 if (*arg == NULL)
2865 goto failret;
Bram Moolenaar2c330432020-04-13 14:41:35 +02002866 whitep = (char_u *)" ";
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002867 *arg = skipwhite(*arg);
Bram Moolenaar2c330432020-04-13 14:41:35 +02002868 p = *arg;
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002869 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002870 if (**arg == '}')
2871 break;
2872 if (**arg != ',')
2873 {
2874 semsg(_(e_missing_dict_comma), *arg);
2875 goto failret;
2876 }
Bram Moolenaar2c330432020-04-13 14:41:35 +02002877 whitep = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002878 *arg = skipwhite(*arg + 1);
2879 }
2880
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002881 *arg = *arg + 1;
2882
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002883 // Allow for following comment, after at least one space.
Bram Moolenaar2c330432020-04-13 14:41:35 +02002884 p = skipwhite(*arg);
2885 if (VIM_ISWHITE(**arg) && (*p == '"' || comment_start(p)))
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002886 *arg += STRLEN(*arg);
2887
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002888 dict_unref(d);
2889 return generate_NEWDICT(cctx, count);
2890
2891failret:
Bram Moolenaar4fdae992020-04-12 16:38:57 +02002892 if (*arg == NULL)
2893 semsg(_(e_missing_dict_end), _("[end of lines]"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002894 dict_unref(d);
2895 return FAIL;
2896}
2897
2898/*
2899 * Compile "&option".
2900 */
2901 static int
2902compile_get_option(char_u **arg, cctx_T *cctx)
2903{
2904 typval_T rettv;
2905 char_u *start = *arg;
2906 int ret;
2907
2908 // parse the option and get the current value to get the type.
2909 rettv.v_type = VAR_UNKNOWN;
2910 ret = get_option_tv(arg, &rettv, TRUE);
2911 if (ret == OK)
2912 {
2913 // include the '&' in the name, get_option_tv() expects it.
2914 char_u *name = vim_strnsave(start, *arg - start);
2915 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string;
2916
2917 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
2918 vim_free(name);
2919 }
2920 clear_tv(&rettv);
2921
2922 return ret;
2923}
2924
2925/*
2926 * Compile "$VAR".
2927 */
2928 static int
2929compile_get_env(char_u **arg, cctx_T *cctx)
2930{
2931 char_u *start = *arg;
2932 int len;
2933 int ret;
2934 char_u *name;
2935
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002936 ++*arg;
2937 len = get_env_len(arg);
2938 if (len == 0)
2939 {
2940 semsg(_(e_syntax_at), start - 1);
2941 return FAIL;
2942 }
2943
2944 // include the '$' in the name, get_env_tv() expects it.
2945 name = vim_strnsave(start, len + 1);
2946 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string);
2947 vim_free(name);
2948 return ret;
2949}
2950
2951/*
2952 * Compile "@r".
2953 */
2954 static int
2955compile_get_register(char_u **arg, cctx_T *cctx)
2956{
2957 int ret;
2958
2959 ++*arg;
2960 if (**arg == NUL)
2961 {
2962 semsg(_(e_syntax_at), *arg - 1);
2963 return FAIL;
2964 }
2965 if (!valid_yank_reg(**arg, TRUE))
2966 {
2967 emsg_invreg(**arg);
2968 return FAIL;
2969 }
2970 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string);
2971 ++*arg;
2972 return ret;
2973}
2974
2975/*
2976 * Apply leading '!', '-' and '+' to constant "rettv".
2977 */
2978 static int
2979apply_leader(typval_T *rettv, char_u *start, char_u *end)
2980{
2981 char_u *p = end;
2982
2983 // this works from end to start
2984 while (p > start)
2985 {
2986 --p;
2987 if (*p == '-' || *p == '+')
2988 {
2989 // only '-' has an effect, for '+' we only check the type
2990#ifdef FEAT_FLOAT
2991 if (rettv->v_type == VAR_FLOAT)
2992 {
2993 if (*p == '-')
2994 rettv->vval.v_float = -rettv->vval.v_float;
2995 }
2996 else
2997#endif
2998 {
2999 varnumber_T val;
3000 int error = FALSE;
3001
3002 // tv_get_number_chk() accepts a string, but we don't want that
3003 // here
3004 if (check_not_string(rettv) == FAIL)
3005 return FAIL;
3006 val = tv_get_number_chk(rettv, &error);
3007 clear_tv(rettv);
3008 if (error)
3009 return FAIL;
3010 if (*p == '-')
3011 val = -val;
3012 rettv->v_type = VAR_NUMBER;
3013 rettv->vval.v_number = val;
3014 }
3015 }
3016 else
3017 {
3018 int v = tv2bool(rettv);
3019
3020 // '!' is permissive in the type.
3021 clear_tv(rettv);
3022 rettv->v_type = VAR_BOOL;
3023 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
3024 }
3025 }
3026 return OK;
3027}
3028
3029/*
3030 * Recognize v: variables that are constants and set "rettv".
3031 */
3032 static void
3033get_vim_constant(char_u **arg, typval_T *rettv)
3034{
3035 if (STRNCMP(*arg, "v:true", 6) == 0)
3036 {
3037 rettv->v_type = VAR_BOOL;
3038 rettv->vval.v_number = VVAL_TRUE;
3039 *arg += 6;
3040 }
3041 else if (STRNCMP(*arg, "v:false", 7) == 0)
3042 {
3043 rettv->v_type = VAR_BOOL;
3044 rettv->vval.v_number = VVAL_FALSE;
3045 *arg += 7;
3046 }
3047 else if (STRNCMP(*arg, "v:null", 6) == 0)
3048 {
3049 rettv->v_type = VAR_SPECIAL;
3050 rettv->vval.v_number = VVAL_NULL;
3051 *arg += 6;
3052 }
3053 else if (STRNCMP(*arg, "v:none", 6) == 0)
3054 {
3055 rettv->v_type = VAR_SPECIAL;
3056 rettv->vval.v_number = VVAL_NONE;
3057 *arg += 6;
3058 }
3059}
3060
3061/*
3062 * Compile code to apply '-', '+' and '!'.
3063 */
3064 static int
3065compile_leader(cctx_T *cctx, char_u *start, char_u *end)
3066{
3067 char_u *p = end;
3068
3069 // this works from end to start
3070 while (p > start)
3071 {
3072 --p;
3073 if (*p == '-' || *p == '+')
3074 {
3075 int negate = *p == '-';
3076 isn_T *isn;
3077
3078 // TODO: check type
3079 while (p > start && (p[-1] == '-' || p[-1] == '+'))
3080 {
3081 --p;
3082 if (*p == '-')
3083 negate = !negate;
3084 }
3085 // only '-' has an effect, for '+' we only check the type
3086 if (negate)
3087 isn = generate_instr(cctx, ISN_NEGATENR);
3088 else
3089 isn = generate_instr(cctx, ISN_CHECKNR);
3090 if (isn == NULL)
3091 return FAIL;
3092 }
3093 else
3094 {
3095 int invert = TRUE;
3096
3097 while (p > start && p[-1] == '!')
3098 {
3099 --p;
3100 invert = !invert;
3101 }
3102 if (generate_2BOOL(cctx, invert) == FAIL)
3103 return FAIL;
3104 }
3105 }
3106 return OK;
3107}
3108
3109/*
3110 * Compile whatever comes after "name" or "name()".
3111 */
3112 static int
3113compile_subscript(
3114 char_u **arg,
3115 cctx_T *cctx,
3116 char_u **start_leader,
3117 char_u *end_leader)
3118{
3119 for (;;)
3120 {
3121 if (**arg == '(')
3122 {
3123 int argcount = 0;
3124
3125 // funcref(arg)
3126 *arg = skipwhite(*arg + 1);
3127 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3128 return FAIL;
3129 if (generate_PCALL(cctx, argcount, TRUE) == FAIL)
3130 return FAIL;
3131 }
3132 else if (**arg == '-' && (*arg)[1] == '>')
3133 {
3134 char_u *p;
3135
3136 // something->method()
3137 // Apply the '!', '-' and '+' first:
3138 // -1.0->func() works like (-1.0)->func()
3139 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3140 return FAIL;
3141 *start_leader = end_leader; // don't apply again later
3142
3143 *arg = skipwhite(*arg + 2);
3144 if (**arg == '{')
3145 {
3146 // lambda call: list->{lambda}
3147 if (compile_lambda_call(arg, cctx) == FAIL)
3148 return FAIL;
3149 }
3150 else
3151 {
3152 // method call: list->method()
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003153 p = *arg;
3154 if (ASCII_ISALPHA(*p) && p[1] == ':')
3155 p += 2;
3156 for ( ; eval_isnamec1(*p); ++p)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003157 ;
3158 if (*p != '(')
3159 {
Bram Moolenaar0b37a2f2020-03-29 21:38:15 +02003160 semsg(_(e_missing_paren), *arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003161 return FAIL;
3162 }
3163 // TODO: base value may not be the first argument
3164 if (compile_call(arg, p - *arg, cctx, 1) == FAIL)
3165 return FAIL;
3166 }
3167 }
3168 else if (**arg == '[')
3169 {
Bram Moolenaarb13af502020-02-17 21:12:08 +01003170 garray_T *stack;
3171 type_T **typep;
3172
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003173 // list index: list[123]
3174 // TODO: more arguments
3175 // TODO: dict member dict['name']
3176 *arg = skipwhite(*arg + 1);
3177 if (compile_expr1(arg, cctx) == FAIL)
3178 return FAIL;
3179
3180 if (**arg != ']')
3181 {
3182 emsg(_(e_missbrac));
3183 return FAIL;
3184 }
Bram Moolenaarf2460a32020-02-07 22:09:54 +01003185 *arg = *arg + 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003186
3187 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
3188 return FAIL;
Bram Moolenaarb13af502020-02-17 21:12:08 +01003189 stack = &cctx->ctx_type_stack;
3190 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
3191 if ((*typep)->tt_type != VAR_LIST && *typep != &t_any)
3192 {
3193 emsg(_(e_listreq));
3194 return FAIL;
3195 }
Bram Moolenaar0062c2d2020-02-20 22:14:31 +01003196 if ((*typep)->tt_type == VAR_LIST)
3197 *typep = (*typep)->tt_member;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003198 }
3199 else if (**arg == '.' && (*arg)[1] != '.')
3200 {
3201 char_u *p;
3202
3203 ++*arg;
3204 p = *arg;
3205 // dictionary member: dict.name
3206 if (eval_isnamec1(*p))
3207 while (eval_isnamec(*p))
3208 MB_PTR_ADV(p);
3209 if (p == *arg)
3210 {
3211 semsg(_(e_syntax_at), *arg);
3212 return FAIL;
3213 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003214 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL)
3215 return FAIL;
3216 *arg = p;
3217 }
3218 else
3219 break;
3220 }
3221
3222 // TODO - see handle_subscript():
3223 // Turn "dict.Func" into a partial for "Func" bound to "dict".
3224 // Don't do this when "Func" is already a partial that was bound
3225 // explicitly (pt_auto is FALSE).
3226
3227 return OK;
3228}
3229
3230/*
3231 * Compile an expression at "*p" and add instructions to "instr".
3232 * "p" is advanced until after the expression, skipping white space.
3233 *
3234 * This is the equivalent of eval1(), eval2(), etc.
3235 */
3236
3237/*
3238 * number number constant
3239 * 0zFFFFFFFF Blob constant
3240 * "string" string constant
3241 * 'string' literal string constant
3242 * &option-name option value
3243 * @r register contents
3244 * identifier variable value
3245 * function() function call
3246 * $VAR environment variable
3247 * (expression) nested expression
3248 * [expr, expr] List
3249 * {key: val, key: val} Dictionary
3250 * #{key: val, key: val} Dictionary with literal keys
3251 *
3252 * Also handle:
3253 * ! in front logical NOT
3254 * - in front unary minus
3255 * + in front unary plus (ignored)
3256 * trailing (arg) funcref/partial call
3257 * trailing [] subscript in String or List
3258 * trailing .name entry in Dictionary
3259 * trailing ->name() method call
3260 */
3261 static int
3262compile_expr7(char_u **arg, cctx_T *cctx)
3263{
3264 typval_T rettv;
3265 char_u *start_leader, *end_leader;
3266 int ret = OK;
3267
3268 /*
3269 * Skip '!', '-' and '+' characters. They are handled later.
3270 */
3271 start_leader = *arg;
3272 while (**arg == '!' || **arg == '-' || **arg == '+')
3273 *arg = skipwhite(*arg + 1);
3274 end_leader = *arg;
3275
3276 rettv.v_type = VAR_UNKNOWN;
3277 switch (**arg)
3278 {
3279 /*
3280 * Number constant.
3281 */
3282 case '0': // also for blob starting with 0z
3283 case '1':
3284 case '2':
3285 case '3':
3286 case '4':
3287 case '5':
3288 case '6':
3289 case '7':
3290 case '8':
3291 case '9':
3292 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL)
3293 return FAIL;
3294 break;
3295
3296 /*
3297 * String constant: "string".
3298 */
3299 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL)
3300 return FAIL;
3301 break;
3302
3303 /*
3304 * Literal string constant: 'str''ing'.
3305 */
3306 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL)
3307 return FAIL;
3308 break;
3309
3310 /*
3311 * Constant Vim variable.
3312 */
3313 case 'v': get_vim_constant(arg, &rettv);
3314 ret = NOTDONE;
3315 break;
3316
3317 /*
3318 * List: [expr, expr]
3319 */
3320 case '[': ret = compile_list(arg, cctx);
3321 break;
3322
3323 /*
3324 * Dictionary: #{key: val, key: val}
3325 */
3326 case '#': if ((*arg)[1] == '{')
3327 {
3328 ++*arg;
3329 ret = compile_dict(arg, cctx, TRUE);
3330 }
3331 else
3332 ret = NOTDONE;
3333 break;
3334
3335 /*
3336 * Lambda: {arg, arg -> expr}
3337 * Dictionary: {'key': val, 'key': val}
3338 */
3339 case '{': {
3340 char_u *start = skipwhite(*arg + 1);
3341
3342 // Find out what comes after the arguments.
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003343 // TODO: pass getline function
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003344 ret = get_function_args(&start, '-', NULL,
Bram Moolenaar5e774c72020-04-12 21:53:00 +02003345 NULL, NULL, NULL, TRUE, NULL, NULL);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003346 if (ret != FAIL && *start == '>')
3347 ret = compile_lambda(arg, cctx);
3348 else
3349 ret = compile_dict(arg, cctx, FALSE);
3350 }
3351 break;
3352
3353 /*
3354 * Option value: &name
3355 */
3356 case '&': ret = compile_get_option(arg, cctx);
3357 break;
3358
3359 /*
3360 * Environment variable: $VAR.
3361 */
3362 case '$': ret = compile_get_env(arg, cctx);
3363 break;
3364
3365 /*
3366 * Register contents: @r.
3367 */
3368 case '@': ret = compile_get_register(arg, cctx);
3369 break;
3370 /*
3371 * nested expression: (expression).
3372 */
3373 case '(': *arg = skipwhite(*arg + 1);
3374 ret = compile_expr1(arg, cctx); // recursive!
3375 *arg = skipwhite(*arg);
3376 if (**arg == ')')
3377 ++*arg;
3378 else if (ret == OK)
3379 {
3380 emsg(_(e_missing_close));
3381 ret = FAIL;
3382 }
3383 break;
3384
3385 default: ret = NOTDONE;
3386 break;
3387 }
3388 if (ret == FAIL)
3389 return FAIL;
3390
3391 if (rettv.v_type != VAR_UNKNOWN)
3392 {
3393 // apply the '!', '-' and '+' before the constant
3394 if (apply_leader(&rettv, start_leader, end_leader) == FAIL)
3395 {
3396 clear_tv(&rettv);
3397 return FAIL;
3398 }
3399 start_leader = end_leader; // don't apply again below
3400
3401 // push constant
3402 switch (rettv.v_type)
3403 {
3404 case VAR_BOOL:
3405 generate_PUSHBOOL(cctx, rettv.vval.v_number);
3406 break;
3407 case VAR_SPECIAL:
3408 generate_PUSHSPEC(cctx, rettv.vval.v_number);
3409 break;
3410 case VAR_NUMBER:
3411 generate_PUSHNR(cctx, rettv.vval.v_number);
3412 break;
3413#ifdef FEAT_FLOAT
3414 case VAR_FLOAT:
3415 generate_PUSHF(cctx, rettv.vval.v_float);
3416 break;
3417#endif
3418 case VAR_BLOB:
3419 generate_PUSHBLOB(cctx, rettv.vval.v_blob);
3420 rettv.vval.v_blob = NULL;
3421 break;
3422 case VAR_STRING:
3423 generate_PUSHS(cctx, rettv.vval.v_string);
3424 rettv.vval.v_string = NULL;
3425 break;
3426 default:
3427 iemsg("constant type missing");
3428 return FAIL;
3429 }
3430 }
3431 else if (ret == NOTDONE)
3432 {
3433 char_u *p;
3434 int r;
3435
3436 if (!eval_isnamec1(**arg))
3437 {
3438 semsg(_("E1015: Name expected: %s"), *arg);
3439 return FAIL;
3440 }
3441
3442 // "name" or "name()"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01003443 p = to_name_end(*arg, TRUE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003444 if (*p == '(')
3445 r = compile_call(arg, p - *arg, cctx, 0);
3446 else
3447 r = compile_load(arg, p, cctx, TRUE);
3448 if (r == FAIL)
3449 return FAIL;
3450 }
3451
3452 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL)
3453 return FAIL;
3454
3455 // Now deal with prefixed '-', '+' and '!', if not done already.
3456 return compile_leader(cctx, start_leader, end_leader);
3457}
3458
3459/*
3460 * * number multiplication
3461 * / number division
3462 * % number modulo
3463 */
3464 static int
3465compile_expr6(char_u **arg, cctx_T *cctx)
3466{
3467 char_u *op;
3468
3469 // get the first variable
3470 if (compile_expr7(arg, cctx) == FAIL)
3471 return FAIL;
3472
3473 /*
3474 * Repeat computing, until no "*", "/" or "%" is following.
3475 */
3476 for (;;)
3477 {
3478 op = skipwhite(*arg);
3479 if (*op != '*' && *op != '/' && *op != '%')
3480 break;
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003481 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003482 {
3483 char_u buf[3];
3484
3485 vim_strncpy(buf, op, 1);
3486 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003487 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003488 }
3489 *arg = skipwhite(op + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003490 if (may_get_next_line(op + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003491 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003492
3493 // get the second variable
3494 if (compile_expr7(arg, cctx) == FAIL)
3495 return FAIL;
3496
3497 generate_two_op(cctx, op);
3498 }
3499
3500 return OK;
3501}
3502
3503/*
3504 * + number addition
3505 * - number subtraction
3506 * .. string concatenation
3507 */
3508 static int
3509compile_expr5(char_u **arg, cctx_T *cctx)
3510{
3511 char_u *op;
3512 int oplen;
3513
3514 // get the first variable
3515 if (compile_expr6(arg, cctx) == FAIL)
3516 return FAIL;
3517
3518 /*
3519 * Repeat computing, until no "+", "-" or ".." is following.
3520 */
3521 for (;;)
3522 {
3523 op = skipwhite(*arg);
3524 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.')))
3525 break;
3526 oplen = (*op == '.' ? 2 : 1);
3527
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003528 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003529 {
3530 char_u buf[3];
3531
3532 vim_strncpy(buf, op, oplen);
3533 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003534 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003535 }
3536
3537 *arg = skipwhite(op + oplen);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003538 if (may_get_next_line(op + oplen, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003539 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003540
3541 // get the second variable
3542 if (compile_expr6(arg, cctx) == FAIL)
3543 return FAIL;
3544
3545 if (*op == '.')
3546 {
3547 if (may_generate_2STRING(-2, cctx) == FAIL
3548 || may_generate_2STRING(-1, cctx) == FAIL)
3549 return FAIL;
3550 generate_instr_drop(cctx, ISN_CONCAT, 1);
3551 }
3552 else
3553 generate_two_op(cctx, op);
3554 }
3555
3556 return OK;
3557}
3558
Bram Moolenaar080457c2020-03-03 21:53:32 +01003559 static exptype_T
3560get_compare_type(char_u *p, int *len, int *type_is)
3561{
3562 exptype_T type = EXPR_UNKNOWN;
3563 int i;
3564
3565 switch (p[0])
3566 {
3567 case '=': if (p[1] == '=')
3568 type = EXPR_EQUAL;
3569 else if (p[1] == '~')
3570 type = EXPR_MATCH;
3571 break;
3572 case '!': if (p[1] == '=')
3573 type = EXPR_NEQUAL;
3574 else if (p[1] == '~')
3575 type = EXPR_NOMATCH;
3576 break;
3577 case '>': if (p[1] != '=')
3578 {
3579 type = EXPR_GREATER;
3580 *len = 1;
3581 }
3582 else
3583 type = EXPR_GEQUAL;
3584 break;
3585 case '<': if (p[1] != '=')
3586 {
3587 type = EXPR_SMALLER;
3588 *len = 1;
3589 }
3590 else
3591 type = EXPR_SEQUAL;
3592 break;
3593 case 'i': if (p[1] == 's')
3594 {
3595 // "is" and "isnot"; but not a prefix of a name
3596 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3597 *len = 5;
3598 i = p[*len];
3599 if (!isalnum(i) && i != '_')
3600 {
3601 type = *len == 2 ? EXPR_IS : EXPR_ISNOT;
3602 *type_is = TRUE;
3603 }
3604 }
3605 break;
3606 }
3607 return type;
3608}
3609
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003610/*
3611 * expr5a == expr5b
3612 * expr5a =~ expr5b
3613 * expr5a != expr5b
3614 * expr5a !~ expr5b
3615 * expr5a > expr5b
3616 * expr5a >= expr5b
3617 * expr5a < expr5b
3618 * expr5a <= expr5b
3619 * expr5a is expr5b
3620 * expr5a isnot expr5b
3621 *
3622 * Produces instructions:
3623 * EVAL expr5a Push result of "expr5a"
3624 * EVAL expr5b Push result of "expr5b"
3625 * COMPARE one of the compare instructions
3626 */
3627 static int
3628compile_expr4(char_u **arg, cctx_T *cctx)
3629{
3630 exptype_T type = EXPR_UNKNOWN;
3631 char_u *p;
3632 int len = 2;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003633 int type_is = FALSE;
3634
3635 // get the first variable
3636 if (compile_expr5(arg, cctx) == FAIL)
3637 return FAIL;
3638
3639 p = skipwhite(*arg);
Bram Moolenaar080457c2020-03-03 21:53:32 +01003640 type = get_compare_type(p, &len, &type_is);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003641
3642 /*
3643 * If there is a comparative operator, use it.
3644 */
3645 if (type != EXPR_UNKNOWN)
3646 {
3647 int ic = FALSE; // Default: do not ignore case
3648
3649 if (type_is && (p[len] == '?' || p[len] == '#'))
3650 {
3651 semsg(_(e_invexpr2), *arg);
3652 return FAIL;
3653 }
3654 // extra question mark appended: ignore case
3655 if (p[len] == '?')
3656 {
3657 ic = TRUE;
3658 ++len;
3659 }
3660 // extra '#' appended: match case (ignored)
3661 else if (p[len] == '#')
3662 ++len;
3663 // nothing appended: match case
3664
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003665 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003666 {
3667 char_u buf[7];
3668
3669 vim_strncpy(buf, p, len);
3670 semsg(_(e_white_both), buf);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003671 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003672 }
3673
3674 // get the second variable
3675 *arg = skipwhite(p + len);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003676 if (may_get_next_line(p + len, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003677 return FAIL;
3678
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003679 if (compile_expr5(arg, cctx) == FAIL)
3680 return FAIL;
3681
3682 generate_COMPARE(cctx, type, ic);
3683 }
3684
3685 return OK;
3686}
3687
3688/*
3689 * Compile || or &&.
3690 */
3691 static int
3692compile_and_or(char_u **arg, cctx_T *cctx, char *op)
3693{
3694 char_u *p = skipwhite(*arg);
3695 int opchar = *op;
3696
3697 if (p[0] == opchar && p[1] == opchar)
3698 {
3699 garray_T *instr = &cctx->ctx_instr;
3700 garray_T end_ga;
3701
3702 /*
3703 * Repeat until there is no following "||" or "&&"
3704 */
3705 ga_init2(&end_ga, sizeof(int), 10);
3706 while (p[0] == opchar && p[1] == opchar)
3707 {
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003708 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[2]))
3709 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003710 semsg(_(e_white_both), op);
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003711 return FAIL;
3712 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003713
3714 if (ga_grow(&end_ga, 1) == FAIL)
3715 {
3716 ga_clear(&end_ga);
3717 return FAIL;
3718 }
3719 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len;
3720 ++end_ga.ga_len;
3721 generate_JUMP(cctx, opchar == '|'
3722 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0);
3723
3724 // eval the next expression
3725 *arg = skipwhite(p + 2);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003726 if (may_get_next_line(p + 2, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003727 return FAIL;
3728
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003729 if ((opchar == '|' ? compile_expr3(arg, cctx)
3730 : compile_expr4(arg, cctx)) == FAIL)
3731 {
3732 ga_clear(&end_ga);
3733 return FAIL;
3734 }
3735 p = skipwhite(*arg);
3736 }
3737
3738 // Fill in the end label in all jumps.
3739 while (end_ga.ga_len > 0)
3740 {
3741 isn_T *isn;
3742
3743 --end_ga.ga_len;
3744 isn = ((isn_T *)instr->ga_data)
3745 + *(((int *)end_ga.ga_data) + end_ga.ga_len);
3746 isn->isn_arg.jump.jump_where = instr->ga_len;
3747 }
3748 ga_clear(&end_ga);
3749 }
3750
3751 return OK;
3752}
3753
3754/*
3755 * expr4a && expr4a && expr4a logical AND
3756 *
3757 * Produces instructions:
3758 * EVAL expr4a Push result of "expr4a"
3759 * JUMP_AND_KEEP_IF_FALSE end
3760 * EVAL expr4b Push result of "expr4b"
3761 * JUMP_AND_KEEP_IF_FALSE end
3762 * EVAL expr4c Push result of "expr4c"
3763 * end:
3764 */
3765 static int
3766compile_expr3(char_u **arg, cctx_T *cctx)
3767{
3768 // get the first variable
3769 if (compile_expr4(arg, cctx) == FAIL)
3770 return FAIL;
3771
3772 // || and && work almost the same
3773 return compile_and_or(arg, cctx, "&&");
3774}
3775
3776/*
3777 * expr3a || expr3b || expr3c logical OR
3778 *
3779 * Produces instructions:
3780 * EVAL expr3a Push result of "expr3a"
3781 * JUMP_AND_KEEP_IF_TRUE end
3782 * EVAL expr3b Push result of "expr3b"
3783 * JUMP_AND_KEEP_IF_TRUE end
3784 * EVAL expr3c Push result of "expr3c"
3785 * end:
3786 */
3787 static int
3788compile_expr2(char_u **arg, cctx_T *cctx)
3789{
3790 // eval the first expression
3791 if (compile_expr3(arg, cctx) == FAIL)
3792 return FAIL;
3793
3794 // || and && work almost the same
3795 return compile_and_or(arg, cctx, "||");
3796}
3797
3798/*
3799 * Toplevel expression: expr2 ? expr1a : expr1b
3800 *
3801 * Produces instructions:
3802 * EVAL expr2 Push result of "expr"
3803 * JUMP_IF_FALSE alt jump if false
3804 * EVAL expr1a
3805 * JUMP_ALWAYS end
3806 * alt: EVAL expr1b
3807 * end:
3808 */
3809 static int
3810compile_expr1(char_u **arg, cctx_T *cctx)
3811{
3812 char_u *p;
3813
3814 // evaluate the first expression
3815 if (compile_expr2(arg, cctx) == FAIL)
3816 return FAIL;
3817
3818 p = skipwhite(*arg);
3819 if (*p == '?')
3820 {
3821 garray_T *instr = &cctx->ctx_instr;
3822 garray_T *stack = &cctx->ctx_type_stack;
3823 int alt_idx = instr->ga_len;
3824 int end_idx;
3825 isn_T *isn;
3826 type_T *type1;
3827 type_T *type2;
3828
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003829 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3830 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003831 semsg(_(e_white_both), "?");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003832 return FAIL;
3833 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003834
3835 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
3836
3837 // evaluate the second expression; any type is accepted
3838 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003839 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003840 return FAIL;
3841
Bram Moolenaara6d53682020-01-28 23:04:06 +01003842 if (compile_expr1(arg, cctx) == FAIL)
3843 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003844
3845 // remember the type and drop it
3846 --stack->ga_len;
3847 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
3848
3849 end_idx = instr->ga_len;
3850 generate_JUMP(cctx, JUMP_ALWAYS, 0);
3851
3852 // jump here from JUMP_IF_FALSE
3853 isn = ((isn_T *)instr->ga_data) + alt_idx;
3854 isn->isn_arg.jump.jump_where = instr->ga_len;
3855
3856 // Check for the ":".
3857 p = skipwhite(*arg);
3858 if (*p != ':')
3859 {
3860 emsg(_(e_missing_colon));
3861 return FAIL;
3862 }
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003863 if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[1]))
3864 {
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003865 semsg(_(e_white_both), ":");
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003866 return FAIL;
3867 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003868
3869 // evaluate the third expression
3870 *arg = skipwhite(p + 1);
Bram Moolenaar2c330432020-04-13 14:41:35 +02003871 if (may_get_next_line(p + 1, arg, cctx) == FAIL)
Bram Moolenaar9c7e6dd2020-04-12 20:55:20 +02003872 return FAIL;
3873
Bram Moolenaara6d53682020-01-28 23:04:06 +01003874 if (compile_expr1(arg, cctx) == FAIL)
3875 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003876
3877 // If the types differ, the result has a more generic type.
3878 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01003879 common_type(type1, type2, &type2, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003880
3881 // jump here from JUMP_ALWAYS
3882 isn = ((isn_T *)instr->ga_data) + end_idx;
3883 isn->isn_arg.jump.jump_where = instr->ga_len;
3884 }
3885 return OK;
3886}
3887
3888/*
3889 * compile "return [expr]"
3890 */
3891 static char_u *
3892compile_return(char_u *arg, int set_return_type, cctx_T *cctx)
3893{
3894 char_u *p = arg;
3895 garray_T *stack = &cctx->ctx_type_stack;
3896 type_T *stack_type;
3897
3898 if (*p != NUL && *p != '|' && *p != '\n')
3899 {
3900 // compile return argument into instructions
3901 if (compile_expr1(&p, cctx) == FAIL)
3902 return NULL;
3903
3904 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3905 if (set_return_type)
3906 cctx->ctx_ufunc->uf_ret_type = stack_type;
3907 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx)
3908 == FAIL)
3909 return NULL;
3910 }
3911 else
3912 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003913 // "set_return_type" cannot be TRUE, only used for a lambda which
3914 // always has an argument.
Bram Moolenaar4c683752020-04-05 21:38:23 +02003915 if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID
3916 && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003917 {
3918 emsg(_("E1003: Missing return value"));
3919 return NULL;
3920 }
3921
3922 // No argument, return zero.
3923 generate_PUSHNR(cctx, 0);
3924 }
3925
3926 if (generate_instr(cctx, ISN_RETURN) == NULL)
3927 return NULL;
3928
3929 // "return val | endif" is possible
3930 return skipwhite(p);
3931}
3932
3933/*
3934 * Return the length of an assignment operator, or zero if there isn't one.
3935 */
3936 int
3937assignment_len(char_u *p, int *heredoc)
3938{
3939 if (*p == '=')
3940 {
3941 if (p[1] == '<' && p[2] == '<')
3942 {
3943 *heredoc = TRUE;
3944 return 3;
3945 }
3946 return 1;
3947 }
3948 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=')
3949 return 2;
3950 if (STRNCMP(p, "..=", 3) == 0)
3951 return 3;
3952 return 0;
3953}
3954
3955// words that cannot be used as a variable
3956static char *reserved[] = {
3957 "true",
3958 "false",
3959 NULL
3960};
3961
3962/*
3963 * Get a line for "=<<".
3964 * Return a pointer to the line in allocated memory.
3965 * Return NULL for end-of-file or some error.
3966 */
3967 static char_u *
3968heredoc_getline(
3969 int c UNUSED,
3970 void *cookie,
3971 int indent UNUSED,
3972 int do_concat UNUSED)
3973{
3974 cctx_T *cctx = (cctx_T *)cookie;
3975
3976 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len)
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02003977 {
3978 iemsg("Heredoc got to end");
3979 return NULL;
3980 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003981 ++cctx->ctx_lnum;
3982 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)
3983 [cctx->ctx_lnum]);
3984}
3985
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003986typedef enum {
3987 dest_local,
3988 dest_option,
3989 dest_env,
3990 dest_global,
Bram Moolenaard3aac292020-04-19 14:32:17 +02003991 dest_buffer,
3992 dest_window,
3993 dest_tab,
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01003994 dest_vimvar,
3995 dest_script,
3996 dest_reg,
3997} assign_dest_T;
3998
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01003999/*
4000 * compile "let var [= expr]", "const var = expr" and "var = expr"
4001 * "arg" points to "var".
4002 */
4003 static char_u *
4004compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
4005{
4006 char_u *p;
4007 char_u *ret = NULL;
4008 int var_count = 0;
4009 int semicolon = 0;
4010 size_t varlen;
4011 garray_T *instr = &cctx->ctx_instr;
4012 int idx = -1;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004013 int new_local = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004014 char_u *op;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004015 int opt_type;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004016 assign_dest_T dest = dest_local;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004017 int opt_flags = 0;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004018 int vimvaridx = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004019 int oplen = 0;
4020 int heredoc = FALSE;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004021 type_T *type = &t_any;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004022 lvar_T *lvar;
4023 char_u *name;
4024 char_u *sp;
4025 int has_type = FALSE;
4026 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
4027 int instr_count = -1;
4028
4029 p = skip_var_list(arg, FALSE, &var_count, &semicolon);
4030 if (p == NULL)
4031 return NULL;
4032 if (var_count > 0)
4033 {
4034 // TODO: let [var, var] = list
4035 emsg("Cannot handle a list yet");
4036 return NULL;
4037 }
4038
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004039 // "a: type" is declaring variable "a" with a type, not "a:".
4040 if (is_decl && p == arg + 2 && p[-1] == ':')
4041 --p;
4042
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004043 varlen = p - arg;
4044 name = vim_strnsave(arg, (int)varlen);
4045 if (name == NULL)
4046 return NULL;
4047
Bram Moolenaar080457c2020-03-03 21:53:32 +01004048 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004049 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004050 if (*arg == '&')
4051 {
4052 int cc;
4053 long numval;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004054
Bram Moolenaar080457c2020-03-03 21:53:32 +01004055 dest = dest_option;
4056 if (cmdidx == CMD_const)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004057 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004058 emsg(_(e_const_option));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004059 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004060 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004061 if (is_decl)
4062 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004063 semsg(_("E1052: Cannot declare an option: %s"), arg);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004064 goto theend;
4065 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004066 p = arg;
4067 p = find_option_end(&p, &opt_flags);
4068 if (p == NULL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004069 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004070 // cannot happen?
Bram Moolenaar080457c2020-03-03 21:53:32 +01004071 emsg(_(e_letunexp));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004072 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004073 }
4074 cc = *p;
4075 *p = NUL;
Bram Moolenaar20431c92020-03-20 18:39:46 +01004076 opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004077 *p = cc;
4078 if (opt_type == -3)
4079 {
Bram Moolenaar9be61bb2020-03-30 22:51:24 +02004080 semsg(_(e_unknown_option), arg);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004081 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004082 }
4083 if (opt_type == -2 || opt_type == 0)
4084 type = &t_string;
4085 else
4086 type = &t_number; // both number and boolean option
4087 }
4088 else if (*arg == '$')
4089 {
4090 dest = dest_env;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004091 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004092 if (is_decl)
4093 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004094 semsg(_("E1065: Cannot declare an environment variable: %s"),
4095 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004096 goto theend;
4097 }
4098 }
4099 else if (*arg == '@')
4100 {
4101 if (!valid_yank_reg(arg[1], TRUE))
4102 {
4103 emsg_invreg(arg[1]);
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004104 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004105 }
4106 dest = dest_reg;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004107 type = &t_string;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004108 if (is_decl)
4109 {
4110 semsg(_("E1066: Cannot declare a register: %s"), name);
4111 goto theend;
4112 }
4113 }
4114 else if (STRNCMP(arg, "g:", 2) == 0)
4115 {
4116 dest = dest_global;
4117 if (is_decl)
4118 {
4119 semsg(_("E1016: Cannot declare a global variable: %s"), name);
4120 goto theend;
4121 }
4122 }
Bram Moolenaard3aac292020-04-19 14:32:17 +02004123 else if (STRNCMP(arg, "b:", 2) == 0)
4124 {
4125 dest = dest_buffer;
4126 if (is_decl)
4127 {
4128 semsg(_("E1078: Cannot declare a buffer variable: %s"), name);
4129 goto theend;
4130 }
4131 }
4132 else if (STRNCMP(arg, "w:", 2) == 0)
4133 {
4134 dest = dest_window;
4135 if (is_decl)
4136 {
4137 semsg(_("E1079: Cannot declare a window variable: %s"), name);
4138 goto theend;
4139 }
4140 }
4141 else if (STRNCMP(arg, "t:", 2) == 0)
4142 {
4143 dest = dest_tab;
4144 if (is_decl)
4145 {
4146 semsg(_("E1080: Cannot declare a tab variable: %s"), name);
4147 goto theend;
4148 }
4149 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004150 else if (STRNCMP(arg, "v:", 2) == 0)
4151 {
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004152 typval_T *vtv;
4153 int di_flags;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004154
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004155 vimvaridx = find_vim_var(name + 2, &di_flags);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004156 if (vimvaridx < 0)
4157 {
4158 semsg(_(e_var_notfound), arg);
4159 goto theend;
4160 }
Bram Moolenaar5da356e2020-04-09 19:34:43 +02004161 // We use the current value of "sandbox" here, is that OK?
4162 if (var_check_ro(di_flags, name, FALSE))
4163 goto theend;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004164 dest = dest_vimvar;
Bram Moolenaara8c17702020-04-01 21:17:24 +02004165 vtv = get_vim_var_tv(vimvaridx);
4166 type = typval2type(vtv);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004167 if (is_decl)
4168 {
4169 semsg(_("E1064: Cannot declare a v: variable: %s"), name);
4170 goto theend;
4171 }
4172 }
4173 else
4174 {
4175 for (idx = 0; reserved[idx] != NULL; ++idx)
4176 if (STRCMP(reserved[idx], name) == 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004177 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004178 semsg(_("E1034: Cannot use reserved name %s"), name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004179 goto theend;
4180 }
Bram Moolenaar080457c2020-03-03 21:53:32 +01004181
4182 idx = lookup_local(arg, varlen, cctx);
4183 if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004184 {
Bram Moolenaar080457c2020-03-03 21:53:32 +01004185 if (is_decl)
4186 {
4187 semsg(_("E1017: Variable already declared: %s"), name);
4188 goto theend;
4189 }
4190 else
4191 {
4192 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4193 if (lvar->lv_const)
4194 {
4195 semsg(_("E1018: Cannot assign to a constant: %s"), name);
4196 goto theend;
4197 }
4198 }
4199 }
4200 else if (STRNCMP(arg, "s:", 2) == 0
4201 || lookup_script(arg, varlen) == OK
4202 || find_imported(arg, varlen, cctx) != NULL)
4203 {
4204 dest = dest_script;
4205 if (is_decl)
4206 {
4207 semsg(_("E1054: Variable already declared in the script: %s"),
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004208 name);
Bram Moolenaar080457c2020-03-03 21:53:32 +01004209 goto theend;
4210 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004211 }
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004212 else if (name[1] == ':' && name[2] != NUL)
4213 {
4214 semsg(_("E1082: Cannot use a namespaced variable: %s"), name);
4215 goto theend;
4216 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004217 }
4218 }
4219
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004220 if (dest != dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004221 {
4222 if (is_decl && *p == ':')
4223 {
4224 // parse optional type: "let var: type = expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02004225 if (!VIM_ISWHITE(p[1]))
4226 {
4227 semsg(_(e_white_after), ":");
4228 goto theend;
4229 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004230 p = skipwhite(p + 1);
4231 type = parse_type(&p, cctx->ctx_type_list);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004232 has_type = TRUE;
4233 }
Bram Moolenaara8c17702020-04-01 21:17:24 +02004234 else if (idx >= 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004235 {
4236 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4237 type = lvar->lv_type;
4238 }
4239 }
4240
4241 sp = p;
4242 p = skipwhite(p);
4243 op = p;
4244 oplen = assignment_len(p, &heredoc);
4245 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen])))
4246 {
4247 char_u buf[4];
4248
4249 vim_strncpy(buf, op, oplen);
4250 semsg(_(e_white_both), buf);
4251 }
4252
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004253 if (oplen == 3 && !heredoc && dest != dest_global
Bram Moolenaar4c683752020-04-05 21:38:23 +02004254 && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004255 {
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01004256 emsg(_("E1019: Can only concatenate to string"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004257 goto theend;
4258 }
4259
Bram Moolenaar080457c2020-03-03 21:53:32 +01004260 if (idx < 0 && dest == dest_local && cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004261 {
4262 if (oplen > 1 && !heredoc)
4263 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004264 // +=, /=, etc. require an existing variable
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004265 semsg(_("E1020: cannot use an operator on a new variable: %s"),
4266 name);
4267 goto theend;
4268 }
4269
4270 // new local variable
Bram Moolenaar08938ee2020-04-11 23:17:17 +02004271 if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE))
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004272 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004273 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type);
4274 if (idx < 0)
4275 goto theend;
Bram Moolenaar01b38622020-03-30 21:28:39 +02004276 new_local = TRUE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004277 }
4278
4279 if (heredoc)
4280 {
4281 list_T *l;
4282 listitem_T *li;
4283
4284 // [let] varname =<< [trim] {end}
4285 eap->getline = heredoc_getline;
4286 eap->cookie = cctx;
Bram Moolenaar6c2b7b82020-04-14 20:15:49 +02004287 l = heredoc_get(eap, op + 3, FALSE);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004288
4289 // Push each line and the create the list.
Bram Moolenaar00d253e2020-04-06 22:13:01 +02004290 FOR_ALL_LIST_ITEMS(l, li)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004291 {
4292 generate_PUSHS(cctx, li->li_tv.vval.v_string);
4293 li->li_tv.vval.v_string = NULL;
4294 }
4295 generate_NEWLIST(cctx, l->lv_len);
4296 type = &t_list_string;
4297 list_free(l);
4298 p += STRLEN(p);
4299 }
4300 else if (oplen > 0)
4301 {
Bram Moolenaara8c17702020-04-01 21:17:24 +02004302 int r;
4303 type_T *stacktype;
4304 garray_T *stack;
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004305
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004306 // for "+=", "*=", "..=" etc. first load the current value
4307 if (*op != '=')
4308 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004309 switch (dest)
4310 {
4311 case dest_option:
4312 // TODO: check the option exists
Bram Moolenaara8c17702020-04-01 21:17:24 +02004313 generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004314 break;
4315 case dest_global:
4316 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4317 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004318 case dest_buffer:
4319 generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
4320 break;
4321 case dest_window:
4322 generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type);
4323 break;
4324 case dest_tab:
4325 generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type);
4326 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004327 case dest_script:
Bram Moolenaarb35efa52020-02-26 20:15:18 +01004328 compile_load_scriptvar(cctx,
4329 name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE);
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004330 break;
4331 case dest_env:
4332 // Include $ in the name here
4333 generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
4334 break;
4335 case dest_reg:
4336 generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
4337 break;
4338 case dest_vimvar:
4339 generate_LOADV(cctx, name + 2, TRUE);
4340 break;
4341 case dest_local:
4342 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
4343 break;
4344 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004345 }
4346
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004347 // Compile the expression. Temporarily hide the new local variable
4348 // here, it is not available to this expression.
Bram Moolenaar01b38622020-03-30 21:28:39 +02004349 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004350 --cctx->ctx_locals.ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004351 instr_count = instr->ga_len;
4352 p = skipwhite(p + oplen);
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004353 r = compile_expr1(&p, cctx);
Bram Moolenaar01b38622020-03-30 21:28:39 +02004354 if (new_local)
Bram Moolenaard25ec2c2020-03-30 21:05:45 +02004355 ++cctx->ctx_locals.ga_len;
4356 if (r == FAIL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004357 goto theend;
4358
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004359 if (cctx->ctx_skip != TRUE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004360 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004361 stack = &cctx->ctx_type_stack;
4362 stacktype = stack->ga_len == 0 ? &t_void
4363 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
4364 if (idx >= 0 && (is_decl || !has_type))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004365 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004366 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
4367 if (new_local && !has_type)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004368 {
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004369 if (stacktype->tt_type == VAR_VOID)
4370 {
4371 emsg(_("E1031: Cannot use void value"));
4372 goto theend;
4373 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004374 else
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004375 {
4376 // An empty list or dict has a &t_void member, for a
4377 // variable that implies &t_any.
4378 if (stacktype == &t_list_empty)
4379 lvar->lv_type = &t_list_any;
4380 else if (stacktype == &t_dict_empty)
4381 lvar->lv_type = &t_dict_any;
4382 else
4383 lvar->lv_type = stacktype;
4384 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004385 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004386 else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
4387 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004388 }
Bram Moolenaarec5929d2020-04-07 20:53:39 +02004389 else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004390 goto theend;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004391 }
4392 }
4393 else if (cmdidx == CMD_const)
4394 {
4395 emsg(_("E1021: const requires a value"));
4396 goto theend;
4397 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004398 else if (!has_type || dest == dest_option)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004399 {
4400 emsg(_("E1022: type or initialization required"));
4401 goto theend;
4402 }
4403 else
4404 {
4405 // variables are always initialized
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004406 if (ga_grow(instr, 1) == FAIL)
4407 goto theend;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004408 switch (type->tt_type)
4409 {
4410 case VAR_BOOL:
4411 generate_PUSHBOOL(cctx, VVAL_FALSE);
4412 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004413 case VAR_FLOAT:
4414#ifdef FEAT_FLOAT
4415 generate_PUSHF(cctx, 0.0);
4416#endif
4417 break;
4418 case VAR_STRING:
4419 generate_PUSHS(cctx, NULL);
4420 break;
4421 case VAR_BLOB:
4422 generate_PUSHBLOB(cctx, NULL);
4423 break;
4424 case VAR_FUNC:
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004425 generate_PUSHFUNC(cctx, NULL, &t_func_void);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004426 break;
Bram Moolenaar04d05222020-02-06 22:06:54 +01004427 case VAR_LIST:
4428 generate_NEWLIST(cctx, 0);
4429 break;
4430 case VAR_DICT:
4431 generate_NEWDICT(cctx, 0);
4432 break;
4433 case VAR_JOB:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004434 generate_PUSHJOB(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004435 break;
4436 case VAR_CHANNEL:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01004437 generate_PUSHCHANNEL(cctx, NULL);
Bram Moolenaar04d05222020-02-06 22:06:54 +01004438 break;
4439 case VAR_NUMBER:
4440 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02004441 case VAR_ANY:
Bram Moolenaar9c8bb7c2020-04-09 21:08:09 +02004442 case VAR_PARTIAL:
Bram Moolenaar04d05222020-02-06 22:06:54 +01004443 case VAR_VOID:
Bram Moolenaare69f6d02020-04-01 22:11:01 +02004444 case VAR_SPECIAL: // cannot happen
Bram Moolenaar04d05222020-02-06 22:06:54 +01004445 generate_PUSHNR(cctx, 0);
4446 break;
4447 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004448 }
4449
4450 if (oplen > 0 && *op != '=')
4451 {
4452 type_T *expected = &t_number;
4453 garray_T *stack = &cctx->ctx_type_stack;
4454 type_T *stacktype;
4455
4456 // TODO: if type is known use float or any operation
4457
4458 if (*op == '.')
4459 expected = &t_string;
4460 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4461 if (need_type(stacktype, expected, -1, cctx) == FAIL)
4462 goto theend;
4463
4464 if (*op == '.')
4465 generate_instr_drop(cctx, ISN_CONCAT, 1);
4466 else
4467 {
4468 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1);
4469
4470 if (isn == NULL)
4471 goto theend;
4472 switch (*op)
4473 {
4474 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break;
4475 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break;
4476 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break;
4477 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break;
4478 case '%': isn->isn_arg.op.op_type = EXPR_REM; break;
4479 }
4480 }
4481 }
4482
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004483 switch (dest)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004484 {
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004485 case dest_option:
4486 generate_STOREOPT(cctx, name + 1, opt_flags);
4487 break;
4488 case dest_global:
4489 // include g: with the name, easier to execute that way
4490 generate_STORE(cctx, ISN_STOREG, 0, name);
4491 break;
Bram Moolenaard3aac292020-04-19 14:32:17 +02004492 case dest_buffer:
4493 // include b: with the name, easier to execute that way
4494 generate_STORE(cctx, ISN_STOREB, 0, name);
4495 break;
4496 case dest_window:
4497 // include w: with the name, easier to execute that way
4498 generate_STORE(cctx, ISN_STOREW, 0, name);
4499 break;
4500 case dest_tab:
4501 // include t: with the name, easier to execute that way
4502 generate_STORE(cctx, ISN_STORET, 0, name);
4503 break;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004504 case dest_env:
4505 generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
4506 break;
4507 case dest_reg:
4508 generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
4509 break;
4510 case dest_vimvar:
4511 generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
4512 break;
4513 case dest_script:
4514 {
4515 char_u *rawname = name + (name[1] == ':' ? 2 : 0);
4516 imported_T *import = NULL;
4517 int sid = current_sctx.sc_sid;
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01004518
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004519 if (name[1] != ':')
4520 {
4521 import = find_imported(name, 0, cctx);
4522 if (import != NULL)
4523 sid = import->imp_sid;
4524 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004525
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004526 idx = get_script_item_idx(sid, rawname, TRUE);
4527 // TODO: specific type
4528 if (idx < 0)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02004529 {
4530 char_u *name_s = name;
4531
4532 // Include s: in the name for store_var()
4533 if (name[1] != ':')
4534 {
4535 int len = (int)STRLEN(name) + 3;
4536
4537 name_s = alloc(len);
4538 if (name_s == NULL)
4539 name_s = name;
4540 else
4541 vim_snprintf((char *)name_s, len, "s:%s", name);
4542 }
4543 generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, &t_any);
4544 if (name_s != name)
4545 vim_free(name_s);
4546 }
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004547 else
4548 generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
4549 sid, idx, &t_any);
4550 }
4551 break;
4552 case dest_local:
4553 {
4554 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004555
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004556 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE
4557 // into ISN_STORENR
4558 if (instr->ga_len == instr_count + 1
4559 && isn->isn_type == ISN_PUSHNR)
4560 {
4561 varnumber_T val = isn->isn_arg.number;
4562 garray_T *stack = &cctx->ctx_type_stack;
4563
4564 isn->isn_type = ISN_STORENR;
Bram Moolenaara471eea2020-03-04 22:20:26 +01004565 isn->isn_arg.storenr.stnr_idx = idx;
4566 isn->isn_arg.storenr.stnr_val = val;
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +01004567 if (stack->ga_len > 0)
4568 --stack->ga_len;
4569 }
4570 else
4571 generate_STORE(cctx, ISN_STORE, idx, NULL);
4572 }
4573 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004574 }
4575 ret = p;
4576
4577theend:
4578 vim_free(name);
4579 return ret;
4580}
4581
4582/*
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004583 * Check if "name" can be "unlet".
4584 */
4585 int
4586check_vim9_unlet(char_u *name)
4587{
4588 if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
4589 {
4590 semsg(_("E1081: Cannot unlet %s"), name);
4591 return FAIL;
4592 }
4593 return OK;
4594}
4595
4596/*
4597 * Callback passed to ex_unletlock().
4598 */
4599 static int
4600compile_unlet(
4601 lval_T *lvp,
4602 char_u *name_end,
4603 exarg_T *eap,
4604 int deep UNUSED,
4605 void *coookie)
4606{
4607 cctx_T *cctx = coookie;
4608
4609 if (lvp->ll_tv == NULL)
4610 {
4611 char_u *p = lvp->ll_name;
4612 int cc = *name_end;
4613 int ret = OK;
4614
4615 // Normal name. Only supports g:, w:, t: and b: namespaces.
4616 *name_end = NUL;
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004617 if (*p == '$')
4618 ret = generate_UNLET(cctx, ISN_UNLETENV, p + 1, eap->forceit);
4619 else if (check_vim9_unlet(p) == FAIL)
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004620 ret = FAIL;
4621 else
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02004622 ret = generate_UNLET(cctx, ISN_UNLET, p, eap->forceit);
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02004623
4624 *name_end = cc;
4625 return ret;
4626 }
4627
4628 // TODO: unlet {list}[idx]
4629 // TODO: unlet {dict}[key]
4630 emsg("Sorry, :unlet not fully implemented yet");
4631 return FAIL;
4632}
4633
4634/*
4635 * compile "unlet var", "lock var" and "unlock var"
4636 * "arg" points to "var".
4637 */
4638 static char_u *
4639compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
4640{
4641 char_u *p = arg;
4642
4643 if (eap->cmdidx != CMD_unlet)
4644 {
4645 emsg("Sorry, :lock and unlock not implemented yet");
4646 return NULL;
4647 }
4648
4649 if (*p == '!')
4650 {
4651 p = skipwhite(p + 1);
4652 eap->forceit = TRUE;
4653 }
4654
4655 ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
4656 return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
4657}
4658
4659/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004660 * Compile an :import command.
4661 */
4662 static char_u *
4663compile_import(char_u *arg, cctx_T *cctx)
4664{
Bram Moolenaar5269bd22020-03-09 19:25:27 +01004665 return handle_import(arg, &cctx->ctx_imports, 0, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004666}
4667
4668/*
4669 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry".
4670 */
4671 static int
4672compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx)
4673{
4674 garray_T *instr = &cctx->ctx_instr;
4675 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T);
4676
4677 if (endlabel == NULL)
4678 return FAIL;
4679 endlabel->el_next = *el;
4680 *el = endlabel;
4681 endlabel->el_end_label = instr->ga_len;
4682
4683 generate_JUMP(cctx, when, 0);
4684 return OK;
4685}
4686
4687 static void
4688compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx)
4689{
4690 garray_T *instr = &cctx->ctx_instr;
4691
4692 while (*el != NULL)
4693 {
4694 endlabel_T *cur = (*el);
4695 isn_T *isn;
4696
4697 isn = ((isn_T *)instr->ga_data) + cur->el_end_label;
4698 isn->isn_arg.jump.jump_where = instr->ga_len;
4699 *el = cur->el_next;
4700 vim_free(cur);
4701 }
4702}
4703
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004704 static void
4705compile_free_jump_to_end(endlabel_T **el)
4706{
4707 while (*el != NULL)
4708 {
4709 endlabel_T *cur = (*el);
4710
4711 *el = cur->el_next;
4712 vim_free(cur);
4713 }
4714}
4715
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01004716/*
4717 * Create a new scope and set up the generic items.
4718 */
4719 static scope_T *
4720new_scope(cctx_T *cctx, scopetype_T type)
4721{
4722 scope_T *scope = ALLOC_CLEAR_ONE(scope_T);
4723
4724 if (scope == NULL)
4725 return NULL;
4726 scope->se_outer = cctx->ctx_scope;
4727 cctx->ctx_scope = scope;
4728 scope->se_type = type;
4729 scope->se_local_count = cctx->ctx_locals.ga_len;
4730 return scope;
4731}
4732
4733/*
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004734 * Free the current scope and go back to the outer scope.
4735 */
4736 static void
4737drop_scope(cctx_T *cctx)
4738{
4739 scope_T *scope = cctx->ctx_scope;
4740
4741 if (scope == NULL)
4742 {
4743 iemsg("calling drop_scope() without a scope");
4744 return;
4745 }
4746 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar3cca2992020-04-02 22:57:36 +02004747 switch (scope->se_type)
4748 {
4749 case IF_SCOPE:
4750 compile_free_jump_to_end(&scope->se_u.se_if.is_end_label); break;
4751 case FOR_SCOPE:
4752 compile_free_jump_to_end(&scope->se_u.se_for.fs_end_label); break;
4753 case WHILE_SCOPE:
4754 compile_free_jump_to_end(&scope->se_u.se_while.ws_end_label); break;
4755 case TRY_SCOPE:
4756 compile_free_jump_to_end(&scope->se_u.se_try.ts_end_label); break;
4757 case NO_SCOPE:
4758 case BLOCK_SCOPE:
4759 break;
4760 }
Bram Moolenaar25b70c72020-04-01 16:34:17 +02004761 vim_free(scope);
4762}
4763
4764/*
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004765 * Evaluate an expression that is a constant:
4766 * has(arg)
4767 *
4768 * Also handle:
4769 * ! in front logical NOT
4770 *
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004771 * Return FAIL if the expression is not a constant.
4772 */
4773 static int
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004774evaluate_const_expr7(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004775{
4776 typval_T argvars[2];
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004777 char_u *start_leader, *end_leader;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004778 int has_call = FALSE;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004779
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004780 /*
4781 * Skip '!' characters. They are handled later.
4782 */
4783 start_leader = *arg;
4784 while (**arg == '!')
4785 *arg = skipwhite(*arg + 1);
4786 end_leader = *arg;
4787
4788 /*
Bram Moolenaar080457c2020-03-03 21:53:32 +01004789 * Recognize only a few types of constants for now.
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004790 */
Bram Moolenaar080457c2020-03-03 21:53:32 +01004791 if (STRNCMP("true", *arg, 4) == 0 && !ASCII_ISALNUM((*arg)[4]))
4792 {
4793 tv->v_type = VAR_SPECIAL;
4794 tv->vval.v_number = VVAL_TRUE;
4795 *arg += 4;
4796 return OK;
4797 }
4798 if (STRNCMP("false", *arg, 5) == 0 && !ASCII_ISALNUM((*arg)[5]))
4799 {
4800 tv->v_type = VAR_SPECIAL;
4801 tv->vval.v_number = VVAL_FALSE;
4802 *arg += 5;
4803 return OK;
4804 }
4805
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004806 if (STRNCMP("has(", *arg, 4) == 0)
4807 {
4808 has_call = TRUE;
4809 *arg = skipwhite(*arg + 4);
4810 }
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004811
4812 if (**arg == '"')
4813 {
4814 if (get_string_tv(arg, tv, TRUE) == FAIL)
4815 return FAIL;
4816 }
4817 else if (**arg == '\'')
4818 {
4819 if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
4820 return FAIL;
4821 }
4822 else
4823 return FAIL;
4824
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004825 if (has_call)
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004826 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004827 *arg = skipwhite(*arg);
4828 if (**arg != ')')
4829 return FAIL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02004830 *arg = *arg + 1;
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004831
4832 argvars[0] = *tv;
4833 argvars[1].v_type = VAR_UNKNOWN;
4834 tv->v_type = VAR_NUMBER;
4835 tv->vval.v_number = 0;
4836 f_has(argvars, tv);
4837 clear_tv(&argvars[0]);
4838
4839 while (start_leader < end_leader)
4840 {
4841 if (*start_leader == '!')
4842 tv->vval.v_number = !tv->vval.v_number;
4843 ++start_leader;
4844 }
Bram Moolenaar7f829ca2020-01-31 22:12:41 +01004845 }
4846
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004847 return OK;
4848}
4849
Bram Moolenaar080457c2020-03-03 21:53:32 +01004850 static int
4851evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
4852{
4853 exptype_T type = EXPR_UNKNOWN;
4854 char_u *p;
4855 int len = 2;
4856 int type_is = FALSE;
4857
4858 // get the first variable
4859 if (evaluate_const_expr7(arg, cctx, tv) == FAIL)
4860 return FAIL;
4861
4862 p = skipwhite(*arg);
4863 type = get_compare_type(p, &len, &type_is);
4864
4865 /*
4866 * If there is a comparative operator, use it.
4867 */
4868 if (type != EXPR_UNKNOWN)
4869 {
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004870 typval_T tv2;
4871 char_u *s1, *s2;
4872 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4873 int n;
4874
4875 // TODO: Only string == string is supported now
4876 if (tv->v_type != VAR_STRING)
4877 return FAIL;
4878 if (type != EXPR_EQUAL)
4879 return FAIL;
4880
4881 // get the second variable
Bram Moolenaar4227c782020-04-02 16:00:04 +02004882 init_tv(&tv2);
Bram Moolenaar80c34ca2020-04-01 23:05:18 +02004883 *arg = skipwhite(p + len);
4884 if (evaluate_const_expr7(arg, cctx, &tv2) == FAIL
4885 || tv2.v_type != VAR_STRING)
4886 {
4887 clear_tv(&tv2);
4888 return FAIL;
4889 }
4890 s1 = tv_get_string_buf(tv, buf1);
4891 s2 = tv_get_string_buf(&tv2, buf2);
4892 n = STRCMP(s1, s2);
4893 clear_tv(tv);
4894 clear_tv(&tv2);
4895 tv->v_type = VAR_BOOL;
4896 tv->vval.v_number = n == 0 ? VVAL_TRUE : VVAL_FALSE;
Bram Moolenaar080457c2020-03-03 21:53:32 +01004897 }
4898
4899 return OK;
4900}
4901
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004902static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
4903
4904/*
4905 * Compile constant || or &&.
4906 */
4907 static int
4908evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
4909{
4910 char_u *p = skipwhite(*arg);
4911 int opchar = *op;
4912
4913 if (p[0] == opchar && p[1] == opchar)
4914 {
4915 int val = tv2bool(tv);
4916
4917 /*
4918 * Repeat until there is no following "||" or "&&"
4919 */
4920 while (p[0] == opchar && p[1] == opchar)
4921 {
4922 typval_T tv2;
4923
4924 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
4925 return FAIL;
4926
4927 // eval the next expression
4928 *arg = skipwhite(p + 2);
4929 tv2.v_type = VAR_UNKNOWN;
Bram Moolenaareed35712020-02-04 23:08:14 +01004930 tv2.v_lock = 0;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004931 if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
Bram Moolenaar080457c2020-03-03 21:53:32 +01004932 : evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004933 {
4934 clear_tv(&tv2);
4935 return FAIL;
4936 }
4937 if ((opchar == '&') == val)
4938 {
4939 // false || tv2 or true && tv2: use tv2
4940 clear_tv(tv);
4941 *tv = tv2;
4942 val = tv2bool(tv);
4943 }
4944 else
4945 clear_tv(&tv2);
4946 p = skipwhite(*arg);
4947 }
4948 }
4949
4950 return OK;
4951}
4952
4953/*
4954 * Evaluate an expression that is a constant: expr4 && expr4 && expr4
4955 * Return FAIL if the expression is not a constant.
4956 */
4957 static int
4958evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
4959{
4960 // evaluate the first expression
Bram Moolenaar080457c2020-03-03 21:53:32 +01004961 if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01004962 return FAIL;
4963
4964 // || and && work almost the same
4965 return evaluate_const_and_or(arg, cctx, "&&", tv);
4966}
4967
4968/*
4969 * Evaluate an expression that is a constant: expr3 || expr3 || expr3
4970 * Return FAIL if the expression is not a constant.
4971 */
4972 static int
4973evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
4974{
4975 // evaluate the first expression
4976 if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
4977 return FAIL;
4978
4979 // || and && work almost the same
4980 return evaluate_const_and_or(arg, cctx, "||", tv);
4981}
4982
4983/*
4984 * Evaluate an expression that is a constant: expr2 ? expr1 : expr1
4985 * E.g. for "has('feature')".
4986 * This does not produce error messages. "tv" should be cleared afterwards.
4987 * Return FAIL if the expression is not a constant.
4988 */
4989 static int
4990evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
4991{
4992 char_u *p;
4993
4994 // evaluate the first expression
4995 if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
4996 return FAIL;
4997
4998 p = skipwhite(*arg);
4999 if (*p == '?')
5000 {
5001 int val = tv2bool(tv);
5002 typval_T tv2;
5003
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005004 // require space before and after the ?
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005005 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5006 return FAIL;
5007
5008 // evaluate the second expression; any type is accepted
5009 clear_tv(tv);
5010 *arg = skipwhite(p + 1);
5011 if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
5012 return FAIL;
5013
5014 // Check for the ":".
5015 p = skipwhite(*arg);
5016 if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
5017 return FAIL;
5018
5019 // evaluate the third expression
5020 *arg = skipwhite(p + 1);
5021 tv2.v_type = VAR_UNKNOWN;
5022 if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
5023 {
5024 clear_tv(&tv2);
5025 return FAIL;
5026 }
5027 if (val)
5028 {
5029 // use the expr after "?"
5030 clear_tv(&tv2);
5031 }
5032 else
5033 {
5034 // use the expr after ":"
5035 clear_tv(tv);
5036 *tv = tv2;
5037 }
5038 }
5039 return OK;
5040}
5041
5042/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005043 * compile "if expr"
5044 *
5045 * "if expr" Produces instructions:
5046 * EVAL expr Push result of "expr"
5047 * JUMP_IF_FALSE end
5048 * ... body ...
5049 * end:
5050 *
5051 * "if expr | else" Produces instructions:
5052 * EVAL expr Push result of "expr"
5053 * JUMP_IF_FALSE else
5054 * ... body ...
5055 * JUMP_ALWAYS end
5056 * else:
5057 * ... body ...
5058 * end:
5059 *
5060 * "if expr1 | elseif expr2 | else" Produces instructions:
5061 * EVAL expr Push result of "expr"
5062 * JUMP_IF_FALSE elseif
5063 * ... body ...
5064 * JUMP_ALWAYS end
5065 * elseif:
5066 * EVAL expr Push result of "expr"
5067 * JUMP_IF_FALSE else
5068 * ... body ...
5069 * JUMP_ALWAYS end
5070 * else:
5071 * ... body ...
5072 * end:
5073 */
5074 static char_u *
5075compile_if(char_u *arg, cctx_T *cctx)
5076{
5077 char_u *p = arg;
5078 garray_T *instr = &cctx->ctx_instr;
5079 scope_T *scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005080 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005081
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005082 // compile "expr"; if we know it evaluates to FALSE skip the block
5083 tv.v_type = VAR_UNKNOWN;
5084 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5085 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5086 else
5087 cctx->ctx_skip = MAYBE;
5088 clear_tv(&tv);
5089 if (cctx->ctx_skip == MAYBE)
5090 {
5091 p = arg;
5092 if (compile_expr1(&p, cctx) == FAIL)
5093 return NULL;
5094 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005095
5096 scope = new_scope(cctx, IF_SCOPE);
5097 if (scope == NULL)
5098 return NULL;
5099
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005100 if (cctx->ctx_skip == MAYBE)
5101 {
5102 // "where" is set when ":elseif", "else" or ":endif" is found
5103 scope->se_u.se_if.is_if_label = instr->ga_len;
5104 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5105 }
5106 else
5107 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005108
5109 return p;
5110}
5111
5112 static char_u *
5113compile_elseif(char_u *arg, cctx_T *cctx)
5114{
5115 char_u *p = arg;
5116 garray_T *instr = &cctx->ctx_instr;
5117 isn_T *isn;
5118 scope_T *scope = cctx->ctx_scope;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005119 typval_T tv;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005120
5121 if (scope == NULL || scope->se_type != IF_SCOPE)
5122 {
5123 emsg(_(e_elseif_without_if));
5124 return NULL;
5125 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005126 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005127
Bram Moolenaar158906c2020-02-06 20:39:45 +01005128 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005129 {
5130 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005131 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005132 return NULL;
5133 // previous "if" or "elseif" jumps here
5134 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5135 isn->isn_arg.jump.jump_where = instr->ga_len;
5136 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005137
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005138 // compile "expr"; if we know it evaluates to FALSE skip the block
5139 tv.v_type = VAR_UNKNOWN;
5140 if (evaluate_const_expr1(&p, cctx, &tv) == OK)
5141 cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
5142 else
5143 cctx->ctx_skip = MAYBE;
5144 clear_tv(&tv);
5145 if (cctx->ctx_skip == MAYBE)
5146 {
5147 p = arg;
5148 if (compile_expr1(&p, cctx) == FAIL)
5149 return NULL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005150
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005151 // "where" is set when ":elseif", "else" or ":endif" is found
5152 scope->se_u.se_if.is_if_label = instr->ga_len;
5153 generate_JUMP(cctx, JUMP_IF_FALSE, 0);
5154 }
5155 else
5156 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005157
5158 return p;
5159}
5160
5161 static char_u *
5162compile_else(char_u *arg, cctx_T *cctx)
5163{
5164 char_u *p = arg;
5165 garray_T *instr = &cctx->ctx_instr;
5166 isn_T *isn;
5167 scope_T *scope = cctx->ctx_scope;
5168
5169 if (scope == NULL || scope->se_type != IF_SCOPE)
5170 {
5171 emsg(_(e_else_without_if));
5172 return NULL;
5173 }
Bram Moolenaar20431c92020-03-20 18:39:46 +01005174 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005175
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005176 // jump from previous block to the end, unless the else block is empty
5177 if (cctx->ctx_skip == MAYBE)
5178 {
5179 if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005180 JUMP_ALWAYS, cctx) == FAIL)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005181 return NULL;
5182 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005183
Bram Moolenaar158906c2020-02-06 20:39:45 +01005184 if (cctx->ctx_skip == MAYBE)
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005185 {
5186 if (scope->se_u.se_if.is_if_label >= 0)
5187 {
5188 // previous "if" or "elseif" jumps here
5189 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5190 isn->isn_arg.jump.jump_where = instr->ga_len;
Bram Moolenaar158906c2020-02-06 20:39:45 +01005191 scope->se_u.se_if.is_if_label = -1;
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005192 }
5193 }
5194
5195 if (cctx->ctx_skip != MAYBE)
5196 cctx->ctx_skip = !cctx->ctx_skip;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005197
5198 return p;
5199}
5200
5201 static char_u *
5202compile_endif(char_u *arg, cctx_T *cctx)
5203{
5204 scope_T *scope = cctx->ctx_scope;
5205 ifscope_T *ifscope;
5206 garray_T *instr = &cctx->ctx_instr;
5207 isn_T *isn;
5208
5209 if (scope == NULL || scope->se_type != IF_SCOPE)
5210 {
5211 emsg(_(e_endif_without_if));
5212 return NULL;
5213 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005214 ifscope = &scope->se_u.se_if;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005215 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005216
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005217 if (scope->se_u.se_if.is_if_label >= 0)
5218 {
5219 // previous "if" or "elseif" jumps here
5220 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
5221 isn->isn_arg.jump.jump_where = instr->ga_len;
5222 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005223 // Fill in the "end" label in jumps at the end of the blocks.
5224 compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
Bram Moolenaara259d8d2020-01-31 20:10:50 +01005225 cctx->ctx_skip = FALSE;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005226
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005227 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005228 return arg;
5229}
5230
5231/*
5232 * compile "for var in expr"
5233 *
5234 * Produces instructions:
5235 * PUSHNR -1
5236 * STORE loop-idx Set index to -1
5237 * EVAL expr Push result of "expr"
5238 * top: FOR loop-idx, end Increment index, use list on bottom of stack
5239 * - if beyond end, jump to "end"
5240 * - otherwise get item from list and push it
5241 * STORE var Store item in "var"
5242 * ... body ...
5243 * JUMP top Jump back to repeat
5244 * end: DROP Drop the result of "expr"
5245 *
5246 */
5247 static char_u *
5248compile_for(char_u *arg, cctx_T *cctx)
5249{
5250 char_u *p;
5251 size_t varlen;
5252 garray_T *instr = &cctx->ctx_instr;
5253 garray_T *stack = &cctx->ctx_type_stack;
5254 scope_T *scope;
5255 int loop_idx; // index of loop iteration variable
5256 int var_idx; // index of "var"
5257 type_T *vartype;
5258
5259 // TODO: list of variables: "for [key, value] in dict"
5260 // parse "var"
5261 for (p = arg; eval_isnamec1(*p); ++p)
5262 ;
5263 varlen = p - arg;
5264 var_idx = lookup_local(arg, varlen, cctx);
5265 if (var_idx >= 0)
5266 {
5267 semsg(_("E1023: variable already defined: %s"), arg);
5268 return NULL;
5269 }
5270
5271 // consume "in"
5272 p = skipwhite(p);
5273 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2]))
5274 {
5275 emsg(_(e_missing_in));
5276 return NULL;
5277 }
5278 p = skipwhite(p + 2);
5279
5280
5281 scope = new_scope(cctx, FOR_SCOPE);
5282 if (scope == NULL)
5283 return NULL;
5284
5285 // Reserve a variable to store the loop iteration counter.
5286 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number);
5287 if (loop_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005288 {
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005289 // only happens when out of memory
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005290 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005291 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005292 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005293
5294 // Reserve a variable to store "var"
5295 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any);
5296 if (var_idx < 0)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005297 {
5298 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005299 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005300 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005301
5302 generate_STORENR(cctx, loop_idx, -1);
5303
5304 // compile "expr", it remains on the stack until "endfor"
5305 arg = p;
5306 if (compile_expr1(&arg, cctx) == FAIL)
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005307 {
5308 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005309 return NULL;
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005310 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005311
5312 // now we know the type of "var"
5313 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5314 if (vartype->tt_type != VAR_LIST)
5315 {
5316 emsg(_("E1024: need a List to iterate over"));
Bram Moolenaar25b70c72020-04-01 16:34:17 +02005317 drop_scope(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005318 return NULL;
5319 }
Bram Moolenaar4c683752020-04-05 21:38:23 +02005320 if (vartype->tt_member->tt_type != VAR_ANY)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005321 {
5322 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx;
5323
5324 lvar->lv_type = vartype->tt_member;
5325 }
5326
5327 // "for_end" is set when ":endfor" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005328 scope->se_u.se_for.fs_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005329
5330 generate_FOR(cctx, loop_idx);
5331 generate_STORE(cctx, ISN_STORE, var_idx, NULL);
5332
5333 return arg;
5334}
5335
5336/*
5337 * compile "endfor"
5338 */
5339 static char_u *
5340compile_endfor(char_u *arg, cctx_T *cctx)
5341{
5342 garray_T *instr = &cctx->ctx_instr;
5343 scope_T *scope = cctx->ctx_scope;
5344 forscope_T *forscope;
5345 isn_T *isn;
5346
5347 if (scope == NULL || scope->se_type != FOR_SCOPE)
5348 {
5349 emsg(_(e_for));
5350 return NULL;
5351 }
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005352 forscope = &scope->se_u.se_for;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005353 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005354 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005355
5356 // At end of ":for" scope jump back to the FOR instruction.
5357 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
5358
5359 // Fill in the "end" label in the FOR statement so it can jump here
5360 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
5361 isn->isn_arg.forloop.for_end = instr->ga_len;
5362
5363 // Fill in the "end" label any BREAK statements
5364 compile_fill_jump_to_end(&forscope->fs_end_label, cctx);
5365
5366 // Below the ":for" scope drop the "expr" list from the stack.
5367 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL)
5368 return NULL;
5369
5370 vim_free(scope);
5371
5372 return arg;
5373}
5374
5375/*
5376 * compile "while expr"
5377 *
5378 * Produces instructions:
5379 * top: EVAL expr Push result of "expr"
5380 * JUMP_IF_FALSE end jump if false
5381 * ... body ...
5382 * JUMP top Jump back to repeat
5383 * end:
5384 *
5385 */
5386 static char_u *
5387compile_while(char_u *arg, cctx_T *cctx)
5388{
5389 char_u *p = arg;
5390 garray_T *instr = &cctx->ctx_instr;
5391 scope_T *scope;
5392
5393 scope = new_scope(cctx, WHILE_SCOPE);
5394 if (scope == NULL)
5395 return NULL;
5396
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005397 scope->se_u.se_while.ws_top_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005398
5399 // compile "expr"
5400 if (compile_expr1(&p, cctx) == FAIL)
5401 return NULL;
5402
5403 // "while_end" is set when ":endwhile" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005404 if (compile_jump_to_end(&scope->se_u.se_while.ws_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005405 JUMP_IF_FALSE, cctx) == FAIL)
5406 return FAIL;
5407
5408 return p;
5409}
5410
5411/*
5412 * compile "endwhile"
5413 */
5414 static char_u *
5415compile_endwhile(char_u *arg, cctx_T *cctx)
5416{
5417 scope_T *scope = cctx->ctx_scope;
5418
5419 if (scope == NULL || scope->se_type != WHILE_SCOPE)
5420 {
5421 emsg(_(e_while));
5422 return NULL;
5423 }
5424 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005425 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005426
5427 // At end of ":for" scope jump back to the FOR instruction.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005428 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005429
5430 // Fill in the "end" label in the WHILE statement so it can jump here.
5431 // And in any jumps for ":break"
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005432 compile_fill_jump_to_end(&scope->se_u.se_while.ws_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005433
5434 vim_free(scope);
5435
5436 return arg;
5437}
5438
5439/*
5440 * compile "continue"
5441 */
5442 static char_u *
5443compile_continue(char_u *arg, cctx_T *cctx)
5444{
5445 scope_T *scope = cctx->ctx_scope;
5446
5447 for (;;)
5448 {
5449 if (scope == NULL)
5450 {
5451 emsg(_(e_continue));
5452 return NULL;
5453 }
5454 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5455 break;
5456 scope = scope->se_outer;
5457 }
5458
5459 // Jump back to the FOR or WHILE instruction.
5460 generate_JUMP(cctx, JUMP_ALWAYS,
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005461 scope->se_type == FOR_SCOPE ? scope->se_u.se_for.fs_top_label
5462 : scope->se_u.se_while.ws_top_label);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005463 return arg;
5464}
5465
5466/*
5467 * compile "break"
5468 */
5469 static char_u *
5470compile_break(char_u *arg, cctx_T *cctx)
5471{
5472 scope_T *scope = cctx->ctx_scope;
5473 endlabel_T **el;
5474
5475 for (;;)
5476 {
5477 if (scope == NULL)
5478 {
5479 emsg(_(e_break));
5480 return NULL;
5481 }
5482 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
5483 break;
5484 scope = scope->se_outer;
5485 }
5486
5487 // Jump to the end of the FOR or WHILE loop.
5488 if (scope->se_type == FOR_SCOPE)
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005489 el = &scope->se_u.se_for.fs_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005490 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005491 el = &scope->se_u.se_while.ws_end_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005492 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL)
5493 return FAIL;
5494
5495 return arg;
5496}
5497
5498/*
5499 * compile "{" start of block
5500 */
5501 static char_u *
5502compile_block(char_u *arg, cctx_T *cctx)
5503{
5504 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5505 return NULL;
5506 return skipwhite(arg + 1);
5507}
5508
5509/*
5510 * compile end of block: drop one scope
5511 */
5512 static void
5513compile_endblock(cctx_T *cctx)
5514{
5515 scope_T *scope = cctx->ctx_scope;
5516
5517 cctx->ctx_scope = scope->se_outer;
Bram Moolenaar20431c92020-03-20 18:39:46 +01005518 unwind_locals(cctx, scope->se_local_count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005519 vim_free(scope);
5520}
5521
5522/*
5523 * compile "try"
5524 * Creates a new scope for the try-endtry, pointing to the first catch and
5525 * finally.
5526 * Creates another scope for the "try" block itself.
5527 * TRY instruction sets up exception handling at runtime.
5528 *
5529 * "try"
5530 * TRY -> catch1, -> finally push trystack entry
5531 * ... try block
5532 * "throw {exception}"
5533 * EVAL {exception}
5534 * THROW create exception
5535 * ... try block
5536 * " catch {expr}"
5537 * JUMP -> finally
5538 * catch1: PUSH exeception
5539 * EVAL {expr}
5540 * MATCH
5541 * JUMP nomatch -> catch2
5542 * CATCH remove exception
5543 * ... catch block
5544 * " catch"
5545 * JUMP -> finally
5546 * catch2: CATCH remove exception
5547 * ... catch block
5548 * " finally"
5549 * finally:
5550 * ... finally block
5551 * " endtry"
5552 * ENDTRY pop trystack entry, may rethrow
5553 */
5554 static char_u *
5555compile_try(char_u *arg, cctx_T *cctx)
5556{
5557 garray_T *instr = &cctx->ctx_instr;
5558 scope_T *try_scope;
5559 scope_T *scope;
5560
5561 // scope that holds the jumps that go to catch/finally/endtry
5562 try_scope = new_scope(cctx, TRY_SCOPE);
5563 if (try_scope == NULL)
5564 return NULL;
5565
5566 // "catch" is set when the first ":catch" is found.
5567 // "finally" is set when ":finally" or ":endtry" is found
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005568 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005569 if (generate_instr(cctx, ISN_TRY) == NULL)
5570 return NULL;
5571
5572 // scope for the try block itself
5573 scope = new_scope(cctx, BLOCK_SCOPE);
5574 if (scope == NULL)
5575 return NULL;
5576
5577 return arg;
5578}
5579
5580/*
5581 * compile "catch {expr}"
5582 */
5583 static char_u *
5584compile_catch(char_u *arg, cctx_T *cctx UNUSED)
5585{
5586 scope_T *scope = cctx->ctx_scope;
5587 garray_T *instr = &cctx->ctx_instr;
5588 char_u *p;
5589 isn_T *isn;
5590
5591 // end block scope from :try or :catch
5592 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5593 compile_endblock(cctx);
5594 scope = cctx->ctx_scope;
5595
5596 // Error if not in a :try scope
5597 if (scope == NULL || scope->se_type != TRY_SCOPE)
5598 {
5599 emsg(_(e_catch));
5600 return NULL;
5601 }
5602
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005603 if (scope->se_u.se_try.ts_caught_all)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005604 {
5605 emsg(_("E1033: catch unreachable after catch-all"));
5606 return NULL;
5607 }
5608
5609 // Jump from end of previous block to :finally or :endtry
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005610 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005611 JUMP_ALWAYS, cctx) == FAIL)
5612 return NULL;
5613
5614 // End :try or :catch scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005615 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005616 if (isn->isn_arg.try.try_catch == 0)
5617 isn->isn_arg.try.try_catch = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005618 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005619 {
5620 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005621 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005622 isn->isn_arg.jump.jump_where = instr->ga_len;
5623 }
5624
5625 p = skipwhite(arg);
Bram Moolenaar7a092242020-04-16 22:10:49 +02005626 if (ends_excmd2(arg, p))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005627 {
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005628 scope->se_u.se_try.ts_caught_all = TRUE;
5629 scope->se_u.se_try.ts_catch_label = 0;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005630 }
5631 else
5632 {
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005633 char_u *end;
5634 char_u *pat;
5635 char_u *tofree = NULL;
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005636 int dropped = 0;
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005637 int len;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005638
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005639 // Push v:exception, push {expr} and MATCH
5640 generate_instr_type(cctx, ISN_PUSHEXC, &t_string);
5641
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005642 end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005643 if (*end != *p)
5644 {
5645 semsg(_("E1067: Separator mismatch: %s"), p);
5646 vim_free(tofree);
5647 return FAIL;
5648 }
5649 if (tofree == NULL)
Bram Moolenaar3dd64602020-02-13 20:31:28 +01005650 len = (int)(end - (p + 1));
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005651 else
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005652 len = (int)(end - tofree);
5653 pat = vim_strnsave(tofree == NULL ? p + 1 : tofree, len);
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005654 vim_free(tofree);
Bram Moolenaare8c4abb2020-04-02 21:13:25 +02005655 p += len + 2 + dropped;
Bram Moolenaarff80cb62020-02-05 22:10:05 +01005656 if (pat == NULL)
5657 return FAIL;
5658 if (generate_PUSHS(cctx, pat) == FAIL)
5659 return FAIL;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005660
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005661 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL)
5662 return NULL;
5663
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005664 scope->se_u.se_try.ts_catch_label = instr->ga_len;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005665 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
5666 return NULL;
5667 }
5668
5669 if (generate_instr(cctx, ISN_CATCH) == NULL)
5670 return NULL;
5671
5672 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
5673 return NULL;
5674 return p;
5675}
5676
5677 static char_u *
5678compile_finally(char_u *arg, cctx_T *cctx)
5679{
5680 scope_T *scope = cctx->ctx_scope;
5681 garray_T *instr = &cctx->ctx_instr;
5682 isn_T *isn;
5683
5684 // end block scope from :try or :catch
5685 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5686 compile_endblock(cctx);
5687 scope = cctx->ctx_scope;
5688
5689 // Error if not in a :try scope
5690 if (scope == NULL || scope->se_type != TRY_SCOPE)
5691 {
5692 emsg(_(e_finally));
5693 return NULL;
5694 }
5695
5696 // End :catch or :finally scope: set value in ISN_TRY instruction
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005697 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005698 if (isn->isn_arg.try.try_finally != 0)
5699 {
5700 emsg(_(e_finally_dup));
5701 return NULL;
5702 }
5703
5704 // Fill in the "end" label in jumps at the end of the blocks.
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005705 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005706
Bram Moolenaar585fea72020-04-02 22:33:21 +02005707 isn->isn_arg.try.try_finally = instr->ga_len;
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005708 if (scope->se_u.se_try.ts_catch_label != 0)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005709 {
5710 // Previous catch without match jumps here
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005711 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005712 isn->isn_arg.jump.jump_where = instr->ga_len;
5713 }
5714
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005715 // TODO: set index in ts_finally_label jumps
5716
5717 return arg;
5718}
5719
5720 static char_u *
5721compile_endtry(char_u *arg, cctx_T *cctx)
5722{
5723 scope_T *scope = cctx->ctx_scope;
5724 garray_T *instr = &cctx->ctx_instr;
5725 isn_T *isn;
5726
5727 // end block scope from :catch or :finally
5728 if (scope != NULL && scope->se_type == BLOCK_SCOPE)
5729 compile_endblock(cctx);
5730 scope = cctx->ctx_scope;
5731
5732 // Error if not in a :try scope
5733 if (scope == NULL || scope->se_type != TRY_SCOPE)
5734 {
5735 if (scope == NULL)
5736 emsg(_(e_no_endtry));
5737 else if (scope->se_type == WHILE_SCOPE)
5738 emsg(_(e_endwhile));
Bram Moolenaar5b18c242020-01-28 22:30:32 +01005739 else if (scope->se_type == FOR_SCOPE)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005740 emsg(_(e_endfor));
5741 else
5742 emsg(_(e_endif));
5743 return NULL;
5744 }
5745
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005746 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005747 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0)
5748 {
5749 emsg(_("E1032: missing :catch or :finally"));
5750 return NULL;
5751 }
5752
5753 // Fill in the "end" label in jumps at the end of the blocks, if not done
5754 // by ":finally".
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01005755 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005756
5757 // End :catch or :finally scope: set value in ISN_TRY instruction
5758 if (isn->isn_arg.try.try_finally == 0)
5759 isn->isn_arg.try.try_finally = instr->ga_len;
5760 compile_endblock(cctx);
5761
5762 if (generate_instr(cctx, ISN_ENDTRY) == NULL)
5763 return NULL;
5764 return arg;
5765}
5766
5767/*
5768 * compile "throw {expr}"
5769 */
5770 static char_u *
5771compile_throw(char_u *arg, cctx_T *cctx UNUSED)
5772{
5773 char_u *p = skipwhite(arg);
5774
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005775 if (compile_expr1(&p, cctx) == FAIL)
5776 return NULL;
5777 if (may_generate_2STRING(-1, cctx) == FAIL)
5778 return NULL;
5779 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL)
5780 return NULL;
5781
5782 return p;
5783}
5784
5785/*
5786 * compile "echo expr"
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005787 * compile "echomsg expr"
5788 * compile "echoerr expr"
Bram Moolenaarad39c092020-02-26 18:23:43 +01005789 * compile "execute expr"
5790 */
5791 static char_u *
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005792compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
Bram Moolenaarad39c092020-02-26 18:23:43 +01005793{
5794 char_u *p = arg;
5795 int count = 0;
5796
5797 for (;;)
5798 {
5799 if (compile_expr1(&p, cctx) == FAIL)
5800 return NULL;
5801 ++count;
5802 p = skipwhite(p);
5803 if (ends_excmd(*p))
5804 break;
5805 }
5806
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02005807 if (cmdidx == CMD_echo || cmdidx == CMD_echon)
5808 generate_ECHO(cctx, cmdidx == CMD_echo, count);
5809 else if (cmdidx == CMD_execute)
5810 generate_MULT_EXPR(cctx, ISN_EXECUTE, count);
5811 else if (cmdidx == CMD_echomsg)
5812 generate_MULT_EXPR(cctx, ISN_ECHOMSG, count);
5813 else
5814 generate_MULT_EXPR(cctx, ISN_ECHOERR, count);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005815 return p;
5816}
5817
5818/*
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005819 * A command that is not compiled, execute with legacy code.
5820 */
5821 static char_u *
5822compile_exec(char_u *line, exarg_T *eap, cctx_T *cctx)
5823{
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005824 char_u *p;
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005825 int has_expr = FALSE;
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005826
5827 if (cctx->ctx_skip == TRUE)
5828 goto theend;
5829
Bram Moolenaar7d41aa82020-04-26 14:29:56 +02005830 if (eap->cmdidx >= 0 && eap->cmdidx < CMD_SIZE)
5831 has_expr = (excmd_get_argt(eap->cmdidx) & (EX_XFILE | EX_EXPAND));
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005832 if (eap->cmdidx == CMD_syntax && STRNCMP(eap->arg, "include ", 8) == 0)
5833 {
5834 // expand filename in "syntax include [@group] filename"
5835 has_expr = TRUE;
5836 eap->arg = skipwhite(eap->arg + 7);
5837 if (*eap->arg == '@')
5838 eap->arg = skiptowhite(eap->arg);
5839 }
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005840
Bram Moolenaar6378c4f2020-04-26 13:50:41 +02005841 if (has_expr && (p = (char_u *)strstr((char *)eap->arg, "`=")) != NULL)
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02005842 {
5843 int count = 0;
5844 char_u *start = skipwhite(line);
5845
5846 // :cmd xxx`=expr1`yyy`=expr2`zzz
5847 // PUSHS ":cmd xxx"
5848 // eval expr1
5849 // PUSHS "yyy"
5850 // eval expr2
5851 // PUSHS "zzz"
5852 // EXECCONCAT 5
5853 for (;;)
5854 {
5855 if (p > start)
5856 {
5857 generate_PUSHS(cctx, vim_strnsave(start, (int)(p - start)));
5858 ++count;
5859 }
5860 p += 2;
5861 if (compile_expr1(&p, cctx) == FAIL)
5862 return NULL;
5863 may_generate_2STRING(-1, cctx);
5864 ++count;
5865 p = skipwhite(p);
5866 if (*p != '`')
5867 {
5868 emsg(_("E1083: missing backtick"));
5869 return NULL;
5870 }
5871 start = p + 1;
5872
5873 p = (char_u *)strstr((char *)start, "`=");
5874 if (p == NULL)
5875 {
5876 if (*skipwhite(start) != NUL)
5877 {
5878 generate_PUSHS(cctx, vim_strsave(start));
5879 ++count;
5880 }
5881 break;
5882 }
5883 }
5884 generate_EXECCONCAT(cctx, count);
5885 }
5886 else
5887 generate_EXEC(cctx, line);
5888
5889theend:
5890 return (char_u *)"";
5891}
5892
5893/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005894 * After ex_function() has collected all the function lines: parse and compile
5895 * the lines into instructions.
5896 * Adds the function to "def_functions".
5897 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
5898 * return statement (used for lambda).
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005899 * This can be used recursively through compile_lambda(), which may reallocate
5900 * "def_functions".
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005901 */
5902 void
5903compile_def_function(ufunc_T *ufunc, int set_return_type)
5904{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005905 char_u *line = NULL;
5906 char_u *p;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005907 char *errormsg = NULL; // error message
5908 int had_return = FALSE;
5909 cctx_T cctx;
5910 garray_T *instr;
5911 int called_emsg_before = called_emsg;
5912 int ret = FAIL;
5913 sctx_T save_current_sctx = current_sctx;
Bram Moolenaar42a480b2020-02-29 23:23:47 +01005914 int emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005915
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005916 {
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005917 dfunc_T *dfunc; // may be invalidated by compile_lambda()
Bram Moolenaar20431c92020-03-20 18:39:46 +01005918
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005919 if (ufunc->uf_dfunc_idx >= 0)
5920 {
5921 // Redefining a function that was compiled before.
5922 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
5923
5924 // Free old instructions.
5925 delete_def_function_contents(dfunc);
5926 }
5927 else
5928 {
5929 // Add the function to "def_functions".
5930 if (ga_grow(&def_functions, 1) == FAIL)
5931 return;
5932 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
Bram Moolenaara80faa82020-04-12 19:37:17 +02005933 CLEAR_POINTER(dfunc);
Bram Moolenaar05afcee2020-03-31 23:32:31 +02005934 dfunc->df_idx = def_functions.ga_len;
5935 ufunc->uf_dfunc_idx = dfunc->df_idx;
5936 dfunc->df_ufunc = ufunc;
5937 ++def_functions.ga_len;
5938 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005939 }
5940
Bram Moolenaara80faa82020-04-12 19:37:17 +02005941 CLEAR_FIELD(cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005942 cctx.ctx_ufunc = ufunc;
5943 cctx.ctx_lnum = -1;
5944 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10);
5945 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50);
5946 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10);
5947 cctx.ctx_type_list = &ufunc->uf_type_list;
5948 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50);
5949 instr = &cctx.ctx_instr;
5950
5951 // Most modern script version.
5952 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
5953
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005954 if (ufunc->uf_def_args.ga_len > 0)
5955 {
5956 int count = ufunc->uf_def_args.ga_len;
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005957 int first_def_arg = ufunc->uf_args.ga_len - count;
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005958 int i;
5959 char_u *arg;
5960 int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
5961
5962 // Produce instructions for the default values of optional arguments.
5963 // Store the instruction index in uf_def_arg_idx[] so that we know
5964 // where to start when the function is called, depending on the number
5965 // of arguments.
5966 ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
5967 if (ufunc->uf_def_arg_idx == NULL)
5968 goto erret;
5969 for (i = 0; i < count; ++i)
5970 {
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005971 garray_T *stack = &cctx.ctx_type_stack;
5972 type_T *val_type;
5973 int arg_idx = first_def_arg + i;
5974
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005975 ufunc->uf_def_arg_idx[i] = instr->ga_len;
5976 arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
Bram Moolenaar49cf7cc2020-04-07 22:45:00 +02005977 if (compile_expr1(&arg, &cctx) == FAIL)
5978 goto erret;
5979
5980 // If no type specified use the type of the default value.
5981 // Otherwise check that the default value type matches the
5982 // specified type.
5983 val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
5984 if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
5985 ufunc->uf_arg_types[arg_idx] = val_type;
5986 else if (check_type(ufunc->uf_arg_types[i], val_type, FALSE)
5987 == FAIL)
5988 {
5989 arg_type_mismatch(ufunc->uf_arg_types[arg_idx], val_type,
5990 arg_idx + 1);
5991 goto erret;
5992 }
5993
5994 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005995 goto erret;
5996 }
Bram Moolenaar170fcfc2020-02-06 17:51:35 +01005997 ufunc->uf_def_arg_idx[count] = instr->ga_len;
5998 }
5999
6000 /*
6001 * Loop over all the lines of the function and generate instructions.
6002 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006003 for (;;)
6004 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006005 exarg_T ea;
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006006 int is_ex_command = FALSE;
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006007
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006008 // Bail out on the first error to avoid a flood of errors and report
6009 // the right line number when inside try/catch.
6010 if (emsg_before != called_emsg)
6011 goto erret;
6012
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006013 if (line != NULL && *line == '|')
6014 // the line continues after a '|'
6015 ++line;
Bram Moolenaar7a092242020-04-16 22:10:49 +02006016 else if (line != NULL && *line != NUL
6017 && !(*line == '#' && (line == cctx.ctx_line_start
6018 || VIM_ISWHITE(line[-1]))))
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006019 {
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006020 semsg(_("E488: Trailing characters: %s"), line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006021 goto erret;
6022 }
6023 else
6024 {
Bram Moolenaar4fdae992020-04-12 16:38:57 +02006025 line = next_line_from_context(&cctx);
6026 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len)
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006027 // beyond the last line
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006028 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006029 }
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006030 emsg_before = called_emsg;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006031
6032 had_return = FALSE;
Bram Moolenaara80faa82020-04-12 19:37:17 +02006033 CLEAR_FIELD(ea);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006034 ea.cmdlinep = &line;
6035 ea.cmd = skipwhite(line);
6036
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006037 // Some things can be recognized by the first character.
6038 switch (*ea.cmd)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006039 {
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006040 case '#':
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006041 // "#" starts a comment, but "#{" does not.
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006042 if (ea.cmd[1] != '{')
6043 {
6044 line = (char_u *)"";
6045 continue;
6046 }
6047 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006048
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006049 case '}':
6050 {
6051 // "}" ends a block scope
6052 scopetype_T stype = cctx.ctx_scope == NULL
6053 ? NO_SCOPE : cctx.ctx_scope->se_type;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006054
Bram Moolenaarcb711ab2020-04-16 13:00:29 +02006055 if (stype == BLOCK_SCOPE)
6056 {
6057 compile_endblock(&cctx);
6058 line = ea.cmd;
6059 }
6060 else
6061 {
6062 emsg(_("E1025: using } outside of a block scope"));
6063 goto erret;
6064 }
6065 if (line != NULL)
6066 line = skipwhite(ea.cmd + 1);
6067 continue;
6068 }
6069
6070 case '{':
6071 // "{" starts a block scope
6072 // "{'a': 1}->func() is something else
6073 if (ends_excmd(*skipwhite(ea.cmd + 1)))
6074 {
6075 line = compile_block(ea.cmd, &cctx);
6076 continue;
6077 }
6078 break;
6079
6080 case ':':
6081 is_ex_command = TRUE;
6082 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006083 }
6084
6085 /*
6086 * COMMAND MODIFIERS
6087 */
6088 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
6089 {
6090 if (errormsg != NULL)
6091 goto erret;
6092 // empty line or comment
6093 line = (char_u *)"";
6094 continue;
6095 }
6096
6097 // Skip ":call" to get to the function name.
6098 if (checkforcmd(&ea.cmd, "call", 3))
6099 ea.cmd = skipwhite(ea.cmd);
6100
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006101 if (!is_ex_command)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006102 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006103 // Assuming the command starts with a variable or function name,
6104 // find what follows. Also "&opt = val", "$ENV = val" and "@r =
6105 // val".
6106 p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
6107 ? ea.cmd + 1 : ea.cmd;
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006108 p = to_name_end(p, TRUE);
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006109 if (p > ea.cmd && *p != NUL)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006110 {
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006111 int oplen;
6112 int heredoc;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006113
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006114 oplen = assignment_len(skipwhite(p), &heredoc);
6115 if (oplen > 0)
6116 {
6117 // Recognize an assignment if we recognize the variable
6118 // name:
6119 // "g:var = expr"
Bram Moolenaar5381c7a2020-03-02 22:53:32 +01006120 // "local = expr" where "local" is a local var.
6121 // "script = expr" where "script" is a script-local var.
6122 // "import = expr" where "import" is an imported var
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006123 // "&opt = expr"
6124 // "$ENV = expr"
6125 // "@r = expr"
6126 if (*ea.cmd == '&'
6127 || *ea.cmd == '$'
6128 || *ea.cmd == '@'
6129 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
6130 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
6131 || lookup_script(ea.cmd, p - ea.cmd) == OK
6132 || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
6133 {
6134 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
6135 if (line == NULL)
6136 goto erret;
6137 continue;
6138 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006139 }
6140 }
6141 }
6142
6143 /*
6144 * COMMAND after range
6145 */
6146 ea.cmd = skip_range(ea.cmd, NULL);
Bram Moolenaar5b1c8fe2020-02-21 18:42:43 +01006147 p = find_ex_command(&ea, NULL, is_ex_command ? NULL : lookup_local,
6148 &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006149
6150 if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
6151 {
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006152 if (cctx.ctx_skip == TRUE)
6153 {
6154 line += STRLEN(line);
6155 continue;
6156 }
6157
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006158 // Expression or function call.
6159 if (ea.cmdidx == CMD_eval)
6160 {
6161 p = ea.cmd;
6162 if (compile_expr1(&p, &cctx) == FAIL)
6163 goto erret;
6164
6165 // drop the return value
6166 generate_instr_drop(&cctx, ISN_DROP, 1);
6167 line = p;
6168 continue;
6169 }
Bram Moolenaar585fea72020-04-02 22:33:21 +02006170 // CMD_let cannot happen, compile_assignment() above is used
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006171 iemsg("Command from find_ex_command() not handled");
6172 goto erret;
6173 }
6174
6175 p = skipwhite(p);
6176
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006177 if (cctx.ctx_skip == TRUE
6178 && ea.cmdidx != CMD_elseif
6179 && ea.cmdidx != CMD_else
6180 && ea.cmdidx != CMD_endif)
6181 {
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006182 line = (char_u *)"";
Bram Moolenaara259d8d2020-01-31 20:10:50 +01006183 continue;
6184 }
6185
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006186 switch (ea.cmdidx)
6187 {
6188 case CMD_def:
6189 case CMD_function:
6190 // TODO: Nested function
6191 emsg("Nested function not implemented yet");
6192 goto erret;
6193
6194 case CMD_return:
6195 line = compile_return(p, set_return_type, &cctx);
6196 had_return = TRUE;
6197 break;
6198
6199 case CMD_let:
6200 case CMD_const:
6201 line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
6202 break;
6203
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006204 case CMD_unlet:
6205 case CMD_unlockvar:
6206 case CMD_lockvar:
6207 line = compile_unletlock(p, &ea, &cctx);
6208 break;
6209
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006210 case CMD_import:
6211 line = compile_import(p, &cctx);
6212 break;
6213
6214 case CMD_if:
6215 line = compile_if(p, &cctx);
6216 break;
6217 case CMD_elseif:
6218 line = compile_elseif(p, &cctx);
6219 break;
6220 case CMD_else:
6221 line = compile_else(p, &cctx);
6222 break;
6223 case CMD_endif:
6224 line = compile_endif(p, &cctx);
6225 break;
6226
6227 case CMD_while:
6228 line = compile_while(p, &cctx);
6229 break;
6230 case CMD_endwhile:
6231 line = compile_endwhile(p, &cctx);
6232 break;
6233
6234 case CMD_for:
6235 line = compile_for(p, &cctx);
6236 break;
6237 case CMD_endfor:
6238 line = compile_endfor(p, &cctx);
6239 break;
6240 case CMD_continue:
6241 line = compile_continue(p, &cctx);
6242 break;
6243 case CMD_break:
6244 line = compile_break(p, &cctx);
6245 break;
6246
6247 case CMD_try:
6248 line = compile_try(p, &cctx);
6249 break;
6250 case CMD_catch:
6251 line = compile_catch(p, &cctx);
6252 break;
6253 case CMD_finally:
6254 line = compile_finally(p, &cctx);
6255 break;
6256 case CMD_endtry:
6257 line = compile_endtry(p, &cctx);
6258 break;
6259 case CMD_throw:
6260 line = compile_throw(p, &cctx);
6261 break;
6262
6263 case CMD_echo:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006264 case CMD_echon:
Bram Moolenaarad39c092020-02-26 18:23:43 +01006265 case CMD_execute:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006266 case CMD_echomsg:
6267 case CMD_echoerr:
6268 line = compile_mult_expr(p, ea.cmdidx, &cctx);
Bram Moolenaarad39c092020-02-26 18:23:43 +01006269 break;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006270
6271 default:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006272 // TODO: other commands with an expression argument
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006273 // Not recognized, execute with do_cmdline_cmd().
6274 ea.arg = p;
6275 line = compile_exec(line, &ea, &cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006276 break;
6277 }
6278 if (line == NULL)
6279 goto erret;
Bram Moolenaar585fea72020-04-02 22:33:21 +02006280 line = skipwhite(line);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006281
6282 if (cctx.ctx_type_stack.ga_len < 0)
6283 {
6284 iemsg("Type stack underflow");
6285 goto erret;
6286 }
6287 }
6288
6289 if (cctx.ctx_scope != NULL)
6290 {
6291 if (cctx.ctx_scope->se_type == IF_SCOPE)
6292 emsg(_(e_endif));
6293 else if (cctx.ctx_scope->se_type == WHILE_SCOPE)
6294 emsg(_(e_endwhile));
6295 else if (cctx.ctx_scope->se_type == FOR_SCOPE)
6296 emsg(_(e_endfor));
6297 else
6298 emsg(_("E1026: Missing }"));
6299 goto erret;
6300 }
6301
6302 if (!had_return)
6303 {
6304 if (ufunc->uf_ret_type->tt_type != VAR_VOID)
6305 {
6306 emsg(_("E1027: Missing return statement"));
6307 goto erret;
6308 }
6309
6310 // Return zero if there is no return at the end.
6311 generate_PUSHNR(&cctx, 0);
6312 generate_instr(&cctx, ISN_RETURN);
6313 }
6314
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006315 {
6316 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6317 + ufunc->uf_dfunc_idx;
6318 dfunc->df_deleted = FALSE;
6319 dfunc->df_instr = instr->ga_data;
6320 dfunc->df_instr_count = instr->ga_len;
6321 dfunc->df_varcount = cctx.ctx_max_local;
6322 }
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006323
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006324 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006325 int varargs = ufunc->uf_va_name != NULL;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006326 int argcount = ufunc->uf_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006327
6328 // Create a type for the function, with the return type and any
6329 // argument types.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006330 // A vararg is included in uf_args.ga_len but not in uf_arg_types.
6331 // The type is included in "tt_args".
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006332 if (argcount > 0 || varargs)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006333 {
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006334 ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
6335 argcount, &ufunc->uf_type_list);
6336 // Add argument types to the function type.
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006337 if (func_type_add_arg_types(ufunc->uf_func_type,
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006338 argcount + varargs,
6339 &ufunc->uf_type_list) == FAIL)
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006340 {
6341 ret = FAIL;
6342 goto erret;
6343 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006344 ufunc->uf_func_type->tt_argcount = argcount + varargs;
6345 ufunc->uf_func_type->tt_min_argcount =
6346 argcount - ufunc->uf_def_args.ga_len;
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006347 if (ufunc->uf_arg_types == NULL)
6348 {
6349 int i;
6350
6351 // lambda does not have argument types.
6352 for (i = 0; i < argcount; ++i)
6353 ufunc->uf_func_type->tt_args[i] = &t_any;
6354 }
6355 else
6356 mch_memmove(ufunc->uf_func_type->tt_args,
6357 ufunc->uf_arg_types, sizeof(type_T *) * argcount);
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006358 if (varargs)
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006359 {
Bram Moolenaar5d905c22020-04-05 18:20:45 +02006360 ufunc->uf_func_type->tt_args[argcount] =
6361 ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006362 ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
6363 }
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006364 }
Bram Moolenaar1378fbc2020-04-11 20:50:33 +02006365 else
6366 // No arguments, can use a predefined type.
6367 ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
6368 argcount, &ufunc->uf_type_list);
6369
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +02006370 }
6371
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006372 ret = OK;
6373
6374erret:
6375 if (ret == FAIL)
6376 {
Bram Moolenaar20431c92020-03-20 18:39:46 +01006377 int idx;
Bram Moolenaar05afcee2020-03-31 23:32:31 +02006378 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6379 + ufunc->uf_dfunc_idx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006380
6381 for (idx = 0; idx < instr->ga_len; ++idx)
6382 delete_instr(((isn_T *)instr->ga_data) + idx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006383 ga_clear(instr);
Bram Moolenaar20431c92020-03-20 18:39:46 +01006384
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006385 ufunc->uf_dfunc_idx = -1;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006386 if (!dfunc->df_deleted)
6387 --def_functions.ga_len;
6388
Bram Moolenaar3cca2992020-04-02 22:57:36 +02006389 while (cctx.ctx_scope != NULL)
6390 drop_scope(&cctx);
6391
Bram Moolenaar20431c92020-03-20 18:39:46 +01006392 // Don't execute this function body.
6393 ga_clear_strings(&ufunc->uf_lines);
6394
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006395 if (errormsg != NULL)
6396 emsg(errormsg);
6397 else if (called_emsg == called_emsg_before)
Bram Moolenaardf2ecdd2020-02-16 15:03:48 +01006398 emsg(_("E1028: compile_def_function failed"));
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006399 }
6400
6401 current_sctx = save_current_sctx;
Bram Moolenaar20431c92020-03-20 18:39:46 +01006402 free_imported(&cctx);
6403 free_local(&cctx);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006404 ga_clear(&cctx.ctx_type_stack);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006405}
6406
6407/*
6408 * Delete an instruction, free what it contains.
6409 */
Bram Moolenaar20431c92020-03-20 18:39:46 +01006410 void
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006411delete_instr(isn_T *isn)
6412{
6413 switch (isn->isn_type)
6414 {
6415 case ISN_EXEC:
6416 case ISN_LOADENV:
6417 case ISN_LOADG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006418 case ISN_LOADB:
6419 case ISN_LOADW:
6420 case ISN_LOADT:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006421 case ISN_LOADOPT:
6422 case ISN_MEMBER:
6423 case ISN_PUSHEXC:
6424 case ISN_PUSHS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006425 case ISN_STOREENV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006426 case ISN_STOREG:
Bram Moolenaard3aac292020-04-19 14:32:17 +02006427 case ISN_STOREB:
6428 case ISN_STOREW:
6429 case ISN_STORET:
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006430 case ISN_PUSHFUNC:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006431 vim_free(isn->isn_arg.string);
6432 break;
6433
6434 case ISN_LOADS:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006435 case ISN_STORES:
6436 vim_free(isn->isn_arg.loadstore.ls_name);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006437 break;
6438
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006439 case ISN_UNLET:
Bram Moolenaar7bdaea62020-04-19 18:27:26 +02006440 case ISN_UNLETENV:
Bram Moolenaard72c1bf2020-04-19 16:28:59 +02006441 vim_free(isn->isn_arg.unlet.ul_name);
6442 break;
6443
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006444 case ISN_STOREOPT:
6445 vim_free(isn->isn_arg.storeopt.so_name);
6446 break;
6447
6448 case ISN_PUSHBLOB: // push blob isn_arg.blob
6449 blob_unref(isn->isn_arg.blob);
6450 break;
6451
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006452 case ISN_PUSHJOB:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006453#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006454 job_unref(isn->isn_arg.job);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006455#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006456 break;
6457
6458 case ISN_PUSHCHANNEL:
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006459#ifdef FEAT_JOB_CHANNEL
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006460 channel_unref(isn->isn_arg.channel);
Bram Moolenaarf4f190d2020-03-01 13:01:16 +01006461#endif
Bram Moolenaar42a480b2020-02-29 23:23:47 +01006462 break;
6463
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006464 case ISN_UCALL:
6465 vim_free(isn->isn_arg.ufunc.cuf_name);
6466 break;
6467
6468 case ISN_2BOOL:
6469 case ISN_2STRING:
6470 case ISN_ADDBLOB:
6471 case ISN_ADDLIST:
6472 case ISN_BCALL:
6473 case ISN_CATCH:
6474 case ISN_CHECKNR:
6475 case ISN_CHECKTYPE:
6476 case ISN_COMPAREANY:
6477 case ISN_COMPAREBLOB:
6478 case ISN_COMPAREBOOL:
6479 case ISN_COMPAREDICT:
6480 case ISN_COMPAREFLOAT:
6481 case ISN_COMPAREFUNC:
6482 case ISN_COMPARELIST:
6483 case ISN_COMPARENR:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006484 case ISN_COMPARESPECIAL:
6485 case ISN_COMPARESTRING:
6486 case ISN_CONCAT:
6487 case ISN_DCALL:
6488 case ISN_DROP:
6489 case ISN_ECHO:
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02006490 case ISN_ECHOERR:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006491 case ISN_ECHOMSG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006492 case ISN_ENDTRY:
Bram Moolenaarcfe435d2020-04-25 20:02:55 +02006493 case ISN_EXECCONCAT:
6494 case ISN_EXECUTE:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006495 case ISN_FOR:
6496 case ISN_FUNCREF:
6497 case ISN_INDEX:
6498 case ISN_JUMP:
6499 case ISN_LOAD:
6500 case ISN_LOADSCRIPT:
6501 case ISN_LOADREG:
6502 case ISN_LOADV:
6503 case ISN_NEGATENR:
6504 case ISN_NEWDICT:
6505 case ISN_NEWLIST:
6506 case ISN_OPNR:
6507 case ISN_OPFLOAT:
6508 case ISN_OPANY:
6509 case ISN_PCALL:
Bram Moolenaarbd5da372020-03-31 23:13:10 +02006510 case ISN_PCALL_END:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006511 case ISN_PUSHF:
6512 case ISN_PUSHNR:
6513 case ISN_PUSHBOOL:
6514 case ISN_PUSHSPEC:
6515 case ISN_RETURN:
6516 case ISN_STORE:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006517 case ISN_STOREV:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006518 case ISN_STORENR:
Bram Moolenaarb283a8a2020-02-02 22:24:04 +01006519 case ISN_STOREREG:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006520 case ISN_STORESCRIPT:
6521 case ISN_THROW:
6522 case ISN_TRY:
6523 // nothing allocated
6524 break;
6525 }
6526}
6527
6528/*
Bram Moolenaar20431c92020-03-20 18:39:46 +01006529 * Free all instructions for "dfunc".
6530 */
6531 static void
6532delete_def_function_contents(dfunc_T *dfunc)
6533{
6534 int idx;
6535
6536 ga_clear(&dfunc->df_def_args_isn);
6537
6538 if (dfunc->df_instr != NULL)
6539 {
6540 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6541 delete_instr(dfunc->df_instr + idx);
6542 VIM_CLEAR(dfunc->df_instr);
6543 }
6544
6545 dfunc->df_deleted = TRUE;
6546}
6547
6548/*
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006549 * When a user function is deleted, delete any associated def function.
6550 */
6551 void
6552delete_def_function(ufunc_T *ufunc)
6553{
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006554 if (ufunc->uf_dfunc_idx >= 0)
6555 {
6556 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
6557 + ufunc->uf_dfunc_idx;
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006558
Bram Moolenaar20431c92020-03-20 18:39:46 +01006559 delete_def_function_contents(dfunc);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006560 }
6561}
6562
6563#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar20431c92020-03-20 18:39:46 +01006564/*
6565 * Free all functions defined with ":def".
6566 */
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006567 void
6568free_def_functions(void)
6569{
Bram Moolenaar20431c92020-03-20 18:39:46 +01006570 int idx;
6571
6572 for (idx = 0; idx < def_functions.ga_len; ++idx)
6573 {
6574 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
6575
6576 delete_def_function_contents(dfunc);
6577 }
6578
6579 ga_clear(&def_functions);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01006580}
6581#endif
6582
6583
6584#endif // FEAT_EVAL